From 1947fef35ccfd11d520d812174baa62559fc6608 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Sun, 25 Feb 2024 03:40:11 -0800 Subject: [PATCH 001/361] Fix InteropModuleRegistryTest Summary: Fix CI build for InteropModuleRegistryTest changelog: [internal] internal Reviewed By: bvanderhoof Differential Revision: D54166759 fbshipit-source-id: 277c0a34dd4689eff8ef99afaf147efdfd36caa4 --- .../facebook/react/bridge/interop/InteropModuleRegistryTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/interop/InteropModuleRegistryTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/interop/InteropModuleRegistryTest.kt index 97fa6ee9e0aba3..e2fc44363dff99 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/interop/InteropModuleRegistryTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/interop/InteropModuleRegistryTest.kt @@ -10,6 +10,7 @@ package com.facebook.react.bridge.interop +import com.facebook.react.common.annotations.UnstableReactNativeAPI import com.facebook.react.config.ReactFeatureFlags import com.facebook.react.modules.core.JSTimers import com.facebook.react.uimanager.events.RCTEventEmitter From 12f2c3cd2bbf186afe1b4052ebf377d8030c7a73 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Sun, 25 Feb 2024 03:40:11 -0800 Subject: [PATCH 002/361] Fix Build of RNLog in CI Summary: Fix Build of RNLog in CI changelog: [internal] internal Reviewed By: bvanderhoof Differential Revision: D54167011 fbshipit-source-id: 7e1ea21860b479e9fe00df5951fe266f2e342eda --- .../java/com/facebook/react/util/RNLog.kt | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/util/RNLog.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/util/RNLog.kt index aa746249e391e5..481ed8969c13fe 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/util/RNLog.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/util/RNLog.kt @@ -13,14 +13,14 @@ import com.facebook.react.bridge.ReactContext import com.facebook.react.common.ReactConstants /** Logging wrapper for FLog with LogBox support. */ -object RNLog { +public object RNLog { - const val MINIMUM_LEVEL_FOR_UI = Log.WARN - const val LOG = Log.VERBOSE - const val TRACE = Log.DEBUG - const val ADVICE = Log.INFO - const val WARN = Log.WARN - const val ERROR = Log.ERROR + public const val MINIMUM_LEVEL_FOR_UI: Int = Log.WARN + public const val LOG: Int = Log.VERBOSE + public const val TRACE: Int = Log.DEBUG + public const val ADVICE: Int = Log.INFO + public const val WARN: Int = Log.WARN + public const val ERROR: Int = Log.ERROR /** * Log a log level message tagged as React Native to the console. @@ -28,7 +28,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun l(message: String) { + public fun l(message: String) { FLog.i(ReactConstants.TAG, message) } @@ -38,7 +38,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun t(message: String) { + public fun t(message: String) { FLog.i(ReactConstants.TAG, message) } @@ -49,7 +49,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun a(message: String) { + public fun a(message: String) { FLog.w(ReactConstants.TAG, "(ADVICE)$message") } @@ -60,7 +60,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun w(context: ReactContext?, message: String) { + public fun w(context: ReactContext?, message: String) { logInternal(context, message, WARN) FLog.w(ReactConstants.TAG, message) } @@ -72,7 +72,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun e(context: ReactContext?, message: String) { + public fun e(context: ReactContext?, message: String) { logInternal(context, message, ERROR) FLog.e(ReactConstants.TAG, message) } @@ -84,7 +84,7 @@ object RNLog { * @param message The message to log. */ @JvmStatic - fun e(message: String) { + public fun e(message: String) { FLog.e(ReactConstants.TAG, message) } From 0f3018d6af3f013e441d92fa4621ce332a1d3583 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 26 Feb 2024 05:33:18 -0800 Subject: [PATCH 003/361] Update debugger-frontend from 12a45e0...9ceb0ad Summary: Changelog: [Internal] Resyncs `react-native/debugger-frontend` from GitHub - see `rn-chrome-devtools-frontend` [changelog](https://github.com/facebookexperimental/rn-chrome-devtools-frontend/compare/12a45e0628384aa80075493354159ef5d91b2698...9ceb0ade8033ec165bbfbd41c08ac1fcd9f89a46 ). Reviewed By: huntie Differential Revision: D54107317 fbshipit-source-id: 59e670d107e4c0f30900b11df2ad423004e05997 --- packages/debugger-frontend/BUILD_INFO | 4 ++-- .../dist/third-party/front_end/core/sdk/sdk.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/debugger-frontend/BUILD_INFO b/packages/debugger-frontend/BUILD_INFO index ccaa289b9792be..d9f552896e3971 100644 --- a/packages/debugger-frontend/BUILD_INFO +++ b/packages/debugger-frontend/BUILD_INFO @@ -1,5 +1,5 @@ -@generated SignedSource<> -Git revision: 12a45e0628384aa80075493354159ef5d91b2698 +@generated SignedSource<<80b609f93e8535a704728e4ec9472a94>> +Git revision: 9ceb0ade8033ec165bbfbd41c08ac1fcd9f89a46 Built with --nohooks: false Is local checkout: false Remote URL: https://github.com/facebookexperimental/rn-chrome-devtools-frontend diff --git a/packages/debugger-frontend/dist/third-party/front_end/core/sdk/sdk.js b/packages/debugger-frontend/dist/third-party/front_end/core/sdk/sdk.js index ddecfcd892b878..581c33ed4f4494 100644 --- a/packages/debugger-frontend/dist/third-party/front_end/core/sdk/sdk.js +++ b/packages/debugger-frontend/dist/third-party/front_end/core/sdk/sdk.js @@ -1 +1 @@ -import*as e from"../common/common.js";import*as t from"../platform/platform.js";import{assertNotNullOrUndefined as n}from"../platform/platform.js";import*as r from"../../models/text_utils/text_utils.js";import*as s from"../i18n/i18n.js";import*as i from"../host/host.js";import*as a from"../protocol_client/protocol_client.js";import*as o from"../root/root.js";import*as l from"../../models/trace/trace.js";const d=new Map;class c extends e.ObjectWrapper.ObjectWrapper{#e;constructor(e){super(),this.#e=e}target(){return this.#e}async preSuspendModel(e){}async suspendModel(e){}async resumeModel(){}async postResumeModel(){}dispose(){}static register(e,t){if(t.early&&!t.autostart)throw new Error(`Error registering model ${e.name}: early models must be autostarted.`);d.set(e,t)}static get registeredModels(){return d}}var h=Object.freeze({__proto__:null,SDKModel:c});const u=[{longhands:["animation-delay-start","animation-delay-end"],name:"-alternative-animation-delay"},{longhands:["animation-duration","animation-timing-function","animation-delay-start","animation-delay-end","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name","animation-timeline","animation-range-start","animation-range-end"],name:"-alternative-animation-with-delay-start-end"},{longhands:["animation-duration","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name","animation-timeline","animation-range-start","animation-range-end"],name:"-alternative-animation-with-timeline"},{inherited:!0,longhands:["white-space-collapse","text-wrap"],name:"-alternative-white-space"},{inherited:!0,name:"-webkit-border-horizontal-spacing"},{name:"-webkit-border-image"},{inherited:!0,name:"-webkit-border-vertical-spacing"},{keywords:["stretch","start","center","end","baseline"],name:"-webkit-box-align"},{keywords:["slice","clone"],name:"-webkit-box-decoration-break"},{inherited:!0,keywords:["normal","reverse"],name:"-webkit-box-direction"},{name:"-webkit-box-flex"},{name:"-webkit-box-ordinal-group"},{keywords:["horizontal","vertical"],name:"-webkit-box-orient"},{keywords:["start","center","end","justify"],name:"-webkit-box-pack"},{name:"-webkit-box-reflect"},{longhands:["break-after"],name:"-webkit-column-break-after"},{longhands:["break-before"],name:"-webkit-column-break-before"},{longhands:["break-inside"],name:"-webkit-column-break-inside"},{inherited:!0,name:"-webkit-font-smoothing"},{inherited:!0,name:"-webkit-highlight"},{inherited:!0,keywords:["auto","loose","normal","strict","after-white-space","anywhere"],name:"-webkit-line-break"},{name:"-webkit-line-clamp"},{inherited:!0,name:"-webkit-locale"},{longhands:["-webkit-mask-image","-webkit-mask-position-x","-webkit-mask-position-y","-webkit-mask-size","-webkit-mask-repeat-x","-webkit-mask-repeat-y","-webkit-mask-origin","-webkit-mask-clip"],name:"-webkit-mask"},{longhands:["-webkit-mask-box-image-source","-webkit-mask-box-image-slice","-webkit-mask-box-image-width","-webkit-mask-box-image-outset","-webkit-mask-box-image-repeat"],name:"-webkit-mask-box-image"},{name:"-webkit-mask-box-image-outset"},{name:"-webkit-mask-box-image-repeat"},{name:"-webkit-mask-box-image-slice"},{name:"-webkit-mask-box-image-source"},{name:"-webkit-mask-box-image-width"},{name:"-webkit-mask-clip"},{name:"-webkit-mask-composite"},{name:"-webkit-mask-image"},{name:"-webkit-mask-origin"},{longhands:["-webkit-mask-position-x","-webkit-mask-position-y"],name:"-webkit-mask-position"},{name:"-webkit-mask-position-x"},{name:"-webkit-mask-position-y"},{longhands:["-webkit-mask-repeat-x","-webkit-mask-repeat-y"],name:"-webkit-mask-repeat"},{name:"-webkit-mask-repeat-x"},{name:"-webkit-mask-repeat-y"},{name:"-webkit-mask-size"},{name:"-webkit-perspective-origin-x"},{name:"-webkit-perspective-origin-y"},{inherited:!0,keywords:["economy","exact"],name:"-webkit-print-color-adjust"},{inherited:!0,keywords:["logical","visual"],name:"-webkit-rtl-ordering"},{inherited:!0,keywords:["before","after"],name:"-webkit-ruby-position"},{inherited:!0,name:"-webkit-tap-highlight-color"},{inherited:!0,name:"-webkit-text-combine"},{inherited:!0,name:"-webkit-text-decorations-in-effect"},{inherited:!0,name:"-webkit-text-fill-color"},{inherited:!0,name:"-webkit-text-orientation"},{inherited:!0,keywords:["none","disc","circle","square"],name:"-webkit-text-security"},{inherited:!0,longhands:["-webkit-text-stroke-width","-webkit-text-stroke-color"],name:"-webkit-text-stroke"},{inherited:!0,name:"-webkit-text-stroke-color"},{inherited:!0,name:"-webkit-text-stroke-width"},{name:"-webkit-transform-origin-x"},{name:"-webkit-transform-origin-y"},{name:"-webkit-transform-origin-z"},{keywords:["auto","none","element"],name:"-webkit-user-drag"},{inherited:!0,keywords:["read-only","read-write","read-write-plaintext-only"],name:"-webkit-user-modify"},{inherited:!0,name:"-webkit-writing-mode"},{inherited:!0,keywords:["auto","currentcolor"],name:"accent-color"},{name:"additive-symbols"},{name:"align-content"},{name:"align-items"},{name:"align-self"},{keywords:["auto","baseline","alphabetic","ideographic","middle","central","mathematical","before-edge","text-before-edge","after-edge","text-after-edge","hanging"],name:"alignment-baseline"},{name:"all"},{keywords:["none"],name:"anchor-default"},{keywords:["none"],name:"anchor-name"},{keywords:["none"],name:"anchor-scroll"},{longhands:["animation-duration","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name"],name:"animation"},{keywords:["replace","add","accumulate"],name:"animation-composition"},{name:"animation-delay"},{name:"animation-delay-end"},{name:"animation-delay-start"},{keywords:["normal","reverse","alternate","alternate-reverse"],name:"animation-direction"},{name:"animation-duration"},{keywords:["none","forwards","backwards","both"],name:"animation-fill-mode"},{keywords:["infinite"],name:"animation-iteration-count"},{keywords:["none"],name:"animation-name"},{keywords:["running","paused"],name:"animation-play-state"},{longhands:["animation-range-start","animation-range-end"],name:"animation-range"},{name:"animation-range-end"},{name:"animation-range-start"},{keywords:["none","auto"],name:"animation-timeline"},{keywords:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"],name:"animation-timing-function"},{keywords:["none","drag","no-drag"],name:"app-region"},{name:"appearance"},{name:"ascent-override"},{keywords:["auto"],name:"aspect-ratio"},{keywords:["none"],name:"backdrop-filter"},{keywords:["visible","hidden"],name:"backface-visibility"},{longhands:["background-image","background-position-x","background-position-y","background-size","background-repeat-x","background-repeat-y","background-attachment","background-origin","background-clip","background-color"],name:"background"},{keywords:["scroll","fixed","local"],name:"background-attachment"},{keywords:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],name:"background-blend-mode"},{keywords:["border-box","padding-box","content-box"],name:"background-clip"},{keywords:["currentcolor"],name:"background-color"},{keywords:["auto","none"],name:"background-image"},{keywords:["border-box","padding-box","content-box"],name:"background-origin"},{longhands:["background-position-x","background-position-y"],name:"background-position"},{name:"background-position-x"},{name:"background-position-y"},{longhands:["background-repeat-x","background-repeat-y"],name:"background-repeat"},{name:"background-repeat-x"},{name:"background-repeat-y"},{keywords:["auto","cover","contain"],name:"background-size"},{name:"base-palette"},{keywords:["baseline","sub","super"],name:"baseline-shift"},{keywords:["auto","first","last"],name:"baseline-source"},{keywords:["auto"],name:"block-size"},{longhands:["border-top-color","border-top-style","border-top-width","border-right-color","border-right-style","border-right-width","border-bottom-color","border-bottom-style","border-bottom-width","border-left-color","border-left-style","border-left-width","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],name:"border"},{longhands:["border-block-start-color","border-block-start-style","border-block-start-width","border-block-end-color","border-block-end-style","border-block-end-width"],name:"border-block"},{longhands:["border-block-start-color","border-block-end-color"],name:"border-block-color"},{longhands:["border-block-end-width","border-block-end-style","border-block-end-color"],name:"border-block-end"},{name:"border-block-end-color"},{name:"border-block-end-style"},{name:"border-block-end-width"},{longhands:["border-block-start-width","border-block-start-style","border-block-start-color"],name:"border-block-start"},{name:"border-block-start-color"},{name:"border-block-start-style"},{name:"border-block-start-width"},{longhands:["border-block-start-style","border-block-end-style"],name:"border-block-style"},{longhands:["border-block-start-width","border-block-end-width"],name:"border-block-width"},{longhands:["border-bottom-width","border-bottom-style","border-bottom-color"],name:"border-bottom"},{keywords:["currentcolor"],name:"border-bottom-color"},{name:"border-bottom-left-radius"},{name:"border-bottom-right-radius"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-bottom-style"},{keywords:["thin","medium","thick"],name:"border-bottom-width"},{inherited:!0,keywords:["separate","collapse"],name:"border-collapse"},{longhands:["border-top-color","border-right-color","border-bottom-color","border-left-color"],name:"border-color"},{name:"border-end-end-radius"},{name:"border-end-start-radius"},{longhands:["border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],name:"border-image"},{name:"border-image-outset"},{keywords:["stretch","repeat","round","space"],name:"border-image-repeat"},{name:"border-image-slice"},{keywords:["none"],name:"border-image-source"},{keywords:["auto"],name:"border-image-width"},{longhands:["border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-end-color","border-inline-end-style","border-inline-end-width"],name:"border-inline"},{longhands:["border-inline-start-color","border-inline-end-color"],name:"border-inline-color"},{longhands:["border-inline-end-width","border-inline-end-style","border-inline-end-color"],name:"border-inline-end"},{name:"border-inline-end-color"},{name:"border-inline-end-style"},{name:"border-inline-end-width"},{longhands:["border-inline-start-width","border-inline-start-style","border-inline-start-color"],name:"border-inline-start"},{name:"border-inline-start-color"},{name:"border-inline-start-style"},{name:"border-inline-start-width"},{longhands:["border-inline-start-style","border-inline-end-style"],name:"border-inline-style"},{longhands:["border-inline-start-width","border-inline-end-width"],name:"border-inline-width"},{longhands:["border-left-width","border-left-style","border-left-color"],name:"border-left"},{keywords:["currentcolor"],name:"border-left-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-left-style"},{keywords:["thin","medium","thick"],name:"border-left-width"},{longhands:["border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius"],name:"border-radius"},{longhands:["border-right-width","border-right-style","border-right-color"],name:"border-right"},{keywords:["currentcolor"],name:"border-right-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-right-style"},{keywords:["thin","medium","thick"],name:"border-right-width"},{inherited:!0,longhands:["-webkit-border-horizontal-spacing","-webkit-border-vertical-spacing"],name:"border-spacing"},{name:"border-start-end-radius"},{name:"border-start-start-radius"},{keywords:["none"],longhands:["border-top-style","border-right-style","border-bottom-style","border-left-style"],name:"border-style"},{longhands:["border-top-width","border-top-style","border-top-color"],name:"border-top"},{keywords:["currentcolor"],name:"border-top-color"},{name:"border-top-left-radius"},{name:"border-top-right-radius"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-top-style"},{keywords:["thin","medium","thick"],name:"border-top-width"},{longhands:["border-top-width","border-right-width","border-bottom-width","border-left-width"],name:"border-width"},{keywords:["auto"],name:"bottom"},{keywords:["none"],name:"box-shadow"},{keywords:["content-box","border-box"],name:"box-sizing"},{keywords:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"],name:"break-after"},{keywords:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"],name:"break-before"},{keywords:["auto","avoid","avoid-column","avoid-page"],name:"break-inside"},{keywords:["auto","dynamic","static"],name:"buffered-rendering"},{inherited:!0,keywords:["top","bottom"],name:"caption-side"},{inherited:!0,keywords:["auto","currentcolor"],name:"caret-color"},{keywords:["none","left","right","both","inline-start","inline-end"],name:"clear"},{keywords:["auto"],name:"clip"},{keywords:["none"],name:"clip-path"},{inherited:!0,keywords:["nonzero","evenodd"],name:"clip-rule"},{inherited:!0,keywords:["currentcolor"],name:"color"},{inherited:!0,keywords:["auto","srgb","linearrgb"],name:"color-interpolation"},{inherited:!0,keywords:["auto","srgb","linearrgb"],name:"color-interpolation-filters"},{inherited:!0,keywords:["auto","optimizespeed","optimizequality"],name:"color-rendering"},{inherited:!0,name:"color-scheme"},{keywords:["auto"],name:"column-count"},{keywords:["balance","auto"],name:"column-fill"},{keywords:["normal"],name:"column-gap"},{longhands:["column-rule-width","column-rule-style","column-rule-color"],name:"column-rule"},{keywords:["currentcolor"],name:"column-rule-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"column-rule-style"},{keywords:["thin","medium","thick"],name:"column-rule-width"},{keywords:["none","all"],name:"column-span"},{keywords:["auto"],name:"column-width"},{longhands:["column-width","column-count"],name:"columns"},{keywords:["none","strict","content","size","layout","style","paint","inline-size","block-size"],name:"contain"},{name:"contain-intrinsic-block-size"},{keywords:["auto","none"],name:"contain-intrinsic-height"},{name:"contain-intrinsic-inline-size"},{longhands:["contain-intrinsic-width","contain-intrinsic-height"],name:"contain-intrinsic-size"},{keywords:["auto","none"],name:"contain-intrinsic-width"},{longhands:["container-name","container-type"],name:"container"},{keywords:["none"],name:"container-name"},{keywords:["normal","inline-size","size","sticky"],name:"container-type"},{name:"content"},{keywords:["visible","auto","hidden"],name:"content-visibility"},{keywords:["none"],name:"counter-increment"},{keywords:["none"],name:"counter-reset"},{keywords:["none"],name:"counter-set"},{inherited:!0,keywords:["auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize","s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","col-resize","row-resize","all-scroll","zoom-in","zoom-out","grab","grabbing"],name:"cursor"},{name:"cx"},{name:"cy"},{keywords:["none"],name:"d"},{name:"descent-override"},{inherited:!0,keywords:["ltr","rtl"],name:"direction"},{keywords:["inline","block","list-item","inline-block","table","inline-table","table-row-group","table-header-group","table-footer-group","table-row","table-column-group","table-column","table-cell","table-caption","-webkit-box","-webkit-inline-box","flex","inline-flex","grid","inline-grid","contents","flow-root","none","flow","math"],name:"display"},{inherited:!0,keywords:["auto","alphabetic","ideographic","middle","central","mathematical","hanging","use-script","no-change","reset-size","text-after-edge","text-before-edge"],name:"dominant-baseline"},{inherited:!0,keywords:["show","hide"],name:"empty-cells"},{name:"fallback"},{inherited:!0,name:"fill"},{inherited:!0,name:"fill-opacity"},{inherited:!0,keywords:["nonzero","evenodd"],name:"fill-rule"},{keywords:["none"],name:"filter"},{longhands:["flex-grow","flex-shrink","flex-basis"],name:"flex"},{keywords:["auto","fit-content","min-content","max-content","content"],name:"flex-basis"},{keywords:["row","row-reverse","column","column-reverse"],name:"flex-direction"},{longhands:["flex-direction","flex-wrap"],name:"flex-flow"},{name:"flex-grow"},{name:"flex-shrink"},{keywords:["nowrap","wrap","wrap-reverse"],name:"flex-wrap"},{keywords:["none","left","right","inline-start","inline-end"],name:"float"},{keywords:["currentcolor"],name:"flood-color"},{name:"flood-opacity"},{inherited:!0,longhands:["font-style","font-variant-ligatures","font-variant-caps","font-variant-numeric","font-variant-east-asian","font-variant-alternates","font-variant-position","font-weight","font-stretch","font-size","line-height","font-family","font-optical-sizing","font-size-adjust","font-kerning","font-feature-settings","font-variation-settings"],name:"font"},{name:"font-display"},{inherited:!0,name:"font-family"},{inherited:!0,keywords:["normal"],name:"font-feature-settings"},{inherited:!0,keywords:["auto","normal","none"],name:"font-kerning"},{inherited:!0,keywords:["auto","none"],name:"font-optical-sizing"},{inherited:!0,keywords:["normal","light","dark"],name:"font-palette"},{inherited:!0,keywords:["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large","larger","smaller","-webkit-xxx-large"],name:"font-size"},{inherited:!0,keywords:["none","ex-height","cap-height","ch-width","ic-width"],name:"font-size-adjust"},{inherited:!0,keywords:["normal","ultra-condensed","extra-condensed","condensed","semi-condensed","semi-expanded","expanded","extra-expanded","ultra-expanded"],name:"font-stretch"},{inherited:!0,keywords:["normal","italic","oblique"],name:"font-style"},{inherited:!0,longhands:["font-synthesis-weight","font-synthesis-style","font-synthesis-small-caps"],name:"font-synthesis"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-small-caps"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-style"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-weight"},{inherited:!0,longhands:["font-variant-ligatures","font-variant-caps","font-variant-alternates","font-variant-numeric","font-variant-east-asian","font-variant-position"],name:"font-variant"},{inherited:!0,keywords:["normal"],name:"font-variant-alternates"},{inherited:!0,keywords:["normal","small-caps","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps"],name:"font-variant-caps"},{inherited:!0,keywords:["normal","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"],name:"font-variant-east-asian"},{inherited:!0,keywords:["normal","none","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual"],name:"font-variant-ligatures"},{inherited:!0,keywords:["normal","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero"],name:"font-variant-numeric"},{inherited:!0,keywords:["normal","sub","super"],name:"font-variant-position"},{inherited:!0,keywords:["normal"],name:"font-variation-settings"},{inherited:!0,keywords:["normal","bold","bolder","lighter"],name:"font-weight"},{inherited:!0,keywords:["auto","none","preserve-parent-color"],name:"forced-color-adjust"},{longhands:["row-gap","column-gap"],name:"gap"},{longhands:["grid-template-rows","grid-template-columns","grid-template-areas","grid-auto-flow","grid-auto-rows","grid-auto-columns"],name:"grid"},{longhands:["grid-row-start","grid-column-start","grid-row-end","grid-column-end"],name:"grid-area"},{keywords:["auto","min-content","max-content"],name:"grid-auto-columns"},{keywords:["row","column"],name:"grid-auto-flow"},{keywords:["auto","min-content","max-content"],name:"grid-auto-rows"},{longhands:["grid-column-start","grid-column-end"],name:"grid-column"},{keywords:["auto"],name:"grid-column-end"},{longhands:["column-gap"],name:"grid-column-gap"},{keywords:["auto"],name:"grid-column-start"},{longhands:["row-gap","column-gap"],name:"grid-gap"},{longhands:["grid-row-start","grid-row-end"],name:"grid-row"},{keywords:["auto"],name:"grid-row-end"},{longhands:["row-gap"],name:"grid-row-gap"},{keywords:["auto"],name:"grid-row-start"},{longhands:["grid-template-rows","grid-template-columns","grid-template-areas"],name:"grid-template"},{keywords:["none"],name:"grid-template-areas"},{keywords:["none"],name:"grid-template-columns"},{keywords:["none"],name:"grid-template-rows"},{keywords:["auto","fit-content","min-content","max-content"],name:"height"},{inherited:!0,name:"hyphenate-character"},{inherited:!0,keywords:["auto"],name:"hyphenate-limit-chars"},{inherited:!0,keywords:["none","manual","auto"],name:"hyphens"},{inherited:!0,name:"image-orientation"},{inherited:!0,keywords:["auto","optimizespeed","optimizequality","-webkit-optimize-contrast","pixelated"],name:"image-rendering"},{name:"inherits"},{inherited:!1,keywords:["drop","normal","raise"],name:"initial-letter"},{name:"initial-value"},{keywords:["auto"],name:"inline-size"},{longhands:["top","right","bottom","left"],name:"inset"},{longhands:["inset-block-start","inset-block-end"],name:"inset-block"},{name:"inset-block-end"},{name:"inset-block-start"},{longhands:["inset-inline-start","inset-inline-end"],name:"inset-inline"},{name:"inset-inline-end"},{name:"inset-inline-start"},{keywords:["auto","isolate"],name:"isolation"},{name:"justify-content"},{name:"justify-items"},{name:"justify-self"},{keywords:["auto"],name:"left"},{inherited:!0,keywords:["normal"],name:"letter-spacing"},{keywords:["currentcolor"],name:"lighting-color"},{inherited:!0,keywords:["auto","loose","normal","strict","anywhere"],name:"line-break"},{name:"line-gap-override"},{inherited:!0,keywords:["normal"],name:"line-height"},{inherited:!0,longhands:["list-style-position","list-style-image","list-style-type"],name:"list-style"},{inherited:!0,keywords:["none"],name:"list-style-image"},{inherited:!0,keywords:["outside","inside"],name:"list-style-position"},{inherited:!0,keywords:["disc","circle","square","disclosure-open","disclosure-closed","decimal","none"],name:"list-style-type"},{longhands:["margin-top","margin-right","margin-bottom","margin-left"],name:"margin"},{longhands:["margin-block-start","margin-block-end"],name:"margin-block"},{keywords:["auto"],name:"margin-block-end"},{keywords:["auto"],name:"margin-block-start"},{keywords:["auto"],name:"margin-bottom"},{longhands:["margin-inline-start","margin-inline-end"],name:"margin-inline"},{keywords:["auto"],name:"margin-inline-end"},{keywords:["auto"],name:"margin-inline-start"},{keywords:["auto"],name:"margin-left"},{keywords:["auto"],name:"margin-right"},{keywords:["auto"],name:"margin-top"},{inherited:!0,longhands:["marker-start","marker-mid","marker-end"],name:"marker"},{inherited:!0,keywords:["none"],name:"marker-end"},{inherited:!0,keywords:["none"],name:"marker-mid"},{inherited:!0,keywords:["none"],name:"marker-start"},{name:"mask"},{keywords:["luminance","alpha"],name:"mask-type"},{inherited:!0,name:"math-depth"},{inherited:!0,keywords:["normal","compact"],name:"math-shift"},{inherited:!0,keywords:["normal","compact"],name:"math-style"},{keywords:["none"],name:"max-block-size"},{keywords:["none"],name:"max-height"},{keywords:["none"],name:"max-inline-size"},{keywords:["none"],name:"max-width"},{name:"min-block-size"},{name:"min-height"},{name:"min-inline-size"},{name:"min-width"},{keywords:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter"],name:"mix-blend-mode"},{name:"negative"},{keywords:["fill","contain","cover","none","scale-down"],name:"object-fit"},{name:"object-position"},{keywords:["none"],name:"object-view-box"},{longhands:["offset-position","offset-path","offset-distance","offset-rotate","offset-anchor"],name:"offset"},{keywords:["auto"],name:"offset-anchor"},{name:"offset-distance"},{keywords:["none"],name:"offset-path"},{keywords:["auto","normal"],name:"offset-position"},{keywords:["auto","reverse"],name:"offset-rotate"},{name:"opacity"},{name:"order"},{keywords:["normal","none"],name:"origin-trial-test-property"},{inherited:!0,name:"orphans"},{longhands:["outline-color","outline-style","outline-width"],name:"outline"},{keywords:["currentcolor"],name:"outline-color"},{name:"outline-offset"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"outline-style"},{keywords:["thin","medium","thick"],name:"outline-width"},{longhands:["overflow-x","overflow-y"],name:"overflow"},{inherited:!1,keywords:["visible","none","auto"],name:"overflow-anchor"},{name:"overflow-block"},{keywords:["border-box","content-box","padding-box"],name:"overflow-clip-margin"},{name:"overflow-inline"},{inherited:!0,keywords:["normal","break-word","anywhere"],name:"overflow-wrap"},{keywords:["visible","hidden","scroll","auto","overlay","clip"],name:"overflow-x"},{keywords:["visible","hidden","scroll","auto","overlay","clip"],name:"overflow-y"},{keywords:["none","auto"],name:"overlay"},{name:"override-colors"},{longhands:["overscroll-behavior-x","overscroll-behavior-y"],name:"overscroll-behavior"},{name:"overscroll-behavior-block"},{name:"overscroll-behavior-inline"},{keywords:["auto","contain","none"],name:"overscroll-behavior-x"},{keywords:["auto","contain","none"],name:"overscroll-behavior-y"},{name:"pad"},{longhands:["padding-top","padding-right","padding-bottom","padding-left"],name:"padding"},{longhands:["padding-block-start","padding-block-end"],name:"padding-block"},{name:"padding-block-end"},{name:"padding-block-start"},{name:"padding-bottom"},{longhands:["padding-inline-start","padding-inline-end"],name:"padding-inline"},{name:"padding-inline-end"},{name:"padding-inline-start"},{name:"padding-left"},{name:"padding-right"},{name:"padding-top"},{keywords:["auto"],name:"page"},{longhands:["break-after"],name:"page-break-after"},{longhands:["break-before"],name:"page-break-before"},{longhands:["break-inside"],name:"page-break-inside"},{name:"page-orientation"},{inherited:!0,keywords:["normal","fill","stroke","markers"],name:"paint-order"},{keywords:["none"],name:"perspective"},{name:"perspective-origin"},{longhands:["align-content","justify-content"],name:"place-content"},{longhands:["align-items","justify-items"],name:"place-items"},{longhands:["align-self","justify-self"],name:"place-self"},{inherited:!0,keywords:["none","auto","stroke","fill","painted","visible","visiblestroke","visiblefill","visiblepainted","bounding-box","all"],name:"pointer-events"},{name:"popover-hide-delay"},{name:"popover-show-delay"},{keywords:["static","relative","absolute","fixed","sticky"],name:"position"},{keywords:["none"],name:"position-fallback"},{name:"prefix"},{inherited:!0,keywords:["auto","none"],name:"quotes"},{name:"r"},{name:"range"},{keywords:["none","both","horizontal","vertical","block","inline"],name:"resize"},{keywords:["auto"],name:"right"},{name:"rotate"},{keywords:["normal"],name:"row-gap"},{inherited:!0,name:"ruby-position"},{keywords:["auto"],name:"rx"},{keywords:["auto"],name:"ry"},{name:"scale"},{keywords:["auto","smooth"],name:"scroll-behavior"},{name:"scroll-customization"},{longhands:["scroll-margin-top","scroll-margin-right","scroll-margin-bottom","scroll-margin-left"],name:"scroll-margin"},{longhands:["scroll-margin-block-start","scroll-margin-block-end"],name:"scroll-margin-block"},{name:"scroll-margin-block-end"},{name:"scroll-margin-block-start"},{name:"scroll-margin-bottom"},{longhands:["scroll-margin-inline-start","scroll-margin-inline-end"],name:"scroll-margin-inline"},{name:"scroll-margin-inline-end"},{name:"scroll-margin-inline-start"},{name:"scroll-margin-left"},{name:"scroll-margin-right"},{name:"scroll-margin-top"},{longhands:["scroll-padding-top","scroll-padding-right","scroll-padding-bottom","scroll-padding-left"],name:"scroll-padding"},{longhands:["scroll-padding-block-start","scroll-padding-block-end"],name:"scroll-padding-block"},{keywords:["auto"],name:"scroll-padding-block-end"},{keywords:["auto"],name:"scroll-padding-block-start"},{keywords:["auto"],name:"scroll-padding-bottom"},{longhands:["scroll-padding-inline-start","scroll-padding-inline-end"],name:"scroll-padding-inline"},{keywords:["auto"],name:"scroll-padding-inline-end"},{keywords:["auto"],name:"scroll-padding-inline-start"},{keywords:["auto"],name:"scroll-padding-left"},{keywords:["auto"],name:"scroll-padding-right"},{keywords:["auto"],name:"scroll-padding-top"},{keywords:["none","start","end","center"],name:"scroll-snap-align"},{keywords:["normal","always"],name:"scroll-snap-stop"},{keywords:["none","x","y","block","inline","both","mandatory","proximity"],name:"scroll-snap-type"},{longhands:["scroll-start-block","scroll-start-inline"],name:"scroll-start"},{keywords:["auto","start","end","center","top","bottom","left","right"],name:"scroll-start-block"},{keywords:["auto","start","end","center","top","bottom","left","right"],name:"scroll-start-inline"},{longhands:["scroll-start-target-block","scroll-start-target-inline"],name:"scroll-start-target"},{keywords:["none","auto"],name:"scroll-start-target-block"},{keywords:["none","auto"],name:"scroll-start-target-inline"},{keywords:["none","auto"],name:"scroll-start-target-x"},{keywords:["none","auto"],name:"scroll-start-target-y"},{name:"scroll-start-x"},{name:"scroll-start-y"},{longhands:["scroll-timeline-name","scroll-timeline-axis","scroll-timeline-attachment"],name:"scroll-timeline"},{name:"scroll-timeline-attachment"},{name:"scroll-timeline-axis"},{name:"scroll-timeline-name"},{inherited:!0,keywords:["auto"],name:"scrollbar-color"},{inherited:!1,keywords:["auto","stable","both-edges"],name:"scrollbar-gutter"},{inherited:!1,keywords:["auto","thin","none"],name:"scrollbar-width"},{name:"shape-image-threshold"},{keywords:["none"],name:"shape-margin"},{keywords:["none"],name:"shape-outside"},{inherited:!0,keywords:["auto","optimizespeed","crispedges","geometricprecision"],name:"shape-rendering"},{name:"size"},{name:"size-adjust"},{inherited:!0,keywords:["none","normal","spell-out","digits","literal-punctuation","no-punctuation"],name:"speak"},{name:"speak-as"},{name:"src"},{keywords:["currentcolor"],name:"stop-color"},{name:"stop-opacity"},{inherited:!0,name:"stroke"},{inherited:!0,keywords:["none"],name:"stroke-dasharray"},{inherited:!0,name:"stroke-dashoffset"},{inherited:!0,keywords:["butt","round","square"],name:"stroke-linecap"},{inherited:!0,keywords:["miter","bevel","round"],name:"stroke-linejoin"},{inherited:!0,name:"stroke-miterlimit"},{inherited:!0,name:"stroke-opacity"},{inherited:!0,name:"stroke-width"},{name:"suffix"},{name:"symbols"},{name:"syntax"},{name:"system"},{inherited:!0,name:"tab-size"},{keywords:["auto","fixed"],name:"table-layout"},{inherited:!0,keywords:["left","right","center","justify","-webkit-left","-webkit-right","-webkit-center","start","end"],name:"text-align"},{inherited:!0,keywords:["auto","start","end","left","right","center","justify"],name:"text-align-last"},{inherited:!0,keywords:["start","middle","end"],name:"text-anchor"},{keywords:["none","start","end","both"],name:"text-box-trim"},{inherited:!0,keywords:["none","all"],name:"text-combine-upright"},{longhands:["text-decoration-line","text-decoration-thickness","text-decoration-style","text-decoration-color"],name:"text-decoration"},{keywords:["currentcolor"],name:"text-decoration-color"},{keywords:["none","underline","overline","line-through","blink","spelling-error","grammar-error"],name:"text-decoration-line"},{inherited:!0,keywords:["none","auto"],name:"text-decoration-skip-ink"},{keywords:["solid","double","dotted","dashed","wavy"],name:"text-decoration-style"},{inherited:!0,keywords:["auto","from-font"],name:"text-decoration-thickness"},{inherited:!0,longhands:["text-emphasis-style","text-emphasis-color"],name:"text-emphasis"},{inherited:!0,keywords:["currentcolor"],name:"text-emphasis-color"},{inherited:!0,name:"text-emphasis-position"},{inherited:!0,name:"text-emphasis-style"},{inherited:!0,name:"text-indent"},{inherited:!0,keywords:["sideways","mixed","upright"],name:"text-orientation"},{keywords:["clip","ellipsis"],name:"text-overflow"},{inherited:!0,keywords:["auto","optimizespeed","optimizelegibility","geometricprecision"],name:"text-rendering"},{inherited:!0,keywords:["none"],name:"text-shadow"},{inherited:!0,keywords:["none","auto"],name:"text-size-adjust"},{inherited:!0,keywords:["capitalize","uppercase","lowercase","none","math-auto"],name:"text-transform"},{inherited:!0,keywords:["auto"],name:"text-underline-offset"},{inherited:!0,keywords:["auto","from-font","under","left","right"],name:"text-underline-position"},{inherited:!0,keywords:["wrap","nowrap","balance","pretty"],name:"text-wrap"},{name:"timeline-scope"},{longhands:["toggle-root","toggle-trigger"],name:"toggle"},{keywords:["none"],name:"toggle-group"},{keywords:["none"],name:"toggle-root"},{keywords:["none"],name:"toggle-trigger"},{keywords:["normal"],name:"toggle-visibility"},{keywords:["auto"],name:"top"},{keywords:["auto","none","pan-x","pan-left","pan-right","pan-y","pan-up","pan-down","pinch-zoom","manipulation"],name:"touch-action"},{keywords:["none"],name:"transform"},{keywords:["fill-box","view-box"],name:"transform-box"},{name:"transform-origin"},{keywords:["flat","preserve-3d"],name:"transform-style"},{longhands:["transition-property","transition-duration","transition-timing-function","transition-delay"],name:"transition"},{name:"transition-delay"},{name:"transition-duration"},{keywords:["none"],name:"transition-property"},{keywords:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"],name:"transition-timing-function"},{name:"translate"},{keywords:["normal","embed","bidi-override","isolate","plaintext","isolate-override"],name:"unicode-bidi"},{name:"unicode-range"},{inherited:!0,keywords:["auto","none","text","all","contain"],name:"user-select"},{keywords:["none","non-scaling-stroke"],name:"vector-effect"},{keywords:["baseline","sub","super","text-top","text-bottom","middle"],name:"vertical-align"},{longhands:["view-timeline-name","view-timeline-axis","view-timeline-attachment"],name:"view-timeline"},{name:"view-timeline-attachment"},{name:"view-timeline-axis"},{name:"view-timeline-inset"},{name:"view-timeline-name"},{keywords:["none"],name:"view-transition-name"},{inherited:!0,keywords:["visible","hidden","collapse"],name:"visibility"},{inherited:!0,keywords:["normal","pre","pre-wrap","pre-line","nowrap","break-spaces"],name:"white-space"},{inherited:!0,keywords:["collapse","preserve","preserve-breaks","break-spaces"],name:"white-space-collapse"},{inherited:!0,name:"widows"},{keywords:["auto","fit-content","min-content","max-content"],name:"width"},{keywords:["auto"],name:"will-change"},{inherited:!0,keywords:["normal"],name:"word-boundary-detection"},{inherited:!0,keywords:["normal","break-all","keep-all","break-word"],name:"word-break"},{inherited:!0,keywords:["normal"],name:"word-spacing"},{inherited:!0,keywords:["horizontal-tb","vertical-rl","vertical-lr"],name:"writing-mode"},{name:"x"},{name:"y"},{keywords:["auto"],name:"z-index"},{name:"zoom"}],g={"-webkit-box-align":{values:["stretch","start","center","end","baseline"]},"-webkit-box-decoration-break":{values:["slice","clone"]},"-webkit-box-direction":{values:["normal","reverse"]},"-webkit-box-orient":{values:["horizontal","vertical"]},"-webkit-box-pack":{values:["start","center","end","justify"]},"-webkit-line-break":{values:["auto","loose","normal","strict","after-white-space","anywhere"]},"-webkit-print-color-adjust":{values:["economy","exact"]},"-webkit-rtl-ordering":{values:["logical","visual"]},"-webkit-ruby-position":{values:["before","after"]},"-webkit-text-security":{values:["none","disc","circle","square"]},"-webkit-user-drag":{values:["auto","none","element"]},"-webkit-user-modify":{values:["read-only","read-write","read-write-plaintext-only"]},"accent-color":{values:["auto","currentcolor"]},"alignment-baseline":{values:["auto","baseline","alphabetic","ideographic","middle","central","mathematical","before-edge","text-before-edge","after-edge","text-after-edge","hanging"]},"anchor-default":{values:["none"]},"anchor-name":{values:["none"]},"anchor-scroll":{values:["none"]},"animation-composition":{values:["replace","add","accumulate"]},"animation-direction":{values:["normal","reverse","alternate","alternate-reverse"]},"animation-fill-mode":{values:["none","forwards","backwards","both"]},"animation-iteration-count":{values:["infinite"]},"animation-name":{values:["none"]},"animation-play-state":{values:["running","paused"]},"animation-timeline":{values:["none","auto"]},"animation-timing-function":{values:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"]},"app-region":{values:["none","drag","no-drag"]},"aspect-ratio":{values:["auto"]},"backdrop-filter":{values:["none"]},"backface-visibility":{values:["visible","hidden"]},"background-attachment":{values:["scroll","fixed","local"]},"background-blend-mode":{values:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"]},"background-clip":{values:["border-box","padding-box","content-box"]},"background-color":{values:["currentcolor"]},"background-image":{values:["auto","none"]},"background-origin":{values:["border-box","padding-box","content-box"]},"background-size":{values:["auto","cover","contain"]},"baseline-shift":{values:["baseline","sub","super"]},"baseline-source":{values:["auto","first","last"]},"block-size":{values:["auto"]},"border-bottom-color":{values:["currentcolor"]},"border-bottom-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-bottom-width":{values:["thin","medium","thick"]},"border-collapse":{values:["separate","collapse"]},"border-image-repeat":{values:["stretch","repeat","round","space"]},"border-image-source":{values:["none"]},"border-image-width":{values:["auto"]},"border-left-color":{values:["currentcolor"]},"border-left-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-left-width":{values:["thin","medium","thick"]},"border-right-color":{values:["currentcolor"]},"border-right-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-right-width":{values:["thin","medium","thick"]},"border-style":{values:["none"]},"border-top-color":{values:["currentcolor"]},"border-top-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-top-width":{values:["thin","medium","thick"]},bottom:{values:["auto"]},"box-shadow":{values:["none"]},"box-sizing":{values:["content-box","border-box"]},"break-after":{values:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"]},"break-before":{values:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"]},"break-inside":{values:["auto","avoid","avoid-column","avoid-page"]},"buffered-rendering":{values:["auto","dynamic","static"]},"caption-side":{values:["top","bottom"]},"caret-color":{values:["auto","currentcolor"]},clear:{values:["none","left","right","both","inline-start","inline-end"]},clip:{values:["auto"]},"clip-path":{values:["none"]},"clip-rule":{values:["nonzero","evenodd"]},color:{values:["currentcolor"]},"color-interpolation":{values:["auto","srgb","linearrgb"]},"color-interpolation-filters":{values:["auto","srgb","linearrgb"]},"color-rendering":{values:["auto","optimizespeed","optimizequality"]},"column-count":{values:["auto"]},"column-fill":{values:["balance","auto"]},"column-gap":{values:["normal"]},"column-rule-color":{values:["currentcolor"]},"column-rule-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"column-rule-width":{values:["thin","medium","thick"]},"column-span":{values:["none","all"]},"column-width":{values:["auto"]},contain:{values:["none","strict","content","size","layout","style","paint","inline-size","block-size"]},"contain-intrinsic-height":{values:["auto","none"]},"contain-intrinsic-width":{values:["auto","none"]},"container-name":{values:["none"]},"container-type":{values:["normal","inline-size","size","sticky"]},"content-visibility":{values:["visible","auto","hidden"]},"counter-increment":{values:["none"]},"counter-reset":{values:["none"]},"counter-set":{values:["none"]},cursor:{values:["auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize","s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","col-resize","row-resize","all-scroll","zoom-in","zoom-out","grab","grabbing"]},d:{values:["none"]},direction:{values:["ltr","rtl"]},display:{values:["inline","block","list-item","inline-block","table","inline-table","table-row-group","table-header-group","table-footer-group","table-row","table-column-group","table-column","table-cell","table-caption","-webkit-box","-webkit-inline-box","flex","inline-flex","grid","inline-grid","contents","flow-root","none","flow","math"]},"dominant-baseline":{values:["auto","alphabetic","ideographic","middle","central","mathematical","hanging","use-script","no-change","reset-size","text-after-edge","text-before-edge"]},"empty-cells":{values:["show","hide"]},"fill-rule":{values:["nonzero","evenodd"]},filter:{values:["none"]},"flex-basis":{values:["auto","fit-content","min-content","max-content","content"]},"flex-direction":{values:["row","row-reverse","column","column-reverse"]},"flex-wrap":{values:["nowrap","wrap","wrap-reverse"]},float:{values:["none","left","right","inline-start","inline-end"]},"flood-color":{values:["currentcolor"]},"font-feature-settings":{values:["normal"]},"font-kerning":{values:["auto","normal","none"]},"font-optical-sizing":{values:["auto","none"]},"font-palette":{values:["normal","light","dark"]},"font-size":{values:["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large","larger","smaller","-webkit-xxx-large"]},"font-size-adjust":{values:["none","ex-height","cap-height","ch-width","ic-width"]},"font-stretch":{values:["normal","ultra-condensed","extra-condensed","condensed","semi-condensed","semi-expanded","expanded","extra-expanded","ultra-expanded"]},"font-style":{values:["normal","italic","oblique"]},"font-synthesis-small-caps":{values:["auto","none"]},"font-synthesis-style":{values:["auto","none"]},"font-synthesis-weight":{values:["auto","none"]},"font-variant-alternates":{values:["normal"]},"font-variant-caps":{values:["normal","small-caps","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps"]},"font-variant-east-asian":{values:["normal","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"]},"font-variant-ligatures":{values:["normal","none","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual"]},"font-variant-numeric":{values:["normal","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero"]},"font-variant-position":{values:["normal","sub","super"]},"font-variation-settings":{values:["normal"]},"font-weight":{values:["normal","bold","bolder","lighter"]},"forced-color-adjust":{values:["auto","none","preserve-parent-color"]},"grid-auto-columns":{values:["auto","min-content","max-content"]},"grid-auto-flow":{values:["row","column"]},"grid-auto-rows":{values:["auto","min-content","max-content"]},"grid-column-end":{values:["auto"]},"grid-column-start":{values:["auto"]},"grid-row-end":{values:["auto"]},"grid-row-start":{values:["auto"]},"grid-template-areas":{values:["none"]},"grid-template-columns":{values:["none"]},"grid-template-rows":{values:["none"]},height:{values:["auto","fit-content","min-content","max-content"]},"hyphenate-limit-chars":{values:["auto"]},hyphens:{values:["none","manual","auto"]},"image-rendering":{values:["auto","optimizespeed","optimizequality","-webkit-optimize-contrast","pixelated"]},"initial-letter":{values:["drop","normal","raise"]},"inline-size":{values:["auto"]},isolation:{values:["auto","isolate"]},left:{values:["auto"]},"letter-spacing":{values:["normal"]},"lighting-color":{values:["currentcolor"]},"line-break":{values:["auto","loose","normal","strict","anywhere"]},"line-height":{values:["normal"]},"list-style-image":{values:["none"]},"list-style-position":{values:["outside","inside"]},"list-style-type":{values:["disc","circle","square","disclosure-open","disclosure-closed","decimal","none"]},"margin-block-end":{values:["auto"]},"margin-block-start":{values:["auto"]},"margin-bottom":{values:["auto"]},"margin-inline-end":{values:["auto"]},"margin-inline-start":{values:["auto"]},"margin-left":{values:["auto"]},"margin-right":{values:["auto"]},"margin-top":{values:["auto"]},"marker-end":{values:["none"]},"marker-mid":{values:["none"]},"marker-start":{values:["none"]},"mask-type":{values:["luminance","alpha"]},"math-shift":{values:["normal","compact"]},"math-style":{values:["normal","compact"]},"max-block-size":{values:["none"]},"max-height":{values:["none"]},"max-inline-size":{values:["none"]},"max-width":{values:["none"]},"mix-blend-mode":{values:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter"]},"object-fit":{values:["fill","contain","cover","none","scale-down"]},"object-view-box":{values:["none"]},"offset-anchor":{values:["auto"]},"offset-path":{values:["none"]},"offset-position":{values:["auto","normal"]},"offset-rotate":{values:["auto","reverse"]},"origin-trial-test-property":{values:["normal","none"]},"outline-color":{values:["currentcolor"]},"outline-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"outline-width":{values:["thin","medium","thick"]},"overflow-anchor":{values:["visible","none","auto"]},"overflow-clip-margin":{values:["border-box","content-box","padding-box"]},"overflow-wrap":{values:["normal","break-word","anywhere"]},"overflow-x":{values:["visible","hidden","scroll","auto","overlay","clip"]},"overflow-y":{values:["visible","hidden","scroll","auto","overlay","clip"]},overlay:{values:["none","auto"]},"overscroll-behavior-x":{values:["auto","contain","none"]},"overscroll-behavior-y":{values:["auto","contain","none"]},page:{values:["auto"]},"paint-order":{values:["normal","fill","stroke","markers"]},perspective:{values:["none"]},"pointer-events":{values:["none","auto","stroke","fill","painted","visible","visiblestroke","visiblefill","visiblepainted","bounding-box","all"]},position:{values:["static","relative","absolute","fixed","sticky"]},"position-fallback":{values:["none"]},quotes:{values:["auto","none"]},resize:{values:["none","both","horizontal","vertical","block","inline"]},right:{values:["auto"]},"row-gap":{values:["normal"]},rx:{values:["auto"]},ry:{values:["auto"]},"scroll-behavior":{values:["auto","smooth"]},"scroll-padding-block-end":{values:["auto"]},"scroll-padding-block-start":{values:["auto"]},"scroll-padding-bottom":{values:["auto"]},"scroll-padding-inline-end":{values:["auto"]},"scroll-padding-inline-start":{values:["auto"]},"scroll-padding-left":{values:["auto"]},"scroll-padding-right":{values:["auto"]},"scroll-padding-top":{values:["auto"]},"scroll-snap-align":{values:["none","start","end","center"]},"scroll-snap-stop":{values:["normal","always"]},"scroll-snap-type":{values:["none","x","y","block","inline","both","mandatory","proximity"]},"scroll-start-block":{values:["auto","start","end","center","top","bottom","left","right"]},"scroll-start-inline":{values:["auto","start","end","center","top","bottom","left","right"]},"scroll-start-target-block":{values:["none","auto"]},"scroll-start-target-inline":{values:["none","auto"]},"scroll-start-target-x":{values:["none","auto"]},"scroll-start-target-y":{values:["none","auto"]},"scrollbar-color":{values:["auto"]},"scrollbar-gutter":{values:["auto","stable","both-edges"]},"scrollbar-width":{values:["auto","thin","none"]},"shape-margin":{values:["none"]},"shape-outside":{values:["none"]},"shape-rendering":{values:["auto","optimizespeed","crispedges","geometricprecision"]},speak:{values:["none","normal","spell-out","digits","literal-punctuation","no-punctuation"]},"stop-color":{values:["currentcolor"]},"stroke-dasharray":{values:["none"]},"stroke-linecap":{values:["butt","round","square"]},"stroke-linejoin":{values:["miter","bevel","round"]},"table-layout":{values:["auto","fixed"]},"text-align":{values:["left","right","center","justify","-webkit-left","-webkit-right","-webkit-center","start","end"]},"text-align-last":{values:["auto","start","end","left","right","center","justify"]},"text-anchor":{values:["start","middle","end"]},"text-box-trim":{values:["none","start","end","both"]},"text-combine-upright":{values:["none","all"]},"text-decoration-color":{values:["currentcolor"]},"text-decoration-line":{values:["none","underline","overline","line-through","blink","spelling-error","grammar-error"]},"text-decoration-skip-ink":{values:["none","auto"]},"text-decoration-style":{values:["solid","double","dotted","dashed","wavy"]},"text-decoration-thickness":{values:["auto","from-font"]},"text-emphasis-color":{values:["currentcolor"]},"text-orientation":{values:["sideways","mixed","upright"]},"text-overflow":{values:["clip","ellipsis"]},"text-rendering":{values:["auto","optimizespeed","optimizelegibility","geometricprecision"]},"text-shadow":{values:["none"]},"text-size-adjust":{values:["none","auto"]},"text-transform":{values:["capitalize","uppercase","lowercase","none","math-auto"]},"text-underline-offset":{values:["auto"]},"text-underline-position":{values:["auto","from-font","under","left","right"]},"text-wrap":{values:["wrap","nowrap","balance","pretty"]},"toggle-group":{values:["none"]},"toggle-root":{values:["none"]},"toggle-trigger":{values:["none"]},"toggle-visibility":{values:["normal"]},top:{values:["auto"]},"touch-action":{values:["auto","none","pan-x","pan-left","pan-right","pan-y","pan-up","pan-down","pinch-zoom","manipulation"]},transform:{values:["none"]},"transform-box":{values:["fill-box","view-box"]},"transform-style":{values:["flat","preserve-3d"]},"transition-property":{values:["none"]},"transition-timing-function":{values:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"]},"unicode-bidi":{values:["normal","embed","bidi-override","isolate","plaintext","isolate-override"]},"user-select":{values:["auto","none","text","all","contain"]},"vector-effect":{values:["none","non-scaling-stroke"]},"vertical-align":{values:["baseline","sub","super","text-top","text-bottom","middle"]},"view-transition-name":{values:["none"]},visibility:{values:["visible","hidden","collapse"]},"white-space":{values:["normal","pre","pre-wrap","pre-line","nowrap","break-spaces"]},"white-space-collapse":{values:["collapse","preserve","preserve-breaks","break-spaces"]},width:{values:["auto","fit-content","min-content","max-content"]},"will-change":{values:["auto"]},"word-boundary-detection":{values:["normal"]},"word-break":{values:["normal","break-all","keep-all","break-word"]},"word-spacing":{values:["normal"]},"writing-mode":{values:["horizontal-tb","vertical-rl","vertical-lr"]},"z-index":{values:["auto"]}},p=new Map([["-epub-caption-side","caption-side"],["-epub-text-combine","-webkit-text-combine"],["-epub-text-emphasis","text-emphasis"],["-epub-text-emphasis-color","text-emphasis-color"],["-epub-text-emphasis-style","text-emphasis-style"],["-epub-text-orientation","-webkit-text-orientation"],["-epub-text-transform","text-transform"],["-epub-word-break","word-break"],["-epub-writing-mode","-webkit-writing-mode"],["-webkit-align-content","align-content"],["-webkit-align-items","align-items"],["-webkit-align-self","align-self"],["-webkit-alternative-animation-delay","-alternative-animation-delay"],["-webkit-alternative-animation-with-delay-start-end","-alternative-animation-with-delay-start-end"],["-webkit-alternative-animation-with-timeline","-alternative-animation-with-timeline"],["-webkit-animation","animation"],["-webkit-animation-delay","animation-delay"],["-webkit-animation-direction","animation-direction"],["-webkit-animation-duration","animation-duration"],["-webkit-animation-fill-mode","animation-fill-mode"],["-webkit-animation-iteration-count","animation-iteration-count"],["-webkit-animation-name","animation-name"],["-webkit-animation-play-state","animation-play-state"],["-webkit-animation-timing-function","animation-timing-function"],["-webkit-app-region","app-region"],["-webkit-appearance","appearance"],["-webkit-backface-visibility","backface-visibility"],["-webkit-background-clip","background-clip"],["-webkit-background-origin","background-origin"],["-webkit-background-size","background-size"],["-webkit-border-after","border-block-end"],["-webkit-border-after-color","border-block-end-color"],["-webkit-border-after-style","border-block-end-style"],["-webkit-border-after-width","border-block-end-width"],["-webkit-border-before","border-block-start"],["-webkit-border-before-color","border-block-start-color"],["-webkit-border-before-style","border-block-start-style"],["-webkit-border-before-width","border-block-start-width"],["-webkit-border-bottom-left-radius","border-bottom-left-radius"],["-webkit-border-bottom-right-radius","border-bottom-right-radius"],["-webkit-border-end","border-inline-end"],["-webkit-border-end-color","border-inline-end-color"],["-webkit-border-end-style","border-inline-end-style"],["-webkit-border-end-width","border-inline-end-width"],["-webkit-border-radius","border-radius"],["-webkit-border-start","border-inline-start"],["-webkit-border-start-color","border-inline-start-color"],["-webkit-border-start-style","border-inline-start-style"],["-webkit-border-start-width","border-inline-start-width"],["-webkit-border-top-left-radius","border-top-left-radius"],["-webkit-border-top-right-radius","border-top-right-radius"],["-webkit-box-shadow","box-shadow"],["-webkit-box-sizing","box-sizing"],["-webkit-clip-path","clip-path"],["-webkit-column-count","column-count"],["-webkit-column-gap","column-gap"],["-webkit-column-rule","column-rule"],["-webkit-column-rule-color","column-rule-color"],["-webkit-column-rule-style","column-rule-style"],["-webkit-column-rule-width","column-rule-width"],["-webkit-column-span","column-span"],["-webkit-column-width","column-width"],["-webkit-columns","columns"],["-webkit-filter","filter"],["-webkit-flex","flex"],["-webkit-flex-basis","flex-basis"],["-webkit-flex-direction","flex-direction"],["-webkit-flex-flow","flex-flow"],["-webkit-flex-grow","flex-grow"],["-webkit-flex-shrink","flex-shrink"],["-webkit-flex-wrap","flex-wrap"],["-webkit-font-feature-settings","font-feature-settings"],["-webkit-hyphenate-character","hyphenate-character"],["-webkit-justify-content","justify-content"],["-webkit-logical-height","block-size"],["-webkit-logical-width","inline-size"],["-webkit-margin-after","margin-block-end"],["-webkit-margin-before","margin-block-start"],["-webkit-margin-end","margin-inline-end"],["-webkit-margin-start","margin-inline-start"],["-webkit-max-logical-height","max-block-size"],["-webkit-max-logical-width","max-inline-size"],["-webkit-min-logical-height","min-block-size"],["-webkit-min-logical-width","min-inline-size"],["-webkit-opacity","opacity"],["-webkit-order","order"],["-webkit-padding-after","padding-block-end"],["-webkit-padding-before","padding-block-start"],["-webkit-padding-end","padding-inline-end"],["-webkit-padding-start","padding-inline-start"],["-webkit-perspective","perspective"],["-webkit-perspective-origin","perspective-origin"],["-webkit-shape-image-threshold","shape-image-threshold"],["-webkit-shape-margin","shape-margin"],["-webkit-shape-outside","shape-outside"],["-webkit-text-emphasis","text-emphasis"],["-webkit-text-emphasis-color","text-emphasis-color"],["-webkit-text-emphasis-position","text-emphasis-position"],["-webkit-text-emphasis-style","text-emphasis-style"],["-webkit-text-size-adjust","text-size-adjust"],["-webkit-transform","transform"],["-webkit-transform-origin","transform-origin"],["-webkit-transform-style","transform-style"],["-webkit-transition","transition"],["-webkit-transition-delay","transition-delay"],["-webkit-transition-duration","transition-duration"],["-webkit-transition-property","transition-property"],["-webkit-transition-timing-function","transition-timing-function"],["-webkit-user-select","user-select"],["word-wrap","overflow-wrap"]]);class m{#t;#n;#r;#s;#i;#a;#o;#l;#d;#c;constructor(e,n){this.#t=[],this.#n=new Map,this.#r=new Map,this.#s=new Set,this.#i=new Set,this.#a=new Map,this.#o=n;for(let t=0;tCSS.supports(e,t))).sort(m.sortPrefixesToEnd).map((t=>`${e}: ${t}`));this.isSVGProperty(e)||this.#d.push(...t),this.#c.push(...t)}}static sortPrefixesToEnd(e,t){const n=e.startsWith("-webkit-"),r=t.startsWith("-webkit-");return n&&!r?1:!n&&r||et?1:0}allProperties(){return this.#t}aliasesFor(){return this.#o}nameValuePresets(e){return e?this.#c:this.#d}isSVGProperty(e){return e=e.toLowerCase(),this.#i.has(e)}getLonghands(e){return this.#n.get(e)||null}getShorthands(e){return this.#r.get(e)||null}isColorAwareProperty(e){return R.has(e.toLowerCase())||this.isCustomProperty(e.toLowerCase())}isFontFamilyProperty(e){return"font-family"===e.toLowerCase()}isAngleAwareProperty(e){const t=e.toLowerCase();return R.has(t)||x.has(t)}isGridAreaDefiningProperty(e){return"grid"===(e=e.toLowerCase())||"grid-template"===e||"grid-template-areas"===e}isLengthProperty(e){return"line-height"!==(e=e.toLowerCase())&&(w.has(e)||e.startsWith("margin")||e.startsWith("padding")||-1!==e.indexOf("width")||-1!==e.indexOf("height"))}isBezierAwareProperty(e){return e=e.toLowerCase(),C.has(e)||this.isCustomProperty(e)}isFontAwareProperty(e){return e=e.toLowerCase(),T.has(e)||this.isCustomProperty(e)}isCustomProperty(e){return e.startsWith("--")}isShadowProperty(e){return"box-shadow"===(e=e.toLowerCase())||"text-shadow"===e||"-webkit-box-shadow"===e}isStringProperty(e){return"content"===(e=e.toLowerCase())}canonicalPropertyName(e){if(this.isCustomProperty(e))return e;e=e.toLowerCase();const t=this.#o.get(e);if(t)return t;if(!e||e.length<9||"-"!==e.charAt(0))return e;const n=e.match(/(?:-webkit-)(.+)/);return n&&this.#l.has(n[1])?n[1]:e}isCSSPropertyName(e){return!!((e=e.toLowerCase()).startsWith("--")&&e.length>2||e.startsWith("-moz-")||e.startsWith("-ms-")||e.startsWith("-o-")||e.startsWith("-webkit-"))||this.#l.has(e)}isPropertyInherited(e){return(e=e.toLowerCase()).startsWith("--")||this.#s.has(this.canonicalPropertyName(e))||this.#s.has(e)}specificPropertyValues(e){const t=e.replace(/^-webkit-/,""),n=this.#a;let r=n.get(e)||n.get(t);if(!r){r=[];for(const t of L)CSS.supports(e,t)&&r.push(t);n.set(e,r)}return r}getPropertyValues(t){const n=["inherit","initial","revert","unset"];if(t=t.toLowerCase(),n.push(...this.specificPropertyValues(t)),this.isColorAwareProperty(t)){n.push("currentColor");for(const t of e.Color.Nicknames.keys())n.push(t)}return n.sort(m.sortPrefixesToEnd)}propertyUsageWeight(e){return P.get(e)||P.get(this.canonicalPropertyName(e))||0}getValuePreset(e,t){const n=S.get(e);let r=n?n.get(t):null;if(!r)return null;let s=r.length,i=r.length;return r&&(s=r.indexOf("|"),i=r.lastIndexOf("|"),i=s===i?i:i-1,r=r.replace(/\|/g,"")),{text:r,startColumn:s,endColumn:i}}isHighlightPseudoType(e){return"highlight"===e||"selection"===e||"target-text"===e||"grammar-error"===e||"spelling-error"===e}}const f=/(var\(\s*--.*?\))/g,b=/((?:\[[\w\- ]+\]\s*)*(?:"[^"]+"|'[^']+'))[^'"\[]*\[?[^'"\[]*/;let y=null;function v(){if(!y){y=new m(u,p)}return y}const I=new Map([["linear-gradient","linear-gradient(|45deg, black, transparent|)"],["radial-gradient","radial-gradient(|black, transparent|)"],["repeating-linear-gradient","repeating-linear-gradient(|45deg, black, transparent 100px|)"],["repeating-radial-gradient","repeating-radial-gradient(|black, transparent 100px|)"],["url","url(||)"]]),k=new Map([["blur","blur(|1px|)"],["brightness","brightness(|0.5|)"],["contrast","contrast(|0.5|)"],["drop-shadow","drop-shadow(|2px 4px 6px black|)"],["grayscale","grayscale(|1|)"],["hue-rotate","hue-rotate(|45deg|)"],["invert","invert(|1|)"],["opacity","opacity(|0.5|)"],["saturate","saturate(|0.5|)"],["sepia","sepia(|1|)"],["url","url(||)"]]),S=new Map([["filter",k],["backdrop-filter",k],["background",I],["background-image",I],["-webkit-mask-image",I],["transform",new Map([["scale","scale(|1.5|)"],["scaleX","scaleX(|1.5|)"],["scaleY","scaleY(|1.5|)"],["scale3d","scale3d(|1.5, 1.5, 1.5|)"],["rotate","rotate(|45deg|)"],["rotateX","rotateX(|45deg|)"],["rotateY","rotateY(|45deg|)"],["rotateZ","rotateZ(|45deg|)"],["rotate3d","rotate3d(|1, 1, 1, 45deg|)"],["skew","skew(|10deg, 10deg|)"],["skewX","skewX(|10deg|)"],["skewY","skewY(|10deg|)"],["translate","translate(|10px, 10px|)"],["translateX","translateX(|10px|)"],["translateY","translateY(|10px|)"],["translateZ","translateZ(|10px|)"],["translate3d","translate3d(|10px, 10px, 10px|)"],["matrix","matrix(|1, 0, 0, 1, 0, 0|)"],["matrix3d","matrix3d(|1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1|)"],["perspective","perspective(|10px|)"]])]]),w=new Set(["background-position","border-spacing","bottom","font-size","height","left","letter-spacing","max-height","max-width","min-height","min-width","right","text-indent","top","width","word-spacing","grid-row-gap","grid-column-gap","row-gap"]),C=new Set(["animation","animation-timing-function","transition","transition-timing-function","-webkit-animation","-webkit-animation-timing-function","-webkit-transition","-webkit-transition-timing-function"]),T=new Set(["font-size","line-height","font-weight","font-family","letter-spacing"]),R=new Set(["accent-color","background","background-color","background-image","border","border-color","border-image","border-image-source","border-bottom","border-bottom-color","border-left","border-left-color","border-right","border-right-color","border-top","border-top-color","box-shadow","caret-color","color","column-rule","column-rule-color","content","fill","list-style-image","outline","outline-color","stop-color","stroke","text-decoration-color","text-shadow","-webkit-border-after","-webkit-border-after-color","-webkit-border-before","-webkit-border-before-color","-webkit-border-end","-webkit-border-end-color","-webkit-border-start","-webkit-border-start-color","-webkit-box-reflect","-webkit-box-shadow","-webkit-column-rule-color","-webkit-mask","-webkit-mask-box-image","-webkit-mask-box-image-source","-webkit-mask-image","-webkit-tap-highlight-color","-webkit-text-decoration-color","-webkit-text-emphasis","-webkit-text-emphasis-color","-webkit-text-fill-color","-webkit-text-stroke","-webkit-text-stroke-color"]),x=new Set(["-webkit-border-image","transform","-webkit-transform","rotate","filter","-webkit-filter","backdrop-filter","offset","offset-rotate","font-style"]),M={"background-repeat":{values:["repeat","repeat-x","repeat-y","no-repeat","space","round"]},content:{values:["normal","close-quote","no-close-quote","no-open-quote","open-quote"]},"baseline-shift":{values:["baseline"]},"max-height":{values:["min-content","max-content","-webkit-fill-available","fit-content"]},color:{values:["black"]},"background-color":{values:["white"]},"box-shadow":{values:["inset"]},"text-shadow":{values:["0 0 black"]},"-webkit-writing-mode":{values:["horizontal-tb","vertical-rl","vertical-lr"]},"writing-mode":{values:["lr","rl","tb","lr-tb","rl-tb","tb-rl"]},"page-break-inside":{values:["avoid"]},cursor:{values:["-webkit-zoom-in","-webkit-zoom-out","-webkit-grab","-webkit-grabbing"]},"border-width":{values:["medium","thick","thin"]},"border-style":{values:["hidden","inset","groove","ridge","outset","dotted","dashed","solid","double"]},size:{values:["a3","a4","a5","b4","b5","landscape","ledger","legal","letter","portrait"]},overflow:{values:["hidden","visible","overlay","scroll"]},"overscroll-behavior":{values:["contain"]},"text-rendering":{values:["optimizeSpeed","optimizeLegibility","geometricPrecision"]},"text-align":{values:["-webkit-auto","-webkit-match-parent"]},"clip-path":{values:["circle","ellipse","inset","polygon","url"]},"color-interpolation":{values:["sRGB","linearRGB"]},"word-wrap":{values:["normal","break-word"]},"font-weight":{values:["100","200","300","400","500","600","700","800","900"]},"-webkit-text-emphasis":{values:["circle","filled","open","dot","double-circle","triangle","sesame"]},"color-rendering":{values:["optimizeSpeed","optimizeQuality"]},"-webkit-text-combine":{values:["horizontal"]},"text-orientation":{values:["sideways-right"]},outline:{values:["inset","groove","ridge","outset","dotted","dashed","solid","double","medium","thick","thin"]},font:{values:["caption","icon","menu","message-box","small-caption","-webkit-mini-control","-webkit-small-control","-webkit-control","status-bar"]},"dominant-baseline":{values:["text-before-edge","text-after-edge","use-script","no-change","reset-size"]},"-webkit-text-emphasis-position":{values:["over","under"]},"alignment-baseline":{values:["before-edge","after-edge","text-before-edge","text-after-edge","hanging"]},"page-break-before":{values:["left","right","always","avoid"]},"border-image":{values:["repeat","stretch","space","round"]},"text-decoration":{values:["blink","line-through","overline","underline","wavy","double","solid","dashed","dotted"]},"font-family":{values:["serif","sans-serif","cursive","fantasy","monospace","system-ui","emoji","math","fangsong","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","-webkit-body"]},zoom:{values:["normal"]},"max-width":{values:["min-content","max-content","-webkit-fill-available","fit-content"]},"-webkit-font-smoothing":{values:["antialiased","subpixel-antialiased"]},border:{values:["hidden","inset","groove","ridge","outset","dotted","dashed","solid","double","medium","thick","thin"]},"font-variant":{values:["small-caps","normal","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"]},"vertical-align":{values:["top","bottom","-webkit-baseline-middle"]},"page-break-after":{values:["left","right","always","avoid"]},"-webkit-text-emphasis-style":{values:["circle","filled","open","dot","double-circle","triangle","sesame"]},transform:{values:["scale","scaleX","scaleY","scale3d","rotate","rotateX","rotateY","rotateZ","rotate3d","skew","skewX","skewY","translate","translateX","translateY","translateZ","translate3d","matrix","matrix3d","perspective"]},"align-content":{values:["normal","baseline","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end"]},"justify-content":{values:["normal","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end","left","right"]},"place-content":{values:["normal","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end","baseline"]},"align-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"justify-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end","left","right","legacy"]},"place-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"align-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"justify-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end","left","right"]},"place-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"perspective-origin":{values:["left","center","right","top","bottom"]},"transform-origin":{values:["left","center","right","top","bottom"]},"transition-timing-function":{values:["cubic-bezier","steps"]},"animation-timing-function":{values:["cubic-bezier","steps"]},"-webkit-backface-visibility":{values:["visible","hidden"]},"-webkit-column-break-after":{values:["always","avoid"]},"-webkit-column-break-before":{values:["always","avoid"]},"-webkit-column-break-inside":{values:["avoid"]},"-webkit-column-span":{values:["all"]},"-webkit-column-gap":{values:["normal"]},filter:{values:["url","blur","brightness","contrast","drop-shadow","grayscale","hue-rotate","invert","opacity","saturate","sepia"]},"backdrop-filter":{values:["url","blur","brightness","contrast","drop-shadow","grayscale","hue-rotate","invert","opacity","saturate","sepia"]},"mix-blend-mode":{values:["unset"]},"background-blend-mode":{values:["unset"]},"grid-template-columns":{values:["min-content","max-content"]},"grid-template-rows":{values:["min-content","max-content"]},"grid-auto-flow":{values:["dense"]},background:{values:["repeat","repeat-x","repeat-y","no-repeat","top","bottom","left","right","center","fixed","local","scroll","space","round","border-box","content-box","padding-box","linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"background-image":{values:["linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"background-position":{values:["top","bottom","left","right","center"]},"background-position-x":{values:["left","right","center"]},"background-position-y":{values:["top","bottom","center"]},"background-repeat-x":{values:["repeat","no-repeat"]},"background-repeat-y":{values:["repeat","no-repeat"]},"border-bottom":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-left":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-right":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-top":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"buffered-rendering":{values:["static","dynamic"]},"color-interpolation-filters":{values:["srgb","linearrgb"]},"column-rule":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"flex-flow":{values:["nowrap","row","row-reverse","column","column-reverse","wrap","wrap-reverse"]},height:{values:["-webkit-fill-available"]},"inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"list-style":{values:["outside","inside","disc","circle","square","decimal","decimal-leading-zero","arabic-indic","bengali","cambodian","khmer","devanagari","gujarati","gurmukhi","kannada","lao","malayalam","mongolian","myanmar","oriya","persian","urdu","telugu","tibetan","thai","lower-roman","upper-roman","lower-greek","lower-alpha","lower-latin","upper-alpha","upper-latin","cjk-earthly-branch","cjk-heavenly-stem","ethiopic-halehame","ethiopic-halehame-am","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","hangul","hangul-consonant","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","hebrew","armenian","lower-armenian","upper-armenian","georgian","cjk-ideographic","simp-chinese-formal","simp-chinese-informal","trad-chinese-formal","trad-chinese-informal","hiragana","katakana","hiragana-iroha","katakana-iroha"]},"max-block-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"max-inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-block-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"object-position":{values:["top","bottom","left","right","center"]},"shape-outside":{values:["border-box","content-box","padding-box","margin-box"]},"-webkit-appearance":{values:["checkbox","radio","push-button","square-button","button","inner-spin-button","listbox","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","menulist","menulist-button","meter","progress-bar","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","searchfield","searchfield-cancel-button","textfield","textarea"]},"-webkit-border-after":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-after-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-after-width":{values:["medium","thick","thin"]},"-webkit-border-before":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-before-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-before-width":{values:["medium","thick","thin"]},"-webkit-border-end":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-end-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-end-width":{values:["medium","thick","thin"]},"-webkit-border-start":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-start-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-start-width":{values:["medium","thick","thin"]},"-webkit-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-margin-collapse":{values:["collapse","separate","discard"]},"-webkit-mask-box-image":{values:["repeat","stretch","space","round"]},"-webkit-mask-box-image-repeat":{values:["repeat","stretch","space","round"]},"-webkit-mask-clip":{values:["text","border","border-box","content","content-box","padding","padding-box"]},"-webkit-mask-composite":{values:["clear","copy","source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","xor","plus-lighter"]},"-webkit-mask-image":{values:["linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"-webkit-mask-origin":{values:["border","border-box","content","content-box","padding","padding-box"]},"-webkit-mask-position":{values:["top","bottom","left","right","center"]},"-webkit-mask-position-x":{values:["left","right","center"]},"-webkit-mask-position-y":{values:["top","bottom","center"]},"-webkit-mask-repeat":{values:["repeat","repeat-x","repeat-y","no-repeat","space","round"]},"-webkit-mask-size":{values:["contain","cover"]},"-webkit-max-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-max-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-min-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-min-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-perspective-origin-x":{values:["left","right","center"]},"-webkit-perspective-origin-y":{values:["top","bottom","center"]},"-webkit-text-decorations-in-effect":{values:["blink","line-through","overline","underline"]},"-webkit-text-stroke":{values:["medium","thick","thin"]},"-webkit-text-stroke-width":{values:["medium","thick","thin"]},"-webkit-transform-origin-x":{values:["left","right","center"]},"-webkit-transform-origin-y":{values:["top","bottom","center"]},width:{values:["-webkit-fill-available"]}},P=new Map([["align-content",57],["align-items",129],["align-self",55],["animation",175],["animation-delay",114],["animation-direction",113],["animation-duration",137],["animation-fill-mode",132],["animation-iteration-count",124],["animation-name",139],["animation-play-state",104],["animation-timing-function",141],["backface-visibility",123],["background",260],["background-attachment",119],["background-clip",165],["background-color",259],["background-image",246],["background-origin",107],["background-position",237],["background-position-x",108],["background-position-y",93],["background-repeat",234],["background-size",203],["border",263],["border-bottom",233],["border-bottom-color",190],["border-bottom-left-radius",186],["border-bottom-right-radius",185],["border-bottom-style",150],["border-bottom-width",179],["border-collapse",209],["border-color",226],["border-image",89],["border-image-outset",50],["border-image-repeat",49],["border-image-slice",58],["border-image-source",32],["border-image-width",52],["border-left",221],["border-left-color",174],["border-left-style",142],["border-left-width",172],["border-radius",224],["border-right",223],["border-right-color",182],["border-right-style",130],["border-right-width",178],["border-spacing",198],["border-style",206],["border-top",231],["border-top-color",192],["border-top-left-radius",187],["border-top-right-radius",189],["border-top-style",152],["border-top-width",180],["border-width",214],["bottom",227],["box-shadow",213],["box-sizing",216],["caption-side",96],["clear",229],["clip",173],["clip-rule",5],["color",256],["content",219],["counter-increment",111],["counter-reset",110],["cursor",250],["direction",176],["display",262],["empty-cells",99],["fill",140],["fill-opacity",82],["fill-rule",22],["filter",160],["flex",133],["flex-basis",66],["flex-direction",85],["flex-flow",94],["flex-grow",112],["flex-shrink",61],["flex-wrap",68],["float",252],["font",211],["font-family",254],["font-kerning",18],["font-size",264],["font-stretch",77],["font-style",220],["font-variant",161],["font-weight",257],["height",266],["image-rendering",90],["justify-content",127],["left",248],["letter-spacing",188],["line-height",244],["list-style",215],["list-style-image",145],["list-style-position",149],["list-style-type",199],["margin",267],["margin-bottom",241],["margin-left",243],["margin-right",238],["margin-top",253],["mask",20],["max-height",205],["max-width",225],["min-height",217],["min-width",218],["object-fit",33],["opacity",251],["order",117],["orphans",146],["outline",222],["outline-color",153],["outline-offset",147],["outline-style",151],["outline-width",148],["overflow",255],["overflow-wrap",105],["overflow-x",184],["overflow-y",196],["padding",265],["padding-bottom",230],["padding-left",235],["padding-right",232],["padding-top",240],["page",8],["page-break-after",120],["page-break-before",69],["page-break-inside",121],["perspective",92],["perspective-origin",103],["pointer-events",183],["position",261],["quotes",158],["resize",168],["right",245],["shape-rendering",38],["size",64],["speak",118],["src",170],["stop-color",42],["stop-opacity",31],["stroke",98],["stroke-dasharray",36],["stroke-dashoffset",3],["stroke-linecap",30],["stroke-linejoin",21],["stroke-miterlimit",12],["stroke-opacity",34],["stroke-width",87],["table-layout",171],["tab-size",46],["text-align",260],["text-anchor",35],["text-decoration",247],["text-indent",207],["text-overflow",204],["text-rendering",155],["text-shadow",208],["text-transform",202],["top",258],["touch-action",80],["transform",181],["transform-origin",162],["transform-style",86],["transition",193],["transition-delay",134],["transition-duration",135],["transition-property",131],["transition-timing-function",122],["unicode-bidi",156],["unicode-range",136],["vertical-align",236],["visibility",242],["-webkit-appearance",191],["-webkit-backface-visibility",154],["-webkit-background-clip",164],["-webkit-background-origin",40],["-webkit-background-size",163],["-webkit-border-end",9],["-webkit-border-horizontal-spacing",81],["-webkit-border-image",75],["-webkit-border-radius",212],["-webkit-border-start",10],["-webkit-border-start-color",16],["-webkit-border-start-width",13],["-webkit-border-vertical-spacing",43],["-webkit-box-align",101],["-webkit-box-direction",51],["-webkit-box-flex",128],["-webkit-box-ordinal-group",91],["-webkit-box-orient",144],["-webkit-box-pack",106],["-webkit-box-reflect",39],["-webkit-box-shadow",210],["-webkit-column-break-inside",60],["-webkit-column-count",84],["-webkit-column-gap",76],["-webkit-column-rule",25],["-webkit-column-rule-color",23],["-webkit-columns",44],["-webkit-column-span",29],["-webkit-column-width",47],["-webkit-filter",159],["-webkit-font-feature-settings",59],["-webkit-font-smoothing",177],["-webkit-highlight",1],["-webkit-line-break",45],["-webkit-line-clamp",126],["-webkit-margin-after",67],["-webkit-margin-before",70],["-webkit-margin-collapse",14],["-webkit-margin-end",65],["-webkit-margin-start",100],["-webkit-margin-top-collapse",78],["-webkit-mask",19],["-webkit-mask-box-image",72],["-webkit-mask-image",88],["-webkit-mask-position",54],["-webkit-mask-repeat",63],["-webkit-mask-size",79],["-webkit-padding-after",15],["-webkit-padding-before",28],["-webkit-padding-end",48],["-webkit-padding-start",73],["-webkit-print-color-adjust",83],["-webkit-rtl-ordering",7],["-webkit-tap-highlight-color",169],["-webkit-text-emphasis-color",11],["-webkit-text-fill-color",71],["-webkit-text-security",17],["-webkit-text-stroke",56],["-webkit-text-stroke-color",37],["-webkit-text-stroke-width",53],["-webkit-user-drag",95],["-webkit-user-modify",62],["-webkit-user-select",194],["-webkit-writing-mode",4],["white-space",228],["widows",115],["width",268],["will-change",74],["word-break",166],["word-spacing",157],["word-wrap",197],["writing-mode",41],["z-index",239],["zoom",200]]),L=["auto","none"];var E=Object.freeze({__proto__:null,CSSMetadata:m,VariableRegex:f,CustomVariableRegex:/(var\(*--[\w\d]+-([\w]+-[\w]+)\))/g,URLRegex:/url\(\s*('.+?'|".+?"|[^)]+)\s*\)/g,GridAreaRowRegex:b,cssMetadata:v});class A{callFrame;callUID;self;total;id;parent;children;functionName;depth;deoptReason;#h;constructor(e,t){this.callFrame=e,this.callUID=`${e.functionName}@${e.scriptId}:${e.lineNumber}:${e.columnNumber}`,this.self=0,this.total=0,this.id=0,this.functionName=e.functionName,this.parent=null,this.children=[],this.#h=t}get scriptId(){return String(this.callFrame.scriptId)}get url(){return this.callFrame.url}get lineNumber(){return this.callFrame.lineNumber}get columnNumber(){return this.callFrame.columnNumber}setFunctionName(e){null!==e&&(this.functionName=e)}target(){return this.#h}}class O{#e;root;total;maxDepth;constructor(e){this.#e=e||null}initialize(e){this.root=e,this.assignDepthsAndParents(),this.total=this.calculateTotals(this.root)}assignDepthsAndParents(){const e=this.root;e.depth=-1,e.parent=null,this.maxDepth=0;const t=[e];for(;t.length;){const e=t.pop(),n=e.depth+1;n>this.maxDepth&&(this.maxDepth=n);const r=e.children;for(const s of r)s.depth=n,s.parent=e,s.children.length&&t.push(s)}}calculateTotals(e){const t=[e],n=[];for(;t.length;){const e=t.pop();e.total=e.self,n.push(e),t.push(...e.children)}for(;n.length>1;){const e=n.pop();e.parent&&(e.parent.total+=e.total)}return e.total}target(){return this.#e}}var N=Object.freeze({__proto__:null,ProfileNode:A,ProfileTreeModel:O});class F{#u;#g;#p;#m;#f;#b;#y;constructor(e,t,n,r){this.#u=e,this.#g=t,this.#p=n,this.#m={},this.#f=0,this.#b=r||"Medium",this.#y=null}static fromProtocolCookie(e){const t=new F(e.name,e.value,null,e.priority);return t.addAttribute("domain",e.domain),t.addAttribute("path",e.path),e.expires&&t.addAttribute("expires",1e3*e.expires),e.httpOnly&&t.addAttribute("httpOnly"),e.secure&&t.addAttribute("secure"),e.sameSite&&t.addAttribute("sameSite",e.sameSite),"sourcePort"in e&&t.addAttribute("sourcePort",e.sourcePort),"sourceScheme"in e&&t.addAttribute("sourceScheme",e.sourceScheme),"partitionKey"in e&&t.addAttribute("partitionKey",e.partitionKey),"partitionKeyOpaque"in e&&t.addAttribute("partitionKey",""),t.setSize(e.size),t}key(){return(this.domain()||"-")+" "+this.name()+" "+(this.path()||"-")}name(){return this.#u}value(){return this.#g}type(){return this.#p}httpOnly(){return"httponly"in this.#m}secure(){return"secure"in this.#m}sameSite(){return this.#m.samesite}partitionKey(){return this.#m.partitionkey}setPartitionKey(e){this.addAttribute("partitionKey",e)}partitionKeyOpaque(){return""===this.#m.partitionkey}setPartitionKeyOpaque(){this.addAttribute("partitionKey","")}priority(){return this.#b}session(){return!("expires"in this.#m||"max-age"in this.#m)}path(){return this.#m.path}domain(){return this.#m.domain}expires(){return this.#m.expires}maxAge(){return this.#m["max-age"]}sourcePort(){return this.#m.sourceport}sourceScheme(){return this.#m.sourcescheme}size(){return this.#f}url(){if(!this.domain()||!this.path())return null;let e="";const t=this.sourcePort();return t&&80!==t&&443!==t&&(e=`:${this.sourcePort()}`),(this.secure()?"https://":"http://")+this.domain()+e+this.path()}setSize(e){this.#f=e}expiresDate(e){return this.maxAge()?new Date(e.getTime()+1e3*this.maxAge()):this.expires()?new Date(this.expires()):null}addAttribute(e,t){const n=e.toLowerCase();if("priority"===n)this.#b=t;else this.#m[n]=t}setCookieLine(e){this.#y=e}getCookieLine(){return this.#y}matchesSecurityOrigin(e){const t=new URL(e).hostname;return F.isDomainMatch(this.domain(),t)}static isDomainMatch(e,t){return t===e||!(!e||"."!==e[0])&&(e.substr(1)===t||t.length>e.length&&t.endsWith(e))}}var B,D;!function(e){e[e.Request=0]="Request",e[e.Response=1]="Response"}(B||(B={})),function(e){e.Name="name",e.Value="value",e.Size="size",e.Domain="domain",e.Path="path",e.Expires="expires",e.HttpOnly="httpOnly",e.Secure="secure",e.SameSite="sameSite",e.SourceScheme="sourceScheme",e.SourcePort="sourcePort",e.Priority="priority",e.PartitionKey="partitionKey"}(D||(D={}));var U=Object.freeze({__proto__:null,Cookie:F,get Type(){return B},get Attributes(){return D}});class H{#v;#I;#k;#S;#w;#C;#T;constructor(e){e&&(this.#v=e.toLowerCase().replace(/^\./,"")),this.#I=[],this.#S=0}static parseSetCookie(e,t){return new H(t).parseSetCookie(e)}cookies(){return this.#I}parseSetCookie(e){if(!this.initialize(e))return null;for(let e=this.extractKeyValue();e;e=this.extractKeyValue())this.#w?this.#w.addAttribute(e.key,e.value):this.addCookie(e,B.Response),this.advanceAndCheckCookieDelimiter()&&this.flushCookie();return this.flushCookie(),this.#I}initialize(e){return this.#k=e,"string"==typeof e&&(this.#I=[],this.#w=null,this.#C="",this.#S=this.#k.length,!0)}flushCookie(){this.#w&&(this.#w.setSize(this.#S-this.#k.length-this.#T),this.#w.setCookieLine(this.#C.replace("\n",""))),this.#w=null,this.#C=""}extractKeyValue(){if(!this.#k||!this.#k.length)return null;const e=/^[ \t]*([^=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this.#k);if(!e)return console.error("Failed parsing cookie header before: "+this.#k),null;const t=new q(e[1]&&e[1].trim(),e[2]&&e[2].trim(),this.#S-this.#k.length);return this.#C+=e[0],this.#k=this.#k.slice(e[0].length),t}advanceAndCheckCookieDelimiter(){if(!this.#k)return!1;const e=/^\s*[\n;]\s*/.exec(this.#k);return!!e&&(this.#C+=e[0],this.#k=this.#k.slice(e[0].length),null!==e[0].match("\n"))}addCookie(e,t){this.#w&&this.#w.setSize(e.position-this.#T),this.#w="string"==typeof e.value?new F(e.key,e.value,t):new F("",e.key,t),this.#v&&this.#w.addAttribute("domain",this.#v),this.#T=e.position,this.#I.push(this.#w)}}class q{key;value;position;constructor(e,t,n){this.key=e,this.value=t,this.position=n}}var _,z,j=Object.freeze({__proto__:null,CookieParser:H});class W extends a.InspectorBackend.TargetBase{#R;#u;#x;#M;#P;#p;#L;#E;#A;#O;#N;#F;constructor(e,n,r,s,i,a,o,l,d){switch(super(s===_.Node,i,a,l),this.#R=e,this.#u=r,this.#x=t.DevToolsPath.EmptyUrlString,this.#M="",this.#P=0,s){case _.Frame:this.#P=z.Browser|z.Storage|z.DOM|z.JS|z.Log|z.Network|z.Target|z.Tracing|z.Emulation|z.Input|z.Inspector|z.Audits|z.WebAuthn|z.IO|z.Media,i?.type()!==_.Frame&&(this.#P|=z.DeviceEmulation|z.ScreenCapture|z.Security|z.ServiceWorker,d?.url.startsWith("chrome-extension://")&&(this.#P&=~z.Security));break;case _.ServiceWorker:this.#P=z.JS|z.Log|z.Network|z.Target|z.Inspector|z.IO,i?.type()!==_.Frame&&(this.#P|=z.Browser);break;case _.SharedWorker:this.#P=z.JS|z.Log|z.Network|z.Target|z.IO|z.Media|z.Inspector;break;case _.Worker:this.#P=z.JS|z.Log|z.Network|z.Target|z.IO|z.Media|z.Emulation;break;case _.Node:this.#P=z.JS;break;case _.AuctionWorklet:this.#P=z.JS|z.EventBreakpoints;break;case _.Browser:this.#P=z.Target|z.IO;break;case _.Tab:this.#P=z.Target}this.#p=s,this.#L=i,this.#E=n,this.#A=new Map,this.#O=o,this.#N=d}createModels(e){this.#F=!0;const t=Array.from(c.registeredModels.entries());for(const[e,n]of t)n.early&&this.model(e);for(const[n,r]of t)(r.autostart||e.has(n))&&this.model(n);this.#F=!1}id(){return this.#E}name(){return this.#u||this.#M}setName(e){this.#u!==e&&(this.#u=e,this.#R.onNameChange(this))}type(){return this.#p}markAsNodeJSForTest(){super.markAsNodeJSForTest(),this.#p=_.Node}targetManager(){return this.#R}hasAllCapabilities(e){return(this.#P&e)===e}decorateLabel(e){return this.#p===_.Worker||this.#p===_.ServiceWorker?"⚙ "+e:e}parentTarget(){return this.#L}outermostTarget(){let e=null,t=this;do{t.type()!==_.Tab&&t.type()!==_.Browser&&(e=t),t=t.parentTarget()}while(t);return e}dispose(e){super.dispose(e),this.#R.removeTarget(this);for(const e of this.#A.values())e.dispose()}model(e){if(!this.#A.get(e)){const t=c.registeredModels.get(e);if(void 0===t)throw"Model class is not registered @"+(new Error).stack;if((this.#P&t.capabilities)===t.capabilities){const t=new e(this);this.#A.set(e,t),this.#F||this.#R.modelAdded(this,e,t,this.#R.isInScope(this))}}return this.#A.get(e)||null}models(){return this.#A}inspectedURL(){return this.#x}setInspectedURL(n){this.#x=n;const r=e.ParsedURL.ParsedURL.fromString(n);this.#M=r?r.lastPathComponentWithFragment():"#"+this.#E,this.parentTarget()?.type()!==_.Frame&&i.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(n||t.DevToolsPath.EmptyUrlString),this.#R.onInspectedURLChange(this),this.#u||this.#R.onNameChange(this)}async suspend(e){this.#O||(this.#O=!0,await Promise.all(Array.from(this.models().values(),(t=>t.preSuspendModel(e)))),await Promise.all(Array.from(this.models().values(),(t=>t.suspendModel(e)))))}async resume(){this.#O&&(this.#O=!1,await Promise.all(Array.from(this.models().values(),(e=>e.resumeModel()))),await Promise.all(Array.from(this.models().values(),(e=>e.postResumeModel()))))}suspended(){return this.#O}updateTargetInfo(e){this.#N=e}targetInfo(){return this.#N}}!function(e){e.Frame="frame",e.ServiceWorker="service-worker",e.Worker="worker",e.SharedWorker="shared-worker",e.Node="node",e.Browser="browser",e.AuctionWorklet="auction-worklet",e.Tab="tab"}(_||(_={})),function(e){e[e.Browser=1]="Browser",e[e.DOM=2]="DOM",e[e.JS=4]="JS",e[e.Log=8]="Log",e[e.Network=16]="Network",e[e.Target=32]="Target",e[e.ScreenCapture=64]="ScreenCapture",e[e.Tracing=128]="Tracing",e[e.Emulation=256]="Emulation",e[e.Security=512]="Security",e[e.Input=1024]="Input",e[e.Inspector=2048]="Inspector",e[e.DeviceEmulation=4096]="DeviceEmulation",e[e.Storage=8192]="Storage",e[e.ServiceWorker=16384]="ServiceWorker",e[e.Audits=32768]="Audits",e[e.WebAuthn=65536]="WebAuthn",e[e.IO=131072]="IO",e[e.Media=262144]="Media",e[e.EventBreakpoints=524288]="EventBreakpoints",e[e.None=0]="None"}(z||(z={}));var V=Object.freeze({__proto__:null,Target:W,get Type(){return _},get Capability(){return z}});let G;class K extends e.ObjectWrapper.ObjectWrapper{#B;#D;#U;#H;#q;#O;#_;#z;#j;#W;constructor(){super(),this.#B=new Set,this.#D=new Set,this.#U=new t.MapUtilities.Multimap,this.#H=new t.MapUtilities.Multimap,this.#O=!1,this.#_=null,this.#z=null,this.#q=new WeakSet,this.#j=!1,this.#W=new Set}static instance({forceNew:e}={forceNew:!1}){return G&&!e||(G=new K),G}static removeInstance(){G=void 0}onInspectedURLChange(e){this.dispatchEventToListeners($.InspectedURLChanged,e)}onNameChange(e){this.dispatchEventToListeners($.NameChanged,e)}async suspendAllTargets(e){if(this.#O)return;this.#O=!0,this.dispatchEventToListeners($.SuspendStateChanged);const t=Array.from(this.#B.values(),(t=>t.suspend(e)));await Promise.all(t)}async resumeAllTargets(){if(!this.#O)return;this.#O=!1,this.dispatchEventToListeners($.SuspendStateChanged);const e=Array.from(this.#B.values(),(e=>e.resume()));await Promise.all(e)}allTargetsSuspended(){return this.#O}models(e,t){const n=[];for(const r of this.#B){if(t?.scoped&&!this.isInScope(r))continue;const s=r.model(e);s&&n.push(s)}return n}inspectedURL(){const e=this.primaryPageTarget();return e?e.inspectedURL():""}observeModels(e,t,n){const r=this.models(e,n);this.#H.set(e,t),n?.scoped&&this.#q.add(t);for(const e of r)t.modelAdded(e)}unobserveModels(e,t){this.#H.delete(e,t),this.#q.delete(t)}modelAdded(e,t,n,r){for(const e of this.#H.get(t).values())this.#q.has(e)&&!r||e.modelAdded(n)}modelRemoved(e,t,n,r){for(const e of this.#H.get(t).values())this.#q.has(e)&&!r||e.modelRemoved(n)}addModelListener(e,t,n,r,s){const i=e=>{s?.scoped&&!this.isInScope(e)||n.call(r,e)};for(const n of this.models(e))n.addEventListener(t,i);this.#U.set(t,{modelClass:e,thisObject:r,listener:n,wrappedListener:i})}removeModelListener(e,t,n,r){if(!this.#U.has(t))return;let s=null;for(const i of this.#U.get(t))i.modelClass===e&&i.listener===n&&i.thisObject===r&&(s=i.wrappedListener,this.#U.delete(t,i));if(s)for(const n of this.models(e))n.removeEventListener(t,s)}observeTargets(e,t){if(this.#D.has(e))throw new Error("Observer can only be registered once");t?.scoped&&this.#q.add(e);for(const n of this.#B)t?.scoped&&!this.isInScope(n)||e.targetAdded(n);this.#D.add(e)}unobserveTargets(e){this.#D.delete(e),this.#q.delete(e)}createTarget(e,t,n,r,s,i,a,o){const l=new W(this,e,t,n,r,s||"",this.#O,a||null,o);i&&l.pageAgent().invoke_waitForDebugger(),l.createModels(new Set(this.#H.keysArray())),this.#B.add(l);const d=this.isInScope(l);for(const e of[...this.#D])this.#q.has(e)&&!d||e.targetAdded(l);for(const[e,t]of l.models().entries())this.modelAdded(l,e,t,d);for(const e of this.#U.keysArray())for(const t of this.#U.get(e)){const n=l.model(t.modelClass);n&&n.addEventListener(e,t.wrappedListener)}return l!==l.outermostTarget()||l.type()===_.Frame&&l!==this.primaryPageTarget()||this.#j||this.setScopeTarget(l),l}removeTarget(e){if(!this.#B.has(e))return;const t=this.isInScope(e);this.#B.delete(e);for(const r of e.models().keys()){const s=e.models().get(r);n(s),this.modelRemoved(e,r,s,t)}for(const n of[...this.#D])this.#q.has(n)&&!t||n.targetRemoved(e);for(const t of this.#U.keysArray())for(const n of this.#U.get(t)){const r=e.model(n.modelClass);r&&r.removeEventListener(t,n.wrappedListener)}}targets(){return[...this.#B]}targetById(e){return this.targets().find((t=>t.id()===e))||null}rootTarget(){return this.#B.size?this.#B.values().next().value:null}primaryPageTarget(){let e=this.rootTarget();return e?.type()===_.Tab&&(e=this.targets().find((t=>t.parentTarget()===e&&t.type()===_.Frame&&!t.targetInfo()?.subtype?.length))||null),e}browserTarget(){return this.#_}async maybeAttachInitialTarget(){if(!Boolean(o.Runtime.Runtime.queryParam("browserConnection")))return!1;this.#_||(this.#_=new W(this,"main","browser",_.Browser,null,"",!1,null,void 0),this.#_.createModels(new Set(this.#H.keysArray())));const e=await i.InspectorFrontendHost.InspectorFrontendHostInstance.initialTargetId();return this.#_.targetAgent().invoke_autoAttachRelated({targetId:e,waitForDebuggerOnStart:!0}),!0}clearAllTargetsForTest(){this.#B.clear()}isInScope(e){if(!e)return!1;for(function(e){return"source"in e&&e.source instanceof c}(e)&&(e=e.source),e instanceof c&&(e=e.target());e&&e!==this.#z;)e=e.parentTarget();return Boolean(e)&&e===this.#z}setScopeTarget(e){if(e!==this.#z){for(const e of this.targets())if(this.isInScope(e)){for(const t of this.#H.keysArray()){const n=e.models().get(t);if(n)for(const e of[...this.#H.get(t)].filter((e=>this.#q.has(e))))e.modelRemoved(n)}for(const t of[...this.#D].filter((e=>this.#q.has(e))))t.targetRemoved(e)}this.#z=e;for(const e of this.targets())if(this.isInScope(e)){for(const t of[...this.#D].filter((e=>this.#q.has(e))))t.targetAdded(e);for(const[t,n]of e.models().entries())for(const e of[...this.#H.get(t)].filter((e=>this.#q.has(e))))e.modelAdded(n)}for(const e of this.#W)e()}}addScopeChangeListener(e){this.#W.add(e)}removeScopeChangeListener(e){this.#W.delete(e)}scopeTarget(){return this.#z}}var $;!function(e){e.AvailableTargetsChanged="AvailableTargetsChanged",e.InspectedURLChanged="InspectedURLChanged",e.NameChanged="NameChanged",e.SuspendStateChanged="SuspendStateChanged"}($||($={}));var Q=Object.freeze({__proto__:null,TargetManager:K,get Events(){return $},Observer:class{targetAdded(e){}targetRemoved(e){}},SDKModelObserver:class{modelAdded(e){}modelRemoved(e){}}});const X={noContentForWebSocket:"Content for WebSockets is currently not supported",noContentForRedirect:"No content available because this request was redirected",noContentForPreflight:"No content available for preflight request",noThrottling:"No throttling",offline:"Offline",slowG:"Slow 3G",fastG:"Fast 3G",requestWasBlockedByDevtoolsS:'Request was blocked by DevTools: "{PH1}"',crossoriginReadBlockingCorb:"Cross-Origin Read Blocking (CORB) blocked cross-origin response {PH1} with MIME type {PH2}. See https://www.chromestatus.com/feature/5629709824032768 for more details.",sFailedLoadingSS:'{PH1} failed loading: {PH2} "{PH3}".',sFinishedLoadingSS:'{PH1} finished loading: {PH2} "{PH3}".'},J=s.i18n.registerUIStrings("core/sdk/NetworkManager.ts",X),Y=s.i18n.getLocalizedString.bind(void 0,J),Z=s.i18n.getLazilyComputedLocalizedString.bind(void 0,J),ee=new WeakMap,te=new Map([["2g","cellular2g"],["3g","cellular3g"],["4g","cellular4g"],["bluetooth","bluetooth"],["wifi","wifi"],["wimax","wimax"]]);class ne extends c{dispatcher;fetchDispatcher;#V;#G;constructor(t){super(t),this.dispatcher=new ce(this),this.fetchDispatcher=new de(t.fetchAgent(),this),this.#V=t.networkAgent(),t.registerNetworkDispatcher(this.dispatcher),t.registerFetchDispatcher(this.fetchDispatcher),e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()&&this.#V.invoke_setCacheDisabled({cacheDisabled:!0}),this.#V.invoke_enable({maxPostDataSize:le}),this.#V.invoke_setAttachDebugStack({enabled:!0}),this.#G=e.Settings.Settings.instance().createSetting("bypassServiceWorker",!1),this.#G.get()&&this.bypassServiceWorkerChanged(),this.#G.addChangeListener(this.bypassServiceWorkerChanged,this),e.Settings.Settings.instance().moduleSetting("cacheDisabled").addChangeListener(this.cacheDisabledSettingChanged,this)}static forRequest(e){return ee.get(e)||null}static canReplayRequest(t){return Boolean(ee.get(t))&&Boolean(t.backendRequestId())&&!t.isRedirect()&&t.resourceType()===e.ResourceType.resourceTypes.XHR}static replayRequest(e){const t=ee.get(e),n=e.backendRequestId();t&&n&&!e.isRedirect()&&t.#V.invoke_replayXHR({requestId:n})}static async searchInRequest(e,t,n,r){const s=ne.forRequest(e),i=e.backendRequestId();if(!s||!i||e.isRedirect())return[];return(await s.#V.invoke_searchInResponseBody({requestId:i,query:t,caseSensitive:n,isRegex:r})).result||[]}static async requestContentData(t){if(t.resourceType()===e.ResourceType.resourceTypes.WebSocket)return{error:Y(X.noContentForWebSocket),content:null,encoded:!1};if(t.finished||await t.once(Te.FinishedLoading),t.isRedirect())return{error:Y(X.noContentForRedirect),content:null,encoded:!1};if(t.isPreflightRequest())return{error:Y(X.noContentForPreflight),content:null,encoded:!1};const n=ne.forRequest(t);if(!n)return{error:"No network manager for request",content:null,encoded:!1};const r=t.backendRequestId();if(!r)return{error:"No backend request id for request",content:null,encoded:!1};const s=await n.#V.invoke_getResponseBody({requestId:r}),i=s.getError()||null;return{error:i,content:i?null:s.body,encoded:s.base64Encoded}}static async requestPostData(e){const t=ne.forRequest(e);if(!t)return console.error("No network manager for request"),null;const n=e.backendRequestId();if(!n)return console.error("No backend request id for request"),null;try{const{postData:e}=await t.#V.invoke_getRequestPostData({requestId:n});return e}catch(e){return e.message}}static connectionType(e){if(!e.download&&!e.upload)return"none";const t="function"==typeof e.title?e.title().toLowerCase():e.title.toLowerCase();for(const[e,n]of te)if(t.includes(e))return n;return"other"}static lowercaseHeaders(e){const t={};for(const n in e)t[n.toLowerCase()]=e[n];return t}requestForURL(e){return this.dispatcher.requestForURL(e)}requestForId(e){return this.dispatcher.requestForId(e)}requestForLoaderId(e){return this.dispatcher.requestForLoaderId(e)}cacheDisabledSettingChanged({data:e}){this.#V.invoke_setCacheDisabled({cacheDisabled:e})}dispose(){e.Settings.Settings.instance().moduleSetting("cacheDisabled").removeChangeListener(this.cacheDisabledSettingChanged,this)}bypassServiceWorkerChanged(){this.#V.invoke_setBypassServiceWorker({bypass:this.#G.get()})}async getSecurityIsolationStatus(e){const t=await this.#V.invoke_getSecurityIsolationStatus({frameId:e??void 0});return t.getError()?null:t.status}async enableReportingApi(e=!0){return this.#V.invoke_enableReportingApi({enable:e})}async loadNetworkResource(e,t,n){const r=await this.#V.invoke_loadNetworkResource({frameId:e??void 0,url:t,options:n});if(r.getError())throw new Error(r.getError());return r.resource}clearRequests(){this.dispatcher.clearRequests()}}var re;!function(e){e.RequestStarted="RequestStarted",e.RequestUpdated="RequestUpdated",e.RequestFinished="RequestFinished",e.RequestUpdateDropped="RequestUpdateDropped",e.ResponseReceived="ResponseReceived",e.MessageGenerated="MessageGenerated",e.RequestRedirected="RequestRedirected",e.LoadingFinished="LoadingFinished",e.ReportingApiReportAdded="ReportingApiReportAdded",e.ReportingApiReportUpdated="ReportingApiReportUpdated",e.ReportingApiEndpointsChangedForOrigin="ReportingApiEndpointsChangedForOrigin"}(re||(re={}));const se={title:Z(X.noThrottling),i18nTitleKey:X.noThrottling,download:-1,upload:-1,latency:0},ie={title:Z(X.offline),i18nTitleKey:X.offline,download:0,upload:0,latency:0},ae={title:Z(X.slowG),i18nTitleKey:X.slowG,download:5e4,upload:5e4,latency:2e3},oe={title:Z(X.fastG),i18nTitleKey:X.fastG,download:18e4,upload:84375,latency:562.5},le=65536;class de{#K;#$;constructor(e,t){this.#K=e,this.#$=t}requestPaused({requestId:e,request:t,resourceType:n,responseStatusCode:r,responseHeaders:s,networkId:i}){const a=i?this.#$.requestForId(i):null;0===a?.originalResponseHeaders.length&&s&&(a.originalResponseHeaders=s),ue.instance().requestIntercepted(new ge(this.#K,t,n,e,a,r,s))}authRequired({}){}}class ce{#$;#Q;#X;#J;#Y;#Z;constructor(e){this.#$=e,this.#Q=new Map,this.#X=new Map,this.#J=new Map,this.#Y=new Map,this.#Z=new Map,ue.instance().addEventListener(ue.Events.RequestIntercepted,this.#ee.bind(this))}#ee(e){const t=this.requestForId(e.data);t&&t.setWasIntercepted(!0)}headersMapToHeadersArray(e){const t=[];for(const n in e){const r=e[n].split("\n");for(let e=0;e=0&&t.setTransferSize(n.encodedDataLength),n.requestHeaders&&!t.hasExtraRequestInfo()&&(t.setRequestHeaders(this.headersMapToHeadersArray(n.requestHeaders)),t.setRequestHeadersText(n.requestHeadersText||"")),t.connectionReused=n.connectionReused,t.connectionId=String(n.connectionId),n.remoteIPAddress&&t.setRemoteAddress(n.remoteIPAddress,n.remotePort||-1),n.fromServiceWorker&&(t.fetchedViaServiceWorker=!0),n.fromDiskCache&&t.setFromDiskCache(),n.fromPrefetchCache&&t.setFromPrefetchCache(),n.cacheStorageCacheName&&t.setResponseCacheStorageCacheName(n.cacheStorageCacheName),n.responseTime&&t.setResponseRetrievalTime(new Date(n.responseTime)),t.timing=n.timing,t.protocol=n.protocol||"",t.alternateProtocolUsage=n.alternateProtocolUsage,n.serviceWorkerResponseSource&&t.setServiceWorkerResponseSource(n.serviceWorkerResponseSource),t.setSecurityState(n.securityState),n.securityDetails&&t.setSecurityDetails(n.securityDetails);const r=e.ResourceType.ResourceType.fromMimeTypeOverride(t.mimeType);r&&t.setResourceType(r)}requestForId(e){return this.#Q.get(e)||null}requestForURL(e){return this.#X.get(e)||null}requestForLoaderId(e){return this.#J.get(e)||null}resourceChangedPriority({requestId:e,newPriority:t}){const n=this.#Q.get(e);n&&n.setPriority(t)}signedExchangeReceived({requestId:t,info:n}){let r=this.#Q.get(t);(r||(r=this.#X.get(n.outerResponse.url),r))&&(r.setSignedExchangeInfo(n),r.setResourceType(e.ResourceType.resourceTypes.SignedExchange),this.updateNetworkRequestWithResponse(r,n.outerResponse),this.updateNetworkRequest(r),this.#$.dispatchEventToListeners(re.ResponseReceived,{request:r,response:n.outerResponse}))}requestWillBeSent({requestId:t,loaderId:n,documentURL:r,request:s,timestamp:i,wallTime:a,initiator:o,redirectResponse:l,type:d,frameId:c,hasUserGesture:h}){let u=this.#Q.get(t);if(u){if(!l)return;u.signedExchangeInfo()||this.responseReceived({requestId:t,loaderId:n,timestamp:i,type:d||"Other",response:l,hasExtraInfo:!1,frameId:c}),u=this.appendRedirect(t,i,s.url),this.#$.dispatchEventToListeners(re.RequestRedirected,u)}else u=Me.create(t,s.url,r,c??null,n,o,h),ee.set(u,this.#$);u.hasNetworkData=!0,this.updateNetworkRequestWithRequest(u,s),u.setIssueTime(i,a),u.setResourceType(d?e.ResourceType.resourceTypes[d]:e.ResourceType.resourceTypes.Other),s.trustTokenParams&&u.setTrustTokenParams(s.trustTokenParams);const g=this.#Z.get(t);g&&(u.setTrustTokenOperationDoneEvent(g),this.#Z.delete(t)),this.getExtraInfoBuilder(t).addRequest(u),this.startNetworkRequest(u,s)}requestServedFromCache({requestId:e}){const t=this.#Q.get(e);t&&t.setFromMemoryCache()}responseReceived({requestId:t,loaderId:n,timestamp:r,type:s,response:i,frameId:a}){const o=this.#Q.get(t),l=ne.lowercaseHeaders(i.headers);if(o)o.responseReceivedTime=r,o.setResourceType(e.ResourceType.resourceTypes[s]),this.updateNetworkRequestWithResponse(o,i),this.updateNetworkRequest(o),this.#$.dispatchEventToListeners(re.ResponseReceived,{request:o,response:i});else{const e=l["last-modified"],t={url:i.url,frameId:a??null,loaderId:n,resourceType:s,mimeType:i.mimeType,lastModified:e?new Date(e):null};this.#$.dispatchEventToListeners(re.RequestUpdateDropped,t)}}dataReceived({requestId:e,timestamp:t,dataLength:n,encodedDataLength:r}){let s=this.#Q.get(e);s||(s=this.maybeAdoptMainResourceRequest(e)),s&&(s.resourceSize+=n,-1!==r&&s.increaseTransferSize(r),s.endTime=t,this.updateNetworkRequest(s))}loadingFinished({requestId:e,timestamp:t,encodedDataLength:n,shouldReportCorbBlocking:r}){let s=this.#Q.get(e);s||(s=this.maybeAdoptMainResourceRequest(e)),s&&(this.getExtraInfoBuilder(e).finished(),this.finishNetworkRequest(s,t,n,r),this.#$.dispatchEventToListeners(re.LoadingFinished,s))}loadingFailed({requestId:t,timestamp:n,type:r,errorText:s,canceled:i,blockedReason:a,corsErrorStatus:o}){const l=this.#Q.get(t);if(l){if(l.failed=!0,l.setResourceType(e.ResourceType.resourceTypes[r]),l.canceled=Boolean(i),a&&(l.setBlockedReason(a),"inspector"===a)){const e=Y(X.requestWasBlockedByDevtoolsS,{PH1:l.url()});this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t,warning:!0})}o&&l.setCorsErrorStatus(o),l.localizedFailDescription=s,this.getExtraInfoBuilder(t).finished(),this.finishNetworkRequest(l,n,-1)}}webSocketCreated({requestId:t,url:n,initiator:r}){const s=Me.createForWebSocket(t,n,r);ee.set(s,this.#$),s.setResourceType(e.ResourceType.resourceTypes.WebSocket),this.startNetworkRequest(s,null)}webSocketWillSendHandshakeRequest({requestId:e,timestamp:t,wallTime:n,request:r}){const s=this.#Q.get(e);s&&(s.requestMethod="GET",s.setRequestHeaders(this.headersMapToHeadersArray(r.headers)),s.setIssueTime(t,n),this.updateNetworkRequest(s))}webSocketHandshakeResponseReceived({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.statusCode=n.status,r.statusText=n.statusText,r.responseHeaders=this.headersMapToHeadersArray(n.headers),r.responseHeadersText=n.headersText||"",n.requestHeaders&&r.setRequestHeaders(this.headersMapToHeadersArray(n.requestHeaders)),n.requestHeadersText&&r.setRequestHeadersText(n.requestHeadersText),r.responseReceivedTime=t,r.protocol="websocket",this.updateNetworkRequest(r))}webSocketFrameReceived({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrame(n,t,!1),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketFrameSent({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrame(n,t,!0),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketFrameError({requestId:e,timestamp:t,errorMessage:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrameError(n,t),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketClosed({requestId:e,timestamp:t}){const n=this.#Q.get(e);n&&this.finishNetworkRequest(n,t,-1)}eventSourceMessageReceived({requestId:e,timestamp:t,eventName:n,eventId:r,data:s}){const i=this.#Q.get(e);i&&i.addEventSourceMessage(t,n,r,s)}requestIntercepted({}){}requestWillBeSentExtraInfo({requestId:e,associatedCookies:t,headers:n,clientSecurityState:r,connectTiming:s,siteHasCookieInOtherPartition:i}){const a=[],o=[];for(const{blockedReasons:e,cookie:n}of t)0===e.length?o.push(F.fromProtocolCookie(n)):a.push({blockedReasons:e,cookie:F.fromProtocolCookie(n)});const l={blockedRequestCookies:a,includedRequestCookies:o,requestHeaders:this.headersMapToHeadersArray(n),clientSecurityState:r,connectTiming:s,siteHasCookieInOtherPartition:i};this.getExtraInfoBuilder(e).addRequestExtraInfo(l)}responseReceivedExtraInfo({requestId:e,blockedCookies:t,headers:n,headersText:r,resourceIPAddressSpace:s,statusCode:i,cookiePartitionKey:a,cookiePartitionKeyOpaque:o}){const l={blockedResponseCookies:t.map((e=>({blockedReasons:e.blockedReasons,cookieLine:e.cookieLine,cookie:e.cookie?F.fromProtocolCookie(e.cookie):null}))),responseHeaders:this.headersMapToHeadersArray(n),responseHeadersText:r,resourceIPAddressSpace:s,statusCode:i,cookiePartitionKey:a,cookiePartitionKeyOpaque:o};this.getExtraInfoBuilder(e).addResponseExtraInfo(l)}getExtraInfoBuilder(e){let t;return this.#Y.has(e)?t=this.#Y.get(e):(t=new pe,this.#Y.set(e,t)),t}appendRedirect(e,t,n){const r=this.#Q.get(e);if(!r)throw new Error(`Could not find original network request for ${e}`);let s=0;for(let e=r.redirectSource();e;e=e.redirectSource())s++;r.markAsRedirect(s),this.finishNetworkRequest(r,t,-1);const i=Me.create(e,n,r.documentURL,r.frameId,r.loaderId,r.initiator(),r.hasUserGesture()??void 0);return ee.set(i,this.#$),i.setRedirectSource(r),r.setRedirectDestination(i),i}maybeAdoptMainResourceRequest(e){const t=ue.instance().inflightMainResourceRequests.get(e);if(!t)return null;const n=ne.forRequest(t).dispatcher;n.#Q.delete(e),n.#X.delete(t.url());const r=t.loaderId;r&&n.#J.delete(r);const s=n.#Y.get(e);return n.#Y.delete(e),this.#Q.set(e,t),this.#X.set(t.url(),t),r&&this.#J.set(r,t),s&&this.#Y.set(e,s),ee.set(t,this.#$),t}startNetworkRequest(e,t){this.#Q.set(e.requestId(),e),this.#X.set(e.url(),e);const n=e.loaderId;n&&this.#J.set(n,e),e.loaderId===e.requestId()&&ue.instance().inflightMainResourceRequests.set(e.requestId(),e),this.#$.dispatchEventToListeners(re.RequestStarted,{request:e,originalRequest:t})}updateNetworkRequest(e){this.#$.dispatchEventToListeners(re.RequestUpdated,e)}finishNetworkRequest(t,n,r,s){if(t.endTime=n,t.finished=!0,r>=0){const e=t.redirectSource();e&&e.signedExchangeInfo()?(t.setTransferSize(0),e.setTransferSize(r),this.updateNetworkRequest(e)):t.setTransferSize(r)}if(this.#$.dispatchEventToListeners(re.RequestFinished,t),ue.instance().inflightMainResourceRequests.delete(t.requestId()),s){const e=Y(X.crossoriginReadBlockingCorb,{PH1:t.url(),PH2:t.mimeType});this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t.requestId(),warning:!0})}if(e.Settings.Settings.instance().moduleSetting("monitoringXHREnabled").get()&&t.resourceType().category()===e.ResourceType.resourceCategories.XHR){let e;const n=t.failed||t.hasErrorStatusCode();e=Y(n?X.sFailedLoadingSS:X.sFinishedLoadingSS,{PH1:t.resourceType().title(),PH2:t.requestMethod,PH3:t.url()}),this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t.requestId(),warning:!1})}}clearRequests(){for(const[e,t]of this.#Q)t.finished&&this.#Q.delete(e);for(const[e,t]of this.#X)t.finished&&this.#X.delete(e);for(const[e,t]of this.#J)t.finished&&this.#J.delete(e);for(const[e,t]of this.#Y)t.isFinished()&&this.#Y.delete(e)}webTransportCreated({transportId:t,url:n,timestamp:r,initiator:s}){const i=Me.createForWebSocket(t,n,s);i.hasNetworkData=!0,ee.set(i,this.#$),i.setResourceType(e.ResourceType.resourceTypes.WebTransport),i.setIssueTime(r,0),this.startNetworkRequest(i,null)}webTransportConnectionEstablished({transportId:e,timestamp:t}){const n=this.#Q.get(e);n&&(n.responseReceivedTime=t,n.endTime=t+.001,this.updateNetworkRequest(n))}webTransportClosed({transportId:e,timestamp:t}){const n=this.#Q.get(e);n&&(n.endTime=t,this.finishNetworkRequest(n,t,0))}trustTokenOperationDone(e){const t=this.#Q.get(e.requestId);t?t.setTrustTokenOperationDoneEvent(e):this.#Z.set(e.requestId,e)}subresourceWebBundleMetadataReceived({requestId:e,urls:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInfo({resourceUrls:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleMetadataError({requestId:e,errorMessage:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInfo({errorMessage:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleInnerResponseParsed({innerRequestId:e,bundleRequestId:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInnerRequestInfo({bundleRequestId:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleInnerResponseError({innerRequestId:e,errorMessage:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInnerRequestInfo({errorMessage:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}reportingApiReportAdded(e){this.#$.dispatchEventToListeners(re.ReportingApiReportAdded,e.report)}reportingApiReportUpdated(e){this.#$.dispatchEventToListeners(re.ReportingApiReportUpdated,e.report)}reportingApiEndpointsChangedForOrigin(e){this.#$.dispatchEventToListeners(re.ReportingApiEndpointsChangedForOrigin,e)}createNetworkRequest(e,t,n,r,s,i){const a=Me.create(e,r,s,t,n,i);return ee.set(a,this.#$),a}}let he;class ue extends e.ObjectWrapper.ObjectWrapper{#te;#ne;#re;#se;#ie;inflightMainResourceRequests;#ae;#oe;#le;#de;#ce;#he;#ue;#ge;constructor(){super(),this.#te="",this.#ne=null,this.#re=null,this.#se=new Set,this.#ie=new Set,this.inflightMainResourceRequests=new Map,this.#ae=se,this.#oe=null,this.#le=e.Settings.Settings.instance().moduleSetting("requestBlockingEnabled"),this.#de=e.Settings.Settings.instance().createSetting("networkBlockedPatterns",[]),this.#ce=[],this.updateBlockedPatterns(),this.#he=new t.MapUtilities.Multimap,K.instance().observeModels(ne,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return he&&!t||(he=new ue),he}static dispose(){he=null}static getChromeVersion(){const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""}static patchUserAgentWithChromeVersion(e){const n=ue.getChromeVersion();if(n.length>0){const r=n.split(".",1)[0]+".0.100.0";return t.StringUtilities.sprintf(e,n,r)}return e}static patchUserAgentMetadataWithChromeVersion(e){if(!e.brands)return;const n=ue.getChromeVersion();if(0===n.length)return;const r=n.split(".",1)[0];for(const n of e.brands)n.version.includes("%s")&&(n.version=t.StringUtilities.sprintf(n.version,r));e.fullVersion&&e.fullVersion.includes("%s")&&(e.fullVersion=t.StringUtilities.sprintf(e.fullVersion,n))}modelAdded(e){const t=e.target().networkAgent(),n=e.target().fetchAgent();this.#ue&&t.invoke_setExtraHTTPHeaders({headers:this.#ue}),this.currentUserAgent()&&t.invoke_setUserAgentOverride({userAgent:this.currentUserAgent(),userAgentMetadata:this.#ne||void 0}),this.#ce.length&&t.invoke_setBlockedURLs({urls:this.#ce}),this.isIntercepting()&&n.invoke_enable({patterns:this.#he.valuesArray()}),null===this.#re?t.invoke_clearAcceptedEncodingsOverride():t.invoke_setAcceptedEncodings({encodings:this.#re}),this.#se.add(t),this.#ie.add(n),this.isThrottling()&&this.updateNetworkConditions(t)}modelRemoved(e){for(const t of this.inflightMainResourceRequests){ne.forRequest(t[1])===e&&this.inflightMainResourceRequests.delete(t[0])}this.#se.delete(e.target().networkAgent()),this.#ie.delete(e.target().fetchAgent())}isThrottling(){return this.#ae.download>=0||this.#ae.upload>=0||this.#ae.latency>0}isOffline(){return!this.#ae.download&&!this.#ae.upload}setNetworkConditions(e){this.#ae=e;for(const e of this.#se)this.updateNetworkConditions(e);this.dispatchEventToListeners(ue.Events.ConditionsChanged)}networkConditions(){return this.#ae}updateNetworkConditions(e){const t=this.#ae;this.isThrottling()?e.invoke_emulateNetworkConditions({offline:this.isOffline(),latency:t.latency,downloadThroughput:t.download<0?0:t.download,uploadThroughput:t.upload<0?0:t.upload,connectionType:ne.connectionType(t)}):e.invoke_emulateNetworkConditions({offline:!1,latency:0,downloadThroughput:0,uploadThroughput:0})}setExtraHTTPHeaders(e){this.#ue=e;for(const e of this.#se)e.invoke_setExtraHTTPHeaders({headers:this.#ue})}currentUserAgent(){return this.#ge?this.#ge:this.#te}updateUserAgentOverride(){const e=this.currentUserAgent();for(const t of this.#se)t.invoke_setUserAgentOverride({userAgent:e,userAgentMetadata:this.#ne||void 0})}setUserAgentOverride(e,t){const n=this.#te!==e;this.#te=e,this.#ge?this.#ne=null:(this.#ne=t,this.updateUserAgentOverride()),n&&this.dispatchEventToListeners(ue.Events.UserAgentChanged)}userAgentOverride(){return this.#te}setCustomUserAgentOverride(e,t=null){this.#ge=e,this.#ne=t,this.updateUserAgentOverride()}setCustomAcceptedEncodingsOverride(e){this.#re=e,this.updateAcceptedEncodingsOverride(),this.dispatchEventToListeners(ue.Events.AcceptedEncodingsChanged)}clearCustomAcceptedEncodingsOverride(){this.#re=null,this.updateAcceptedEncodingsOverride(),this.dispatchEventToListeners(ue.Events.AcceptedEncodingsChanged)}isAcceptedEncodingOverrideSet(){return null!==this.#re}updateAcceptedEncodingsOverride(){const e=this.#re;for(const t of this.#se)null===e?t.invoke_clearAcceptedEncodingsOverride():t.invoke_setAcceptedEncodings({encodings:e})}blockedPatterns(){return this.#de.get().slice()}blockingEnabled(){return this.#le.get()}isBlocking(){return Boolean(this.#ce.length)}setBlockedPatterns(e){this.#de.set(e),this.updateBlockedPatterns(),this.dispatchEventToListeners(ue.Events.BlockedPatternsChanged)}setBlockingEnabled(e){this.#le.get()!==e&&(this.#le.set(e),this.updateBlockedPatterns(),this.dispatchEventToListeners(ue.Events.BlockedPatternsChanged))}updateBlockedPatterns(){const e=[];if(this.#le.get())for(const t of this.#de.get())t.enabled&&e.push(t.url);if(e.length||this.#ce.length){this.#ce=e;for(const e of this.#se)e.invoke_setBlockedURLs({urls:this.#ce})}}isIntercepting(){return Boolean(this.#he.size)}setInterceptionHandlerForPatterns(e,t){this.#he.deleteAll(t);for(const n of e)this.#he.set(t,n);return this.updateInterceptionPatternsOnNextTick()}updateInterceptionPatternsOnNextTick(){return this.#oe||(this.#oe=Promise.resolve().then(this.updateInterceptionPatterns.bind(this))),this.#oe}async updateInterceptionPatterns(){e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()||e.Settings.Settings.instance().moduleSetting("cacheDisabled").set(!0),this.#oe=null;const t=[];for(const e of this.#ie)t.push(e.invoke_enable({patterns:this.#he.valuesArray()}));this.dispatchEventToListeners(ue.Events.InterceptorsChanged),await Promise.all(t)}async requestIntercepted(e){for(const t of this.#he.keysArray())if(await t(e),e.hasResponded()&&e.networkRequest)return void this.dispatchEventToListeners(ue.Events.RequestIntercepted,e.networkRequest.requestId());e.hasResponded()||e.continueRequestWithoutChange()}clearBrowserCache(){for(const e of this.#se)e.invoke_clearBrowserCache()}clearBrowserCookies(){for(const e of this.#se)e.invoke_clearBrowserCookies()}async getCertificate(e){const t=K.instance().primaryPageTarget();if(!t)return[];const n=await t.networkAgent().invoke_getCertificate({origin:e});return n?n.tableNames:[]}async loadResource(t){const n={},r=this.currentUserAgent();r&&(n["User-Agent"]=r),e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()&&(n["Cache-Control"]="no-cache");const s=e.Settings.Settings.instance().moduleSetting("network.enable-remote-file-loading").get();return new Promise((e=>i.ResourceLoader.load(t,n,((t,n,r,s)=>{e({success:t,content:r,errorDescription:s})}),s)))}}!function(e){let t;!function(e){e.BlockedPatternsChanged="BlockedPatternsChanged",e.ConditionsChanged="ConditionsChanged",e.UserAgentChanged="UserAgentChanged",e.InterceptorsChanged="InterceptorsChanged",e.AcceptedEncodingsChanged="AcceptedEncodingsChanged",e.RequestIntercepted="RequestIntercepted",e.RequestFulfilled="RequestFulfilled"}(t=e.Events||(e.Events={}))}(ue||(ue={}));class ge{#K;#pe;request;resourceType;responseStatusCode;responseHeaders;requestId;networkRequest;constructor(e,t,n,r,s,i,a){this.#K=e,this.#pe=!1,this.request=t,this.resourceType=n,this.responseStatusCode=i,this.responseHeaders=a,this.requestId=r,this.networkRequest=s}hasResponded(){return this.#pe}static mergeSetCookieHeaders(e,t){const n=e=>{const t=new Map;for(const n of e){const e=n.value.match(/^([a-zA-Z0-9!#$%&'*+.^_`|~-]+=)(.*)$/);e?t.has(e[1])?t.get(e[1])?.push(n.value):t.set(e[1],[n.value]):t.has(n.value)?t.get(n.value)?.push(n.value):t.set(n.value,[n.value])}return t},r=n(e),s=n(t),i=[];for(const[e,t]of r)if(s.has(e))for(const t of s.get(e)||[])i.push({name:"set-cookie",value:t});else for(const e of t)i.push({name:"set-cookie",value:e});for(const[e,t]of s)if(!r.has(e))for(const e of t)i.push({name:"set-cookie",value:e});return i}async continueRequestWithContent(e,t,n,r){this.#pe=!0;const s=t?await e.text():await async function(e){const t=new FileReader,n=new Promise((e=>{t.onloadend=e}));if(t.readAsDataURL(e),await n,t.error)return console.error("Could not convert blob to base64.",t.error),"";const r=t.result;if(null==r||"string"!=typeof r)return console.error("Could not convert blob to base64."),"";return r.substring(r.indexOf(",")+1)}(e),i=r?200:this.responseStatusCode||200;if(this.networkRequest){const e=this.networkRequest?.originalResponseHeaders.filter((e=>"set-cookie"===e.name))||[],t=n.filter((e=>"set-cookie"===e.name));this.networkRequest.setCookieHeaders=ge.mergeSetCookieHeaders(e,t)}this.#K.invoke_fulfillRequest({requestId:this.requestId,responseCode:i,body:s,responseHeaders:n}),ue.instance().dispatchEventToListeners(ue.Events.RequestFulfilled,this.request.url)}continueRequestWithoutChange(){console.assert(!this.#pe),this.#pe=!0,this.#K.invoke_continueRequest({requestId:this.requestId})}continueRequestWithError(e){console.assert(!this.#pe),this.#pe=!0,this.#K.invoke_failRequest({requestId:this.requestId,errorReason:e})}async responseBody(){const e=await this.#K.invoke_getResponseBody({requestId:this.requestId}),t=e.getError()||null;return{error:t,content:t?null:e.body,encoded:e.base64Encoded}}isRedirect(){return void 0!==this.responseStatusCode&&this.responseStatusCode>=300&&this.responseStatusCode<400}}class pe{#me;#fe;#be;#ye;#ve;#Ie;constructor(){this.#me=[],this.#fe=[],this.#be=[],this.#ye=!1,this.#ve=null,this.#Ie=null}addRequest(e){this.#me.push(e),this.sync(this.#me.length-1)}addRequestExtraInfo(e){this.#fe.push(e),this.sync(this.#fe.length-1)}addResponseExtraInfo(e){this.#be.push(e),this.sync(this.#be.length-1)}setWebBundleInfo(e){this.#ve=e,this.updateFinalRequest()}setWebBundleInnerRequestInfo(e){this.#Ie=e,this.updateFinalRequest()}finished(){this.#ye=!0,this.updateFinalRequest()}isFinished(){return this.#ye}sync(e){const t=this.#me[e];if(!t)return;const n=this.#fe[e];n&&(t.addExtraRequestInfo(n),this.#fe[e]=null);const r=this.#be[e];r&&(t.addExtraResponseInfo(r),this.#be[e]=null)}finalRequest(){return this.#ye&&this.#me[this.#me.length-1]||null}updateFinalRequest(){if(!this.#ye)return;const e=this.finalRequest();e?.setWebBundleInfo(this.#ve),e?.setWebBundleInnerRequestInfo(this.#Ie)}}c.register(ne,{capabilities:z.Network,autostart:!0});var me=Object.freeze({__proto__:null,NetworkManager:ne,get Events(){return re},NoThrottlingConditions:se,OfflineConditions:ie,Slow3GConditions:ae,Fast3GConditions:oe,FetchDispatcher:de,NetworkDispatcher:ce,get MultitargetNetworkManager(){return ue},InterceptedRequest:ge,ConditionsSerializer:class{stringify(e){const t=e;return JSON.stringify({...t,title:"function"==typeof t.title?t.title():t.title})}parse(e){const t=JSON.parse(e);return{...t,title:t.i18nTitleKey?Z(t.i18nTitleKey):t.title}}},networkConditionsEqual:function(e,t){const n="function"==typeof e.title?e.title():e.title,r="function"==typeof t.title?t.title():t.title;return t.download===e.download&&t.upload===e.upload&&t.latency===e.latency&&r===n}});const fe={deprecatedSyntaxFoundPleaseUse:"Deprecated syntax found. Please use: ;dur=;desc=",duplicateParameterSIgnored:'Duplicate parameter "{PH1}" ignored.',noValueFoundForParameterS:'No value found for parameter "{PH1}".',unrecognizedParameterS:'Unrecognized parameter "{PH1}".',extraneousTrailingCharacters:"Extraneous trailing characters.",unableToParseSValueS:'Unable to parse "{PH1}" value "{PH2}".'},be=s.i18n.registerUIStrings("core/sdk/ServerTiming.ts",fe),ye=s.i18n.getLocalizedString.bind(void 0,be);class ve{metric;value;description;constructor(e,t,n){this.metric=e,this.value=t,this.description=n}static parseHeaders(e){const n=e.filter((e=>"server-timing"===e.name.toLowerCase()));if(!n.length)return null;const r=n.reduce(((e,t)=>{const n=this.createFromHeaderValue(t.value);return e.push(...n.map((function(e){return new ve(e.name,e.hasOwnProperty("dur")?e.dur:null,e.hasOwnProperty("desc")?e.desc:"")}))),e}),[]);return r.sort(((e,n)=>t.StringUtilities.compare(e.metric.toLowerCase(),n.metric.toLowerCase()))),r}static createFromHeaderValue(e){function t(){e=e.replace(/^\s*/,"")}function n(n){return console.assert(1===n.length),t(),e.charAt(0)===n&&(e=e.substring(1),!0)}function r(){const t=/^(?:\s*)([\w!#$%&'*+\-.^`|~]+)(?:\s*)(.*)/.exec(e);return t?(e=t[2],t[1]):null}function s(){return t(),'"'===e.charAt(0)?function(){console.assert('"'===e.charAt(0)),e=e.substring(1);let t="";for(;e.length;){const n=/^([^"\\]*)(.*)/.exec(e);if(!n)return null;if(t+=n[1],'"'===n[2].charAt(0))return e=n[2].substring(1),t;console.assert("\\"===n[2].charAt(0)),t+=n[2].charAt(1),e=n[2].substring(2)}return null}():r()}function i(){const t=/([,;].*)/.exec(e);t&&(e=t[1])}const a=[];let o;for(;null!==(o=r());){const t={name:o};for("="===e.charAt(0)&&this.showWarning(ye(fe.deprecatedSyntaxFoundPleaseUse));n(";");){let e;if(null===(e=r()))continue;e=e.toLowerCase();const a=this.getParserForParameter(e);let o=null;if(n("=")&&(o=s(),i()),a){if(t.hasOwnProperty(e)){this.showWarning(ye(fe.duplicateParameterSIgnored,{PH1:e}));continue}null===o&&this.showWarning(ye(fe.noValueFoundForParameterS,{PH1:e})),a.call(this,t,o)}else this.showWarning(ye(fe.unrecognizedParameterS,{PH1:e}))}if(a.push(t),!n(","))break}return e.length&&this.showWarning(ye(fe.extraneousTrailingCharacters)),a}static getParserForParameter(e){switch(e){case"dur":{function t(t,n){if(t.dur=0,null!==n){const r=parseFloat(n);if(isNaN(r))return void ve.showWarning(ye(fe.unableToParseSValueS,{PH1:e,PH2:n}));t.dur=r}}return t}case"desc":{function e(e,t){e.desc=t||""}return e}default:return null}}static showWarning(t){e.Console.Console.instance().warn(`ServerTiming: ${t}`)}}var Ie=Object.freeze({__proto__:null,ServerTiming:ve});const ke={binary:"(binary)",secureOnly:'This cookie was blocked because it had the "`Secure`" attribute and the connection was not secure.',notOnPath:"This cookie was blocked because its path was not an exact match for or a superdirectory of the request url's path.",domainMismatch:"This cookie was blocked because neither did the request URL's domain exactly match the cookie's domain, nor was the request URL's domain a subdomain of the cookie's Domain attribute value.",sameSiteStrict:'This cookie was blocked because it had the "`SameSite=Strict`" attribute and the request was made from a different site. This includes top-level navigation requests initiated by other sites.',sameSiteLax:'This cookie was blocked because it had the "`SameSite=Lax`" attribute and the request was made from a different site and was not initiated by a top-level navigation.',sameSiteUnspecifiedTreatedAsLax:'This cookie didn\'t specify a "`SameSite`" attribute when it was stored and was defaulted to "SameSite=Lax," and was blocked because the request was made from a different site and was not initiated by a top-level navigation. The cookie had to have been set with "`SameSite=None`" to enable cross-site usage.',sameSiteNoneInsecure:'This cookie was blocked because it had the "`SameSite=None`" attribute but was not marked "Secure". Cookies without SameSite restrictions must be marked "Secure" and sent over a secure connection.',userPreferences:"This cookie was blocked due to user preferences.",unknownError:"An unknown error was encountered when trying to send this cookie.",schemefulSameSiteStrict:'This cookie was blocked because it had the "`SameSite=Strict`" attribute but the request was cross-site. This includes top-level navigation requests initiated by other sites. This request is considered cross-site because the URL has a different scheme than the current site.',schemefulSameSiteLax:'This cookie was blocked because it had the "`SameSite=Lax`" attribute but the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site.',schemefulSameSiteUnspecifiedTreatedAsLax:'This cookie didn\'t specify a "`SameSite`" attribute when it was stored, was defaulted to "`SameSite=Lax"`, and was blocked because the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site.',samePartyFromCrossPartyContext:"This cookie was blocked because it had the \"`SameParty`\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set.",nameValuePairExceedsMaxSize:"This cookie was blocked because it was too large. The combined size of the name and value must be less than or equal to 4096 characters.",thisSetcookieWasBlockedDueToUser:"This attempt to set a cookie via a `Set-Cookie` header was blocked due to user preferences.",thisSetcookieHadInvalidSyntax:"This `Set-Cookie` header had invalid syntax.",theSchemeOfThisConnectionIsNot:"The scheme of this connection is not allowed to store cookies.",anUnknownErrorWasEncounteredWhenTrying:"An unknown error was encountered when trying to store this cookie.",thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "{PH1}" attribute but came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site.',thisSetcookieDidntSpecifyASamesite:'This `Set-Cookie` header didn\'t specify a "`SameSite`" attribute, was defaulted to "`SameSite=Lax"`, and was blocked because it came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site.',thisSetcookieWasBlockedBecauseItHadTheSameparty:"This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the \"`SameParty`\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set.",thisSetcookieWasBlockedBecauseItHadTheSamepartyAttribute:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "`SameParty`" attribute but also had other conflicting attributes. Chrome requires cookies that use the "`SameParty`" attribute to also have the "Secure" attribute, and to not be restricted to "`SameSite=Strict`".',blockedReasonSecureOnly:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "Secure" attribute but was not received over a secure connection.',blockedReasonSameSiteStrictLax:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "{PH1}" attribute but came from a cross-site response which was not the response to a top-level navigation.',blockedReasonSameSiteUnspecifiedTreatedAsLax:'This `Set-Cookie` header didn\'t specify a "`SameSite`" attribute and was defaulted to "`SameSite=Lax,`" and was blocked because it came from a cross-site response which was not the response to a top-level navigation. The `Set-Cookie` had to have been set with "`SameSite=None`" to enable cross-site usage.',blockedReasonSameSiteNoneInsecure:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "`SameSite=None`" attribute but did not have the "Secure" attribute, which is required in order to use "`SameSite=None`".',blockedReasonOverwriteSecure:"This attempt to set a cookie via a `Set-Cookie` header was blocked because it was not sent over a secure connection and would have overwritten a cookie with the Secure attribute.",blockedReasonInvalidDomain:"This attempt to set a cookie via a `Set-Cookie` header was blocked because its Domain attribute was invalid with regards to the current host url.",blockedReasonInvalidPrefix:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it used the "`__Secure-`" or "`__Host-`" prefix in its name and broke the additional rules applied to cookies with these prefixes as defined in `https://tools.ietf.org/html/draft-west-cookie-prefixes-05`.',thisSetcookieWasBlockedBecauseTheNameValuePairExceedsMaxSize:"This attempt to set a cookie via a `Set-Cookie` header was blocked because the cookie was too large. The combined size of the name and value must be less than or equal to 4096 characters.",setcookieHeaderIsIgnoredIn:"Set-Cookie header is ignored in response from url: {PH1}. The combined size of the name and value must be less than or equal to 4096 characters."},Se=s.i18n.registerUIStrings("core/sdk/NetworkRequest.ts",ke),we=s.i18n.getLocalizedString.bind(void 0,Se);var Ce,Te,Re,xe;!function(e){e.HTML="text/html",e.XML="text/xml",e.PLAIN="text/plain",e.XHTML="application/xhtml+xml",e.SVG="image/svg+xml",e.CSS="text/css",e.XSL="text/xsl",e.VTT="text/vtt",e.PDF="application/pdf",e.EVENTSTREAM="text/event-stream"}(Ce||(Ce={}));class Me extends e.ObjectWrapper.ObjectWrapper{#ke;#Se;#we;#Ce;#Te;#Re;#xe;#Me;#Pe;#Le;#Ee;#Ae;#Oe;#Ne;#Fe;#Be;#De;statusCode;statusText;requestMethod;requestTime;protocol;alternateProtocolUsage;mixedContentType;#Ue;#He;#qe;#_e;#ze;#je;#We;#Ve;#Ge;#Ke;#$e;#Qe;#Xe;#Je;#Ye;#Ze;#et;#tt;#nt;#rt;#st;connectionId;connectionReused;hasNetworkData;#it;#at;#ot;#lt;#dt;#ct;#ht;#ut;#gt;#pt;localizedFailDescription;#mt;#ft;#bt;#ye;#yt;#vt;#It;#kt;#St;#u;#wt;#Ct;#Tt;#Rt;#xt;#Mt;#Pt;#Lt;#Et;#At;#Ot;#Nt;#Ft;#Bt;#Dt;#Ut;#Ht;#qt;#_t;#zt;#jt;#Wt;#Vt;#Gt;#Kt=new Map;constructor(t,n,r,s,i,a,o,l){super(),this.#ke=t,this.#Se=n,this.setUrl(r),this.#we=s,this.#Ce=i,this.#Te=a,this.#Re=o,this.#xe=l,this.#Me=null,this.#Pe=null,this.#Le=null,this.#Ee=!1,this.#Ae=null,this.#Oe=-1,this.#Ne=-1,this.#Fe=-1,this.#Be=void 0,this.#De=void 0,this.statusCode=0,this.statusText="",this.requestMethod="",this.requestTime=0,this.protocol="",this.alternateProtocolUsage=void 0,this.mixedContentType="none",this.#Ue=null,this.#He=null,this.#qe=null,this.#_e=null,this.#ze=null,this.#je=e.ResourceType.resourceTypes.Other,this.#We=null,this.#Ve=[],this.#Ge=[],this.#Ke={},this.#$e="",this.#Qe=[],this.#Je=[],this.#Ye=[],this.#Ze={},this.#et="",this.#tt="Unknown",this.#nt=null,this.#rt="unknown",this.#st=null,this.connectionId="0",this.connectionReused=!1,this.hasNetworkData=!1,this.#it=null,this.#at=Promise.resolve(null),this.#ot=!1,this.#lt=!1,this.#dt=[],this.#ct=[],this.#ht=[],this.#pt=!1,this.#ut=null,this.#gt=null,this.localizedFailDescription=null,this.#Vt=null,this.#Gt=!1}static create(e,t,n,r,s,i,a){return new Me(e,e,t,n,r,s,i,a)}static createForWebSocket(e,n,r){return new Me(e,e,n,t.DevToolsPath.EmptyUrlString,null,null,r||null)}static createWithoutBackendRequest(e,t,n,r){return new Me(e,void 0,t,n,null,null,r)}identityCompare(e){const t=this.requestId(),n=e.requestId();return t>n?1:te&&(this.#ft=e)),this.dispatchEventToListeners(Te.TimingChanged,this)}get duration(){return-1===this.#Fe||-1===this.#Ne?-1:this.#Fe-this.#Ne}get latency(){return-1===this.#ft||-1===this.#Ne?-1:this.#ft-this.#Ne}get resourceSize(){return this.#Et||0}set resourceSize(e){this.#Et=e}get transferSize(){return this.#bt||0}increaseTransferSize(e){this.#bt=(this.#bt||0)+e}setTransferSize(e){this.#bt=e}get finished(){return this.#ye}set finished(e){this.#ye!==e&&(this.#ye=e,e&&this.dispatchEventToListeners(Te.FinishedLoading,this))}get failed(){return this.#yt}set failed(e){this.#yt=e}get canceled(){return this.#vt}set canceled(e){this.#vt=e}get preserved(){return this.#It}set preserved(e){this.#It=e}blockedReason(){return this.#Be}setBlockedReason(e){this.#Be=e}corsErrorStatus(){return this.#De}setCorsErrorStatus(e){this.#De=e}wasBlocked(){return Boolean(this.#Be)}cached(){return(Boolean(this.#At)||Boolean(this.#Ot))&&!this.#bt}cachedInMemory(){return Boolean(this.#At)&&!this.#bt}fromPrefetchCache(){return Boolean(this.#Nt)}setFromMemoryCache(){this.#At=!0,this.#Bt=void 0}get fromDiskCache(){return this.#Ot}setFromDiskCache(){this.#Ot=!0}setFromPrefetchCache(){this.#Nt=!0}get fetchedViaServiceWorker(){return Boolean(this.#Ft)}set fetchedViaServiceWorker(e){this.#Ft=e}initiatedByServiceWorker(){const e=ne.forRequest(this);return!!e&&e.target().type()===_.ServiceWorker}get timing(){return this.#Bt}set timing(e){if(!e||this.#At)return;this.#Ne=e.requestTime;const t=e.requestTime+e.receiveHeadersEnd/1e3;((this.#ft||-1)<0||this.#ft>t)&&(this.#ft=t),this.#Ne>this.#ft&&(this.#ft=this.#Ne),this.#Bt=e,this.dispatchEventToListeners(Te.TimingChanged,this)}setConnectTimingFromExtraInfo(e){this.#Ne=e.requestTime,this.dispatchEventToListeners(Te.TimingChanged,this)}get mimeType(){return this.#kt}set mimeType(e){this.#kt=e}get displayName(){return this.#St.displayName}name(){return this.#u||this.parseNameAndPathFromURL(),this.#u}path(){return this.#wt||this.parseNameAndPathFromURL(),this.#wt}parseNameAndPathFromURL(){if(this.#St.isDataURL())this.#u=this.#St.dataURLDisplayName(),this.#wt="";else if(this.#St.isBlobURL())this.#u=this.#St.url,this.#wt="";else if(this.#St.isAboutBlank())this.#u=this.#St.url,this.#wt="";else{this.#wt=this.#St.host+this.#St.folderPathComponents;const n=ne.forRequest(this),r=n?e.ParsedURL.ParsedURL.fromString(n.target().inspectedURL()):null;this.#wt=t.StringUtilities.trimURL(this.#wt,r?r.host:""),this.#St.lastPathComponent||this.#St.queryParams?this.#u=this.#St.lastPathComponent+(this.#St.queryParams?"?"+this.#St.queryParams:""):this.#St.folderPathComponents?(this.#u=this.#St.folderPathComponents.substring(this.#St.folderPathComponents.lastIndexOf("/")+1)+"/",this.#wt=this.#wt.substring(0,this.#wt.lastIndexOf("/"))):(this.#u=this.#St.host,this.#wt="")}}get folder(){let e=this.#St.path;const t=e.indexOf("?");-1!==t&&(e=e.substring(0,t));const n=e.lastIndexOf("/");return-1!==n?e.substring(0,n):""}get pathname(){return this.#St.path}resourceType(){return this.#je}setResourceType(e){this.#je=e}get domain(){return this.#St.host}get scheme(){return this.#St.scheme}redirectSource(){return this.#Me}setRedirectSource(e){this.#Me=e}preflightRequest(){return this.#Pe}setPreflightRequest(e){this.#Pe=e}preflightInitiatorRequest(){return this.#Le}setPreflightInitiatorRequest(e){this.#Le=e}isPreflightRequest(){return null!==this.#Re&&void 0!==this.#Re&&"preflight"===this.#Re.type}redirectDestination(){return this.#Ae}setRedirectDestination(e){this.#Ae=e}requestHeaders(){return this.#Ye}setRequestHeaders(e){this.#Ye=e,this.dispatchEventToListeners(Te.RequestHeadersChanged)}requestHeadersText(){return this.#Dt}setRequestHeadersText(e){this.#Dt=e,this.dispatchEventToListeners(Te.RequestHeadersChanged)}requestHeaderValue(e){return this.#Ze[e]||(this.#Ze[e]=this.computeHeaderValue(this.requestHeaders(),e)),this.#Ze[e]}requestFormData(){return this.#at||(this.#at=ne.requestPostData(this)),this.#at}setRequestFormData(e,t){this.#at=e&&null===t?null:Promise.resolve(t),this.#it=null}filteredProtocolName(){const e=this.protocol.toLowerCase();return"h2"===e?"http/2.0":e.replace(/^http\/2(\.0)?\+/,"http/2.0+")}requestHttpVersion(){const e=this.requestHeadersText();if(!e){const e=this.requestHeaderValue("version")||this.requestHeaderValue(":version");return e||this.filteredProtocolName()}const t=e.split(/\r\n/)[0].match(/(HTTP\/\d+\.\d+)$/);return t?t[1]:"HTTP/0.9"}get responseHeaders(){return this.#Ut||[]}set responseHeaders(e){this.#Ut=e,this.#Ht=void 0,this.#_t=void 0,this.#qt=void 0,this.#Ke={},this.dispatchEventToListeners(Te.ResponseHeadersChanged)}get originalResponseHeaders(){return this.#Qe}set originalResponseHeaders(e){this.#Qe=e,this.#Xe=void 0}get setCookieHeaders(){return this.#Je}set setCookieHeaders(e){this.#Je=e}get responseHeadersText(){return this.#$e}set responseHeadersText(e){this.#$e=e,this.dispatchEventToListeners(Te.ResponseHeadersChanged)}get sortedResponseHeaders(){return void 0!==this.#Ht?this.#Ht:(this.#Ht=this.responseHeaders.slice(),this.#Ht.sort((function(e,n){return t.StringUtilities.compare(e.name.toLowerCase(),n.name.toLowerCase())||t.StringUtilities.compare(e.value,n.value)})))}get sortedOriginalResponseHeaders(){return void 0!==this.#Xe?this.#Xe:(this.#Xe=this.originalResponseHeaders.slice(),this.#Xe.sort((function(e,n){return t.StringUtilities.compare(e.name.toLowerCase(),n.name.toLowerCase())||t.StringUtilities.compare(e.value,n.value)})))}hasOverriddenHeaders(){if(!this.#Qe.length)return!1;const e=this.sortedResponseHeaders,t=this.sortedOriginalResponseHeaders;if(t.length!==e.length)return!0;for(let n=0;ne.cookie)),...this.blockedResponseCookies().map((e=>e.cookie))].filter((e=>Boolean(e)))}get serverTimings(){return void 0===this.#_t&&(this.#_t=ve.parseHeaders(this.responseHeaders)),this.#_t}queryString(){if(void 0!==this.#zt)return this.#zt;let e=null;const t=this.url(),n=t.indexOf("?");if(-1!==n){e=t.substring(n+1);const r=e.indexOf("#");-1!==r&&(e=e.substring(0,r))}return this.#zt=e,this.#zt}get queryParameters(){if(this.#jt)return this.#jt;const e=this.queryString();return e?(this.#jt=this.parseParameters(e),this.#jt):null}async parseFormParameters(){const e=this.requestContentType();if(!e)return null;if(e.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)){const e=await this.requestFormData();return e?this.parseParameters(e):null}const t=e.match(/^multipart\/form-data\s*;\s*boundary\s*=\s*(\S+)\s*$/);if(!t)return null;const n=t[1];if(!n)return null;const r=await this.requestFormData();return r?this.parseMultipartFormDataParameters(r,n):null}formParameters(){return this.#it||(this.#it=this.parseFormParameters()),this.#it}responseHttpVersion(){const e=this.#$e;if(!e){const e=this.responseHeaderValue("version")||this.responseHeaderValue(":version");return e||this.filteredProtocolName()}const t=e.split(/\r\n/)[0].match(/^(HTTP\/\d+\.\d+)/);return t?t[1]:"HTTP/0.9"}parseParameters(e){return e.split("&").map((function(e){const t=e.indexOf("=");return-1===t?{name:e,value:""}:{name:e.substring(0,t),value:e.substring(t+1)}}))}parseMultipartFormDataParameters(e,n){const r=t.StringUtilities.escapeForRegExp(n),s=new RegExp('^\\r\\ncontent-disposition\\s*:\\s*form-data\\s*;\\s*name="([^"]*)"(?:\\s*;\\s*filename="([^"]*)")?(?:\\r\\ncontent-type\\s*:\\s*([^\\r\\n]*))?\\r\\n\\r\\n(.*)\\r\\n$',"is");return e.split(new RegExp(`--${r}(?:--s*$)?`,"g")).reduce((function(e,t){const[n,r,i,a,o]=t.match(s)||[];if(!n)return e;const l=i||a?we(ke.binary):o;return e.push({name:r,value:l}),e}),[])}computeHeaderValue(e,t){t=t.toLowerCase();const n=[];for(let r=0;r=400}setInitialPriority(e){this.#Ue=e}initialPriority(){return this.#Ue}setPriority(e){this.#He=e}priority(){return this.#He||this.#Ue||null}setSignedExchangeInfo(e){this.#qe=e}signedExchangeInfo(){return this.#qe}setWebBundleInfo(e){this.#_e=e}webBundleInfo(){return this.#_e}setWebBundleInnerRequestInfo(e){this.#ze=e}webBundleInnerRequestInfo(){return this.#ze}async populateImageSource(e){const{content:t,encoded:n}=await this.contentData();let s=r.ContentProvider.contentAsDataURL(t,this.#kt,n);if(null===s&&!this.#yt){(this.responseHeaderValue("cache-control")||"").includes("no-cache")||(s=this.#mt)}null!==s&&(e.src=s)}initiator(){return this.#Re||null}hasUserGesture(){return this.#xe??null}frames(){return this.#Ve}addProtocolFrameError(e,t){this.addFrame({type:xe.Error,text:e,time:this.pseudoWallTime(t),opCode:-1,mask:!1})}addProtocolFrame(e,t,n){const r=n?xe.Send:xe.Receive;this.addFrame({type:r,text:e.payloadData,time:this.pseudoWallTime(t),opCode:e.opcode,mask:e.mask})}addFrame(e){this.#Ve.push(e),this.dispatchEventToListeners(Te.WebsocketFrameAdded,e)}eventSourceMessages(){return this.#Ge}addEventSourceMessage(e,t,n,r){const s={time:this.pseudoWallTime(e),eventName:t,eventId:n,data:r};this.#Ge.push(s),this.dispatchEventToListeners(Te.EventSourceMessageAdded,s)}markAsRedirect(e){this.#Ee=!0,this.#ke=`${this.#Se}:redirected.${e}`}isRedirect(){return this.#Ee}setRequestIdForTest(e){this.#Se=e,this.#ke=e}charset(){const e=this.responseHeaderValue("content-type");if(!e)return null;const t=e.replace(/ /g,"").split(";").filter((e=>e.toLowerCase().startsWith("charset="))).map((e=>e.slice("charset=".length)));return t.length?t[0]:null}addExtraRequestInfo(e){this.#dt=e.blockedRequestCookies,this.#ct=e.includedRequestCookies,this.setRequestHeaders(e.requestHeaders),this.#ot=!0,this.setRequestHeadersText(""),this.#Ct=e.clientSecurityState,this.setConnectTimingFromExtraInfo(e.connectTiming),this.#pt=e.siteHasCookieInOtherPartition??!1}hasExtraRequestInfo(){return this.#ot}blockedRequestCookies(){return this.#dt}includedRequestCookies(){return this.#ct}hasRequestCookies(){return this.#ct.length>0||this.#dt.length>0}siteHasCookieInOtherPartition(){return this.#pt}static parseStatusTextFromResponseHeadersText(e){return e.split("\r")[0].split(" ").slice(2).join(" ")}addExtraResponseInfo(e){if(this.#ht=e.blockedResponseCookies,this.#ut=e.cookiePartitionKey||null,this.#gt=e.cookiePartitionKeyOpaque||null,this.responseHeaders=e.responseHeaders,this.originalResponseHeaders=e.responseHeaders.map((e=>({...e}))),e.responseHeadersText){if(this.responseHeadersText=e.responseHeadersText,!this.requestHeadersText()){let e=`${this.requestMethod} ${this.parsedURL.path}`;this.parsedURL.queryParams&&(e+=`?${this.parsedURL.queryParams}`),e+=" HTTP/1.1\r\n";for(const{name:t,value:n}of this.requestHeaders())e+=`${t}: ${n}\r\n`;this.setRequestHeadersText(e)}this.statusText=Me.parseStatusTextFromResponseHeadersText(e.responseHeadersText)}this.#tt=e.resourceIPAddressSpace,e.statusCode&&(this.statusCode=e.statusCode),this.#lt=!0;const t=ne.forRequest(this);if(t)for(const e of this.#ht)if(e.blockedReasons.includes("NameValuePairExceedsMaxSize")){const e=we(ke.setcookieHeaderIsIgnoredIn,{PH1:this.url()});t.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:this.#ke,warning:!0})}}hasExtraResponseInfo(){return this.#lt}blockedResponseCookies(){return this.#ht}responseCookiesPartitionKey(){return this.#ut}responseCookiesPartitionKeyOpaque(){return this.#gt}redirectSourceSignedExchangeInfoHasNoErrors(){return null!==this.#Me&&null!==this.#Me.#qe&&!this.#Me.#qe.errors}clientSecurityState(){return this.#Ct}setTrustTokenParams(e){this.#Tt=e}trustTokenParams(){return this.#Tt}setTrustTokenOperationDoneEvent(e){this.#Rt=e,this.dispatchEventToListeners(Te.TrustTokenResultAdded)}trustTokenOperationDoneEvent(){return this.#Rt}setIsSameSite(e){this.#Vt=e}isSameSite(){return this.#Vt}getAssociatedData(e){return this.#Kt.get(e)||null}setAssociatedData(e,t){this.#Kt.set(e,t)}deleteAssociatedData(e){this.#Kt.delete(e)}}!function(e){e.FinishedLoading="FinishedLoading",e.TimingChanged="TimingChanged",e.RemoteAddressChanged="RemoteAddressChanged",e.RequestHeadersChanged="RequestHeadersChanged",e.ResponseHeadersChanged="ResponseHeadersChanged",e.WebsocketFrameAdded="WebsocketFrameAdded",e.EventSourceMessageAdded="EventSourceMessageAdded",e.TrustTokenResultAdded="TrustTokenResultAdded"}(Te||(Te={})),function(e){e.Other="other",e.Parser="parser",e.Redirect="redirect",e.Script="script",e.Preload="preload",e.SignedExchange="signedExchange",e.Preflight="preflight"}(Re||(Re={})),function(e){e.Send="send",e.Receive="receive",e.Error="error"}(xe||(xe={}));var Pe=Object.freeze({__proto__:null,get MIME_TYPE(){return Ce},NetworkRequest:Me,get Events(){return Te},get InitiatorType(){return Re},get WebSocketFrameType(){return xe},cookieBlockedReasonToUiString:function(e){switch(e){case"SecureOnly":return we(ke.secureOnly);case"NotOnPath":return we(ke.notOnPath);case"DomainMismatch":return we(ke.domainMismatch);case"SameSiteStrict":return we(ke.sameSiteStrict);case"SameSiteLax":return we(ke.sameSiteLax);case"SameSiteUnspecifiedTreatedAsLax":return we(ke.sameSiteUnspecifiedTreatedAsLax);case"SameSiteNoneInsecure":return we(ke.sameSiteNoneInsecure);case"UserPreferences":return we(ke.userPreferences);case"UnknownError":return we(ke.unknownError);case"SchemefulSameSiteStrict":return we(ke.schemefulSameSiteStrict);case"SchemefulSameSiteLax":return we(ke.schemefulSameSiteLax);case"SchemefulSameSiteUnspecifiedTreatedAsLax":return we(ke.schemefulSameSiteUnspecifiedTreatedAsLax);case"SamePartyFromCrossPartyContext":return we(ke.samePartyFromCrossPartyContext);case"NameValuePairExceedsMaxSize":return we(ke.nameValuePairExceedsMaxSize)}return""},setCookieBlockedReasonToUiString:function(e){switch(e){case"SecureOnly":return we(ke.blockedReasonSecureOnly);case"SameSiteStrict":return we(ke.blockedReasonSameSiteStrictLax,{PH1:"SameSite=Strict"});case"SameSiteLax":return we(ke.blockedReasonSameSiteStrictLax,{PH1:"SameSite=Lax"});case"SameSiteUnspecifiedTreatedAsLax":return we(ke.blockedReasonSameSiteUnspecifiedTreatedAsLax);case"SameSiteNoneInsecure":return we(ke.blockedReasonSameSiteNoneInsecure);case"UserPreferences":return we(ke.thisSetcookieWasBlockedDueToUser);case"SyntaxError":return we(ke.thisSetcookieHadInvalidSyntax);case"SchemeNotSupported":return we(ke.theSchemeOfThisConnectionIsNot);case"OverwriteSecure":return we(ke.blockedReasonOverwriteSecure);case"InvalidDomain":return we(ke.blockedReasonInvalidDomain);case"InvalidPrefix":return we(ke.blockedReasonInvalidPrefix);case"UnknownError":return we(ke.anUnknownErrorWasEncounteredWhenTrying);case"SchemefulSameSiteStrict":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax,{PH1:"SameSite=Strict"});case"SchemefulSameSiteLax":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax,{PH1:"SameSite=Lax"});case"SchemefulSameSiteUnspecifiedTreatedAsLax":return we(ke.thisSetcookieDidntSpecifyASamesite);case"SamePartyFromCrossPartyContext":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSameparty);case"SamePartyConflictsWithOtherAttributes":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamepartyAttribute);case"NameValuePairExceedsMaxSize":return we(ke.thisSetcookieWasBlockedBecauseTheNameValuePairExceedsMaxSize)}return""},cookieBlockedReasonToAttribute:function(e){switch(e){case"SecureOnly":return D.Secure;case"NotOnPath":return D.Path;case"DomainMismatch":return D.Domain;case"SameSiteStrict":case"SameSiteLax":case"SameSiteUnspecifiedTreatedAsLax":case"SameSiteNoneInsecure":case"SchemefulSameSiteStrict":case"SchemefulSameSiteLax":case"SchemefulSameSiteUnspecifiedTreatedAsLax":return D.SameSite;case"SamePartyFromCrossPartyContext":case"NameValuePairExceedsMaxSize":case"UserPreferences":case"UnknownError":return null}return null},setCookieBlockedReasonToAttribute:function(e){switch(e){case"SecureOnly":case"OverwriteSecure":return D.Secure;case"SameSiteStrict":case"SameSiteLax":case"SameSiteUnspecifiedTreatedAsLax":case"SameSiteNoneInsecure":case"SchemefulSameSiteStrict":case"SchemefulSameSiteLax":case"SchemefulSameSiteUnspecifiedTreatedAsLax":return D.SameSite;case"InvalidDomain":return D.Domain;case"InvalidPrefix":return D.Name;case"SamePartyConflictsWithOtherAttributes":case"SamePartyFromCrossPartyContext":case"NameValuePairExceedsMaxSize":case"UserPreferences":case"SyntaxError":case"SchemeNotSupported":case"UnknownError":return null}return null}});class Le{static fromLocalObject(e){return new Fe(e)}static type(e){if(null===e)return"null";const t=typeof e;return"object"!==t&&"function"!==t?t:e.type}static isNullOrUndefined(e){if(void 0===e)return!0;switch(e.type){case"object":return"null"===e.subtype;case"undefined":return!0;default:return!1}}static arrayNameFromDescription(e){return e.replace(Ue,"").replace(He,"")}static arrayLength(e){if("array"!==e.subtype&&"typedarray"!==e.subtype)return 0;const t=e.description&&e.description.match(Ue),n=e.description&&e.description.match(He);return t?parseInt(t[1],10):n?parseInt(n[1],10):0}static arrayBufferByteLength(e){if("arraybuffer"!==e.subtype)return 0;const t=e.description&&e.description.match(Ue);return t?parseInt(t[1],10):0}static unserializableDescription(e){const t=typeof e;if("number"===t){const t=String(e);if(0===e&&1/e<0)return"-0";if("NaN"===t||"Infinity"===t||"-Infinity"===t)return t}return"bigint"===t?e+"n":null}static toCallArgument(e){const t=typeof e;if("undefined"===t)return{};const n=Le.unserializableDescription(e);if("number"===t)return null!==n?{unserializableValue:n}:{value:e};if("bigint"===t)return{unserializableValue:n};if("string"===t||"boolean"===t)return{value:e};if(!e)return{value:null};const r=e;if(e instanceof Le){const t=e.unserializableValue();if(void 0!==t)return{unserializableValue:t}}else if(void 0!==r.unserializableValue)return{unserializableValue:r.unserializableValue};return void 0!==r.objectId?{objectId:r.objectId}:{value:r.value}}static async loadFromObjectPerProto(e,t,n=!1){const r=await Promise.all([e.getAllProperties(!0,t,n),e.getOwnProperties(t,n)]),s=r[0].properties,i=r[1].properties,a=r[1].internalProperties;if(!i||!s)return{properties:null,internalProperties:null};const o=new Map,l=[];for(let e=0;e100){r+=",…";break}e&&(r+=", "),r+=t}return r+=t,r}get type(){return typeof this.valueInternal}get subtype(){return null===this.valueInternal?"null":Array.isArray(this.valueInternal)?"array":this.valueInternal instanceof Date?"date":void 0}get hasChildren(){return"object"==typeof this.valueInternal&&null!==this.valueInternal&&Boolean(Object.keys(this.valueInternal).length)}async getOwnProperties(e,t=!1){let n=this.children();return t&&(n=n.filter((e=>!function(e){const t=Number(e)>>>0;return String(t)===e}(e.name)))),{properties:n,internalProperties:null}}async getAllProperties(e,t,n=!1){return e?{properties:[],internalProperties:null}:await this.getOwnProperties(t,n)}children(){if(!this.hasChildren)return[];const e=this.valueInternal;return this.#in||(this.#in=Object.keys(e).map((function(t){let n=e[t];return n instanceof Le||(n=Le.fromLocalObject(n)),new Ne(t,n)}))),this.#in}arrayLength(){return Array.isArray(this.valueInternal)?this.valueInternal.length:0}async callFunction(e,t){const n=this.valueInternal,r=t?t.map((e=>e.value)):[];let s,i=!1;try{s=e.apply(n,r)}catch(e){i=!0}return{object:Le.fromLocalObject(s),wasThrown:i}}async callFunctionJSON(e,t){const n=this.valueInternal,r=t?t.map((e=>e.value)):[];let s;try{s=e.apply(n,r)}catch(e){s=null}return s}}class Be{#an;constructor(e){this.#an=e}static objectAsArray(e){if(!e||"object"!==e.type||"array"!==e.subtype&&"typedarray"!==e.subtype)throw new Error("Object is empty or not an array");return new Be(e)}static createFromRemoteObjects(e){if(!e.length)throw new Error("Input array is empty");const t=[];for(let n=0;n1)return new Array(arguments);return[arguments[0]]}),t).then((function(e){if(e.wasThrown||!e.object)throw new Error("Call function throws exceptions or returns empty value");return Be.objectAsArray(e.object)}))}at(e){if(e<0||e>this.#an.arrayLength())throw new Error("Out of range");return this.#an.callFunction((function(e){return this[e]}),[Le.toCallArgument(e)]).then((function(e){if(e.wasThrown||!e.object)throw new Error("Exception in callFunction or result value is empty");return e.object}))}length(){return this.#an.arrayLength()}map(e){const t=[];for(let n=0;n=this.byteLength())throw new RangeError("start is out of range");if(tthis.byteLength())throw new RangeError("end is out of range");return await this.#an.callFunctionJSON((function(e,t){return[...new Uint8Array(this,e,t)]}),[{value:e},{value:t-e}])}object(){return this.#an}},RemoteArray:Be,RemoteFunction:De});class _e{#on;#ln;#dn;#cn;#hn;constructor(e){this.#on=e.fontFamily,this.#ln=e.fontVariationAxes||[],this.#dn=new Map,this.#cn=e.src,this.#hn=e.fontDisplay;for(const e of this.#ln)this.#dn.set(e.tag,e)}getFontFamily(){return this.#on}getSrc(){return this.#cn}getFontDisplay(){return this.#hn}getVariationAxisByTag(e){return this.#dn.get(e)}}var ze=Object.freeze({__proto__:null,CSSFontFace:_e});class je{text="";range;styleSheetId;cssModel;constructor(e){this.cssModel=e}rebase(e){this.styleSheetId===e.styleSheetId&&this.range&&(e.oldRange.equal(this.range)?this.reinitialize(e.payload):this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}equal(e){return!!(this.styleSheetId&&this.range&&e.range)&&(this.styleSheetId===e.styleSheetId&&this.range.equal(e.range))}lineNumberInSource(){if(this.range)return this.header()?.lineNumberInSource(this.range.startLine)}columnNumberInSource(){if(this.range)return this.header()?.columnNumberInSource(this.range.startLine,this.range.startColumn)}header(){return this.styleSheetId?this.cssModel.styleSheetHeaderForId(this.styleSheetId):null}rawLocation(){const e=this.header();if(!e||void 0===this.lineNumberInSource())return null;const t=Number(this.lineNumberInSource());return new rn(e,t,this.columnNumberInSource())}}var We=Object.freeze({__proto__:null,CSSQuery:je});class Ve extends je{name;physicalAxes;logicalAxes;static parseContainerQueriesPayload(e,t){return t.map((t=>new Ve(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.name=e.name,this.physicalAxes=e.physicalAxes,this.logicalAxes=e.logicalAxes}active(){return!0}async getContainerForNode(e){const t=await this.cssModel.domModel().getContainerForNode(e,this.name,this.physicalAxes,this.logicalAxes);if(t)return new Ge(t)}}class Ge{containerNode;constructor(e){this.containerNode=e}async getContainerSizeDetails(){const e=await this.containerNode.domModel().cssModel().getComputedStyle(this.containerNode.id);if(!e)return;const t=e.get("container-type"),n=e.get("contain"),r=e.get("writing-mode");if(!t||!n||!r)return;const s=Ke(`${t} ${n}`),i=$e(s,r);let a,o;return"Both"!==i&&"Horizontal"!==i||(a=e.get("width")),"Both"!==i&&"Vertical"!==i||(o=e.get("height")),{queryAxis:s,physicalAxis:i,width:a,height:o}}}const Ke=e=>{const t=e.split(" ");let n=!1,r=!1;for(const e of t){if("size"===e)return"size";n=n||"inline-size"===e,r=r||"block-size"===e}return n&&r?"size":n?"inline-size":r?"block-size":""},$e=(e,t)=>{const n=t.startsWith("vertical");switch(e){case"":return"";case"size":return"Both";case"inline-size":return n?"Vertical":"Horizontal";case"block-size":return n?"Horizontal":"Vertical"}};var Qe=Object.freeze({__proto__:null,CSSContainerQuery:Ve,CSSContainerQueryContainer:Ge,getQueryAxis:Ke,getPhysicalAxisFromQueryAxis:$e});class Xe extends je{static parseLayerPayload(e,t){return t.map((t=>new Xe(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId}active(){return!0}}var Je=Object.freeze({__proto__:null,CSSLayer:Xe});class Ye{#un;#gn;constructor(e){this.#un=e.active,this.#gn=[];for(let t=0;tnew et(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){if(this.text=e.text,this.source=e.source,this.sourceURL=e.sourceURL||"",this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.mediaList=null,e.mediaList){this.mediaList=[];for(let t=0;tnew nt(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId}active(){return!0}}var rt=Object.freeze({__proto__:null,CSSScope:nt});class st extends je{static parseSupportsPayload(e,t){return t.map((t=>new st(e,t)))}#yn=!0;constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.#yn=e.active}active(){return this.#yn}}var it=Object.freeze({__proto__:null,CSSSupports:st});class at{ownerStyle;index;name;value;important;disabled;parsedOk;implicit;text;range;#yn;#vn;#fn;#In;#kn=[];constructor(e,t,n,s,i,a,o,l,d,c,h){if(this.ownerStyle=e,this.index=t,this.name=n,this.value=s,this.important=i,this.disabled=a,this.parsedOk=o,this.implicit=l,this.text=d,this.range=c?r.TextRange.TextRange.fromObject(c):null,this.#yn=!0,this.#vn=null,this.#fn=null,h&&h.length>0)for(const n of h)this.#kn.push(new at(e,++t,n.name,n.value,i,a,o,!0));else{const r=v().getLonghands(n);for(const n of r||[])this.#kn.push(new at(e,++t,n,"",i,a,o,!0))}}static parsePayload(e,t,n){return new at(e,t,n.name,n.value,n.important||!1,n.disabled||!1,!("parsedOk"in n)||Boolean(n.parsedOk),Boolean(n.implicit),n.text,n.range,n.longhandProperties)}ensureRanges(){if(this.#vn&&this.#fn)return;const e=this.range,t=this.text?new r.Text.Text(this.text):null;if(!e||!t)return;const n=t.value().indexOf(this.name),s=t.value().lastIndexOf(this.value);if(-1===n||-1===s||n>s)return;const i=new r.TextRange.SourceRange(n,this.name.length),a=new r.TextRange.SourceRange(s,this.value.length);function o(e,t,n){return 0===e.startLine&&(e.startColumn+=n,e.endColumn+=n),e.startLine+=t,e.endLine+=t,e}this.#vn=o(t.toTextRange(i),e.startLine,e.startColumn),this.#fn=o(t.toTextRange(a),e.startLine,e.startColumn)}nameRange(){return this.ensureRanges(),this.#vn}valueRange(){return this.ensureRanges(),this.#fn}rebase(e){this.ownerStyle.styleSheetId===e.styleSheetId&&this.range&&(this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}setActive(e){this.#yn=e}get propertyText(){return void 0!==this.text?this.text:""===this.name?"":this.name+": "+this.value+(this.important?" !important":"")+";"}activeInStyle(){return this.#yn}trimmedValueWithoutImportant(){const e="!important";return this.value.endsWith(e)?this.value.slice(0,-e.length).trim():this.value.trim()}async setText(n,s,a){if(!this.ownerStyle)throw new Error("No ownerStyle for property");if(!this.ownerStyle.styleSheetId)throw new Error("No owner style id");if(!this.range||!this.ownerStyle.range)throw new Error("Style not editable");if(s&&(i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited),this.name.startsWith("--")&&i.userMetrics.actionTaken(i.UserMetrics.Action.CustomPropertyEdited)),a&&n===this.propertyText)return this.ownerStyle.cssModel().domModel().markUndoableState(!s),!0;const o=this.range.relativeTo(this.ownerStyle.range.startLine,this.ownerStyle.range.startColumn),l=this.ownerStyle.cssText?this.detectIndentation(this.ownerStyle.cssText):e.Settings.Settings.instance().moduleSetting("textEditorIndent").get(),d=this.ownerStyle.cssText?l.substring(0,this.ownerStyle.range.endColumn):"",c=new r.Text.Text(this.ownerStyle.cssText||"").replaceRange(o,t.StringUtilities.sprintf(";%s;",n)),h=await at.formatStyle(c,l,d);return this.ownerStyle.setText(h,s)}static async formatStyle(e,t,n){const s=t.substring(n.length)+t;t&&(t="\n"+t);let i="",a="",o="",l=!1,d=!1;const c=r.CodeMirrorUtils.createCssTokenizer();return await c("*{"+e+"}",(function(e,n){if(!l){const r=n?.includes("comment")&&function(e){const t=e.indexOf(":");if(-1===t)return!1;const n=e.substring(2,t).trim();return v().isCSSPropertyName(n)}(e),s=n?.includes("string")||n?.includes("meta")||n?.includes("property")||n?.includes("variableName")&&"variableName.function"!==n;return r?i=i.trimEnd()+t+e:s?(l=!0,o=e):(";"!==e||d)&&(i+=e,e.trim()&&!n?.includes("comment")&&(d=";"!==e)),void("{"!==e||n||(d=!1))}if("}"===e||";"===e){const n=o.trim();return i=i.trimEnd()+t+n+(n.endsWith(":")?" ":"")+e,d=!1,l=!1,void(a="")}if(v().isGridAreaDefiningProperty(a)){const t=b.exec(e);t&&0===t.index&&!o.trimEnd().endsWith("]")&&(o=o.trimEnd()+"\n"+s)}a||":"!==e||(a=o);o+=e})),l&&(i+=o),i=i.substring(2,i.length-1).trimEnd(),i+(t?"\n"+n:"")}detectIndentation(e){const t=e.split("\n");return t.length<2?"":r.TextUtils.Utils.lineIndent(t[1])}setValue(e,t,n,r){const s=this.name+": "+e+(this.important?" !important":"")+";";this.setText(s,t,n).then(r)}async setDisabled(e){if(!this.ownerStyle)return!1;if(e===this.disabled)return!0;if(!this.text)return!0;const t=this.text.trim(),n=e=>e+(e.endsWith(";")?"":";");let r;return r=e?"/* "+n(t)+" */":n(this.text.substring(2,t.length-2).trim()),this.setText(r,!0,!0)}setDisplayedStringForInvalidProperty(e){this.#In=e}getInvalidStringForInvalidProperty(){return this.#In}getLonghandProperties(){return this.#kn}}var ot,lt=Object.freeze({__proto__:null,CSSProperty:at});class dt{#Sn;parentRule;#wn;styleSheetId;range;cssText;#Cn;#Tn;#Rn;#xn;type;constructor(e,t,n,r){this.#Sn=e,this.parentRule=t,this.#Mn(n),this.type=r}rebase(e){if(this.styleSheetId===e.styleSheetId&&this.range)if(e.oldRange.equal(this.range))this.#Mn(e.payload);else{this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange);for(let t=0;t0||!l.validContent)continue;let s=0;for(const i of l.validContent.split(";")){const a=i.trim();if(a){let o,l;const d=a.indexOf(":");-1===d?(o=a,l=""):(o=a.substring(0,d).trim(),l=a.substring(d+1).trim());const c=new r.TextRange.TextRange(e,s,e,s+i.length);this.#wn.push(new at(this,this.#wn.length,o,l,!1,!1,!1,!1,i,c.relativeFrom(t,n)))}s+=i.length+1}}function d(e,t){t.validContent="";for(let n=0;n=0;--e)if(this.allProperties()[e].range)return e+1;return 0}#On(e){const t=this.propertyAt(e);if(t&&t.range)return t.range.collapseToStart();if(!this.range)throw new Error("CSSStyleDeclaration.range is null");return this.range.collapseToEnd()}newBlankProperty(e){e=void 0===e?this.pastLastSourcePropertyIndex():e;return new at(this,e,"","",!1,!1,!0,!1,"",this.#On(e))}setText(e,t){return this.range&&this.styleSheetId?this.#Sn.setStyleText(this.styleSheetId,this.range,e,t):Promise.resolve(!1)}insertPropertyAt(e,t,n,r){this.newBlankProperty(e).setText(t+": "+n+";",!1,!0).then(r)}appendProperty(e,t,n){this.insertPropertyAt(this.allProperties().length,e,t,n)}}!function(e){e.Regular="Regular",e.Inline="Inline",e.Attributes="Attributes"}(ot||(ot={}));var ct=Object.freeze({__proto__:null,CSSStyleDeclaration:dt,get Type(){return ot}});class ht{cssModelInternal;styleSheetId;sourceURL;origin;style;constructor(e,t){if(this.cssModelInternal=e,this.styleSheetId=t.styleSheetId,this.styleSheetId){const e=this.getStyleSheetHeader(this.styleSheetId);this.sourceURL=e.sourceURL}this.origin=t.origin,this.style=new dt(this.cssModelInternal,this,t.style,ot.Regular)}rebase(e){this.styleSheetId===e.styleSheetId&&this.style.rebase(e)}resourceURL(){if(!this.styleSheetId)return t.DevToolsPath.EmptyUrlString;return this.getStyleSheetHeader(this.styleSheetId).resourceURL()}isUserAgent(){return"user-agent"===this.origin}isInjected(){return"injected"===this.origin}isViaInspector(){return"inspector"===this.origin}isRegular(){return"regular"===this.origin}cssModel(){return this.cssModelInternal}getStyleSheetHeader(e){const t=this.cssModelInternal.styleSheetHeaderForId(e);return console.assert(null!==t),t}}class ut{text;range;specificity;constructor(e){this.text=e.text,e.range&&(this.range=r.TextRange.TextRange.fromObject(e.range)),e.specificity&&(this.specificity=e.specificity)}rebase(e){this.range&&(this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}}class gt extends ht{selectors;nestingSelectors;media;containerQueries;supports;scopes;layers;wasUsed;constructor(e,t,n){super(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId}),this.reinitializeSelectors(t.selectorList),this.nestingSelectors=t.nestingSelectors,this.media=t.media?et.parseMediaArrayPayload(e,t.media):[],this.containerQueries=t.containerQueries?Ve.parseContainerQueriesPayload(e,t.containerQueries):[],this.scopes=t.scopes?nt.parseScopesPayload(e,t.scopes):[],this.supports=t.supports?st.parseSupportsPayload(e,t.supports):[],this.layers=t.layers?Xe.parseLayerPayload(e,t.layers):[],this.wasUsed=n||!1}static createDummyRule(e,t){const n={selectorList:{text:"",selectors:[{text:t,value:void 0}]},style:{styleSheetId:"0",range:new r.TextRange.TextRange(0,0,0,0),shorthandEntries:[],cssProperties:[]},origin:"inspector"};return new gt(e,n)}reinitializeSelectors(e){this.selectors=[];for(let t=0;te.text)).join(", ")}selectorRange(){const e=this.selectors[0].range,t=this.selectors[this.selectors.length-1].range;return e&&t?new r.TextRange.TextRange(e.startLine,e.startColumn,t.endLine,t.endColumn):null}lineNumberInSource(e){const t=this.selectors[e];if(!t||!t.range||!this.styleSheetId)return 0;return this.getStyleSheetHeader(this.styleSheetId).lineNumberInSource(t.range.startLine)}columnNumberInSource(e){const t=this.selectors[e];if(!t||!t.range||!this.styleSheetId)return;return this.getStyleSheetHeader(this.styleSheetId).columnNumberInSource(t.range.startLine,t.range.startColumn)}rebase(e){if(this.styleSheetId!==e.styleSheetId)return;const t=this.selectorRange();if(t&&t.equal(e.oldRange))this.reinitializeSelectors(e.payload);else for(let t=0;tt.rebase(e))),this.containerQueries.forEach((t=>t.rebase(e))),this.scopes.forEach((t=>t.rebase(e))),this.supports.forEach((t=>t.rebase(e))),super.rebase(e)}}class pt{#Nn;#Fn;constructor(e,t){this.#Nn=new ut(t.animationName),this.#Fn=t.keyframes.map((t=>new mt(e,t)))}name(){return this.#Nn}keyframes(){return this.#Fn}}class mt extends ht{#Bn;constructor(e,t){super(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId}),this.reinitializeKey(t.keyText)}key(){return this.#Bn}reinitializeKey(e){this.#Bn=new ut(e)}rebase(e){this.styleSheetId===e.styleSheetId&&this.#Bn.range&&(e.oldRange.equal(this.#Bn.range)?this.reinitializeKey(e.payload):this.#Bn.rebase(e),super.rebase(e))}setKeyText(e){const t=this.styleSheetId;if(!t)throw"No rule stylesheet id";const n=this.#Bn.range;if(!n)throw"Keyframe key is not editable";return this.cssModelInternal.setKeyframeKey(t,n,e)}}class ft{#Dn;#Un;constructor(e,t){this.#Dn=new ut(t.name),this.#Un=t.tryRules.map((t=>new ht(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId})))}name(){return this.#Dn}tryRules(){return this.#Un}}var bt,yt=Object.freeze({__proto__:null,CSSRule:ht,CSSStyleRule:gt,CSSKeyframesRule:pt,CSSKeyframeRule:mt,CSSPositionFallbackRule:ft});function vt(e){const t=e.match(/var\(\s*(--(?:[\s\w\P{ASCII}-]|\\.)+),?\s*(.*)\s*\)/u);return{variableName:t&&t[1].trim(),fallback:t&&t[2]}}class It{#Sn;#Hn;#qn;#_n;#Fn;#zn;#jn;#Wn;#Vn;#Gn;#Kn;#$n;#Qn;constructor({cssModel:e,node:t,inlinePayload:n,attributesPayload:r,matchedPayload:s,pseudoPayload:i,inheritedPayload:a,inheritedPseudoPayload:o,animationsPayload:l,parentLayoutNodeId:d,positionFallbackRules:c}){this.#Sn=e,this.#Hn=t,this.#qn=new Map,this.#_n=new Map,this.#Fn=[],l&&(this.#Fn=l.map((t=>new pt(e,t)))),this.#Qn=c.map((t=>new ft(e,t))),this.#$n=d,this.#zn=new Map,this.#jn=new Set,s=h(s);for(const e of a)e.matchedCSSRules=h(e.matchedCSSRules);this.#Wn=this.buildMainCascade(n,r,s,a),[this.#Vn,this.#Gn]=this.buildPseudoCascades(i,o),this.#Kn=new Map;for(const e of Array.from(this.#Gn.values()).concat(Array.from(this.#Vn.values())).concat(this.#Wn))for(const t of e.styles())this.#Kn.set(t,e);function h(e){for(const t of e)s(t);const t=[];for(const s of e){const e=t[t.length-1];e&&"user-agent"===s.rule.origin&&"user-agent"===e.rule.origin&&s.rule.selectorList.text===e.rule.selectorList.text&&r(s)===r(e)?n(s,e):t.push(s)}return t;function n(e,t){const n=new Map,r=new Map;for(const e of t.rule.style.shorthandEntries)n.set(e.name,e.value);for(const e of t.rule.style.cssProperties)r.set(e.name,e.value);for(const t of e.rule.style.shorthandEntries)n.set(t.name,t.value);for(const t of e.rule.style.cssProperties)r.set(t.name,t.value);t.rule.style.shorthandEntries=[...n.entries()].map((([e,t])=>({name:e,value:t}))),t.rule.style.cssProperties=[...r.entries()].map((([e,t])=>({name:e,value:t})))}function r(e){return e.rule.media?e.rule.media.map((e=>e.text)).join(", "):null}function s(e){const{matchingSelectors:t,rule:n}=e;"user-agent"===n.origin&&t.length&&(n.selectorList.selectors=n.selectorList.selectors.filter(((e,n)=>t.includes(n))),n.selectorList.text=n.selectorList.selectors.map((e=>e.text)).join(", "),e.matchingSelectors=t.map(((e,t)=>t)))}}}buildMainCascade(e,t,n,r){const s=[],i=[];function a(){if(!t)return;const e=new dt(this.#Sn,null,t,ot.Attributes);this.#zn.set(e,this.#Hn),i.push(e)}if(e&&this.#Hn.nodeType()===Node.ELEMENT_NODE){const t=new dt(this.#Sn,null,e,ot.Inline);this.#zn.set(t,this.#Hn),i.push(t)}let o;for(let e=n.length-1;e>=0;--e){const t=new gt(this.#Sn,n[e].rule);!t.isInjected()&&!t.isUserAgent()||o||(o=!0,a.call(this)),this.#zn.set(t.style,this.#Hn),i.push(t.style),this.addMatchingSelectors(this.#Hn,t,n[e].matchingSelectors)}o||a.call(this),s.push(new kt(this,i,!1));let l=this.#Hn.parentNode;for(let e=0;l&&r&&e=0;--e){const n=new gt(this.#Sn,o[e].rule);this.addMatchingSelectors(l,n,o[e].matchingSelectors),this.containsInherited(n.style)&&(d(i,n.style)||d(this.#jn,n.style)||(this.#zn.set(n.style,l),t.push(n.style),this.#jn.add(n.style)))}l=l.parentNode,s.push(new kt(this,t,!0))}return new St(s);function d(e,t){if(!t.styleSheetId||!t.range)return!1;for(const n of e)if(t.styleSheetId===n.styleSheetId&&n.range&&t.range.equal(n.range))return!0;return!1}}buildSplitCustomHighlightCascades(e,t,n,r){const s=new Map;for(let r=e.length-1;r>=0;--r){const i=this.customHighlightNamesToMatchingSelectorIndices(e[r]);for(const[a,o]of i){const i=new gt(this.#Sn,e[r].rule);this.#zn.set(i.style,t),n&&this.#jn.add(i.style),this.addMatchingSelectors(t,i,o);const l=s.get(a);l?l.push(i.style):s.set(a,[i.style])}}for(const[e,t]of s){const s=new kt(this,t,n,!0),i=r.get(e);i?i.push(s):r.set(e,[s])}}customHighlightNamesToMatchingSelectorIndices(e){const t=new Map;for(let n=0;n=0;--e){const t=new gt(this.#Sn,o[e].rule);a.push(t.style);const s=v().isHighlightPseudoType(n.pseudoType)?this.#Hn:r;this.#zn.set(t.style,s),s&&this.addMatchingSelectors(s,t,o[e].matchingSelectors)}const e=v().isHighlightPseudoType(n.pseudoType),t=new kt(this,a,!1,e);s.set(n.pseudoType,[t])}}if(t){let e=this.#Hn.parentNode;for(let n=0;e&&n=0;--n){const r=new gt(this.#Sn,a[n].rule);t.push(r.style),this.#zn.set(r.style,e),this.#jn.add(r.style),this.addMatchingSelectors(e,r,a[n].matchingSelectors)}const r=v().isHighlightPseudoType(n.pseudoType),i=new kt(this,t,!0,r),o=s.get(n.pseudoType);o?o.push(i):s.set(n.pseudoType,[i])}}e=e.parentNode}}for(const[e,t]of s.entries())n.set(e,new St(t));for(const[e,t]of i.entries())r.set(e,new St(t));return[n,r]}addMatchingSelectors(e,t,n){for(const r of n){const n=t.selectors[r];n&&this.setSelectorMatches(e,n.text,!0)}}node(){return this.#Hn}cssModel(){return this.#Sn}hasMatchingSelectors(e){return this.getMatchingSelectors(e).length>0&&this.queryMatches(e.style)}getParentLayoutNodeId(){return this.#$n}getMatchingSelectors(e){const t=this.nodeForStyle(e.style);if(!t||"number"!=typeof t.id)return[];const n=this.#_n.get(t.id);if(!n)return[];const r=[];for(let t=0;t=0;e--){const t=this.styles[e],n=t.parentRule;if((!n||n instanceof gt)&&(!n||this.#Xn.hasMatchingSelectors(n)))for(const e of t.allProperties()){const n=v();if(this.#Jn&&!this.#Yn&&!n.isPropertyInherited(e.name))continue;if(t.range&&!e.range)continue;if(!e.activeInStyle()){this.propertiesState.set(e,bt.Overloaded);continue}const r=n.canonicalPropertyName(e.name);this.updatePropertyState(e,r);for(const t of e.getLonghandProperties())n.isCSSPropertyName(t.name)&&this.updatePropertyState(t,t.name)}}}updatePropertyState(e,t){const n=this.activeProperties.get(t);!n?.important||e.important?(n&&this.propertiesState.set(n,bt.Overloaded),this.propertiesState.set(e,bt.Active),this.activeProperties.set(t,e)):this.propertiesState.set(e,bt.Overloaded)}}class St{#Zn;#er;#tr;#nr;#rr;#sr;constructor(e){this.#Zn=e,this.#er=new Map,this.#tr=new Map,this.#nr=new Map,this.#rr=!1,this.#sr=new Map;for(const t of e)for(const e of t.styles)this.#sr.set(e,t)}findAvailableCSSVariables(e){const t=this.#sr.get(e);if(!t)return[];this.ensureInitialized();const n=this.#tr.get(t);return n?Array.from(n.keys()):[]}computeCSSVariable(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);return r&&s?this.innerComputeCSSVariable(r,s,t):null}computeValue(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);return r&&s?this.innerComputeValue(r,s,t):null}computeSingleVariableValue(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);if(!r||!s)return null;const i=this.innerComputeValue(r,s,t),{variableName:a}=vt(t);return{computedValue:i,fromFallback:null!==a&&!r.has(a)}}innerComputeCSSVariable(e,t,n){if(!e.has(n))return null;if(t.has(n))return t.get(n)||null;t.set(n,null);const r=e.get(n);if(null==r)return null;const s=this.innerComputeValue(e,t,r);return t.set(n,s),s}innerComputeValue(e,t,n){const s=r.TextUtils.Utils.splitStringByRegexes(n,[f]),i=[];for(const n of s){if(-1===n.regexIndex){i.push(n.value);continue}const{variableName:r,fallback:s}=vt(n.value);if(!r)return null;const a=this.innerComputeCSSVariable(e,t,r);if(null===a&&!s)return null;null===a?i.push(s):i.push(a)}return i.map((e=>e?e.trim():"")).join(" ")}styles(){return Array.from(this.#sr.keys())}propertyState(e){return this.ensureInitialized(),this.#er.get(e)||null}reset(){this.#rr=!1,this.#er.clear(),this.#tr.clear(),this.#nr.clear()}ensureInitialized(){if(this.#rr)return;this.#rr=!0;const e=new Map;for(const t of this.#Zn){t.computeActiveProperties();for(const[n,r]of t.propertiesState){if(r===bt.Overloaded){this.#er.set(n,bt.Overloaded);continue}const t=v().canonicalPropertyName(n.name);e.has(t)?this.#er.set(n,bt.Overloaded):(e.set(t,n),this.#er.set(n,bt.Active))}}for(const[t,n]of e){const r=n.ownerStyle,s=n.getLonghandProperties();if(!s.length)continue;let i=!1;for(const t of s){const n=v().canonicalPropertyName(t.name),s=e.get(n);if(s&&s.ownerStyle===r){i=!0;break}}i||(e.delete(t),this.#er.set(n,bt.Overloaded))}const t=new Map;for(let e=this.#Zn.length-1;e>=0;--e){const n=this.#Zn[e],r=[];for(const e of n.activeProperties.entries()){const n=e[0],s=e[1];n.startsWith("--")&&(t.set(n,s.value),r.push(n))}const s=new Map(t),i=new Map;this.#tr.set(n,s),this.#nr.set(n,i);for(const e of r)t.delete(e),t.set(e,this.innerComputeCSSVariable(s,i,e))}}}!function(e){e.Active="Active",e.Overloaded="Overloaded"}(bt||(bt={}));var wt=Object.freeze({__proto__:null,parseCSSVariableNameAndFallback:vt,CSSMatchedStyles:It,get PropertyState(){return bt}});const Ct={couldNotFindTheOriginalStyle:"Could not find the original style sheet.",thereWasAnErrorRetrievingThe:"There was an error retrieving the source styles."},Tt=s.i18n.registerUIStrings("core/sdk/CSSStyleSheetHeader.ts",Ct),Rt=s.i18n.getLocalizedString.bind(void 0,Tt);class xt{#Sn;id;frameId;sourceURL;hasSourceURL;origin;title;disabled;isInline;isMutable;isConstructed;startLine;startColumn;endLine;endColumn;contentLength;ownerNode;sourceMapURL;loadingFailed;#ir;constructor(e,t){this.#Sn=e,this.id=t.styleSheetId,this.frameId=t.frameId,this.sourceURL=t.sourceURL,this.hasSourceURL=Boolean(t.hasSourceURL),this.origin=t.origin,this.title=t.title,this.disabled=t.disabled,this.isInline=t.isInline,this.isMutable=t.isMutable,this.isConstructed=t.isConstructed,this.startLine=t.startLine,this.startColumn=t.startColumn,this.endLine=t.endLine,this.endColumn=t.endColumn,this.contentLength=t.length,t.ownerNode&&(this.ownerNode=new Rn(e.target(),t.ownerNode)),this.sourceMapURL=t.sourceMapURL,this.loadingFailed=t.loadingFailed??!1,this.#ir=null}originalContentProvider(){if(!this.#ir){const e=async()=>{const e=await this.#Sn.originalStyleSheetText(this);return null===e?{content:null,error:Rt(Ct.couldNotFindTheOriginalStyle),isEncoded:!1}:{content:e,isEncoded:!1}};this.#ir=new r.StaticContentProvider.StaticContentProvider(this.contentURL(),this.contentType(),e)}return this.#ir}setSourceMapURL(e){this.sourceMapURL=e}cssModel(){return this.#Sn}isAnonymousInlineStyleSheet(){return!this.resourceURL()&&!this.#Sn.sourceMapManager().sourceMapForClient(this)}isConstructedByNew(){return this.isConstructed&&0===this.sourceURL.length}resourceURL(){const e=this.isViaInspector()?this.viaInspectorResourceURL():this.sourceURL;return!e&&o.Runtime.experiments.isEnabled(o.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)?this.dynamicStyleURL():e}getFrameURLPath(){const t=this.#Sn.target().model(jn);if(console.assert(Boolean(t)),!t)return"";const n=t.frameForId(this.frameId);if(!n)return"";console.assert(Boolean(n));const r=new e.ParsedURL.ParsedURL(n.url);let s=r.host+r.folderPathComponents;return s.endsWith("/")||(s+="/"),s}viaInspectorResourceURL(){return`inspector://${this.getFrameURLPath()}inspector-stylesheet`}dynamicStyleURL(){return`stylesheet://${this.getFrameURLPath()}style#${this.id}`}lineNumberInSource(e){return this.startLine+e}columnNumberInSource(e,t){return(e?0:this.startColumn)+t}containsLocation(e,t){const n=e===this.startLine&&t>=this.startColumn||e>this.startLine,r=ee.isOutermostFrame()));this.#dr=e.length>0?e[0]:null}getFrame(e){const t=this.#or.get(e);return t?t.frame:null}getAllFrames(){return Array.from(this.#or.values(),(e=>e.frame))}getOutermostFrame(){return this.#dr}async getOrWaitForFrame(e,t){const n=this.getFrame(e);return!n||t&&t===n.resourceTreeModel().target()?new Promise((n=>{const r=this.#hr.get(e);r?r.push({notInTarget:t,resolve:n}):this.#hr.set(e,[{notInTarget:t,resolve:n}])})):n}resolveAwaitedFrame(e){const t=this.#hr.get(e.id);if(!t)return;const n=t.filter((({notInTarget:t,resolve:n})=>!(!t||t!==e.resourceTreeModel().target())||(n(e),!1)));n.length>0?this.#hr.set(e.id,n):this.#hr.delete(e.id)}}var Et;!function(e){e.FrameAddedToTarget="FrameAddedToTarget",e.FrameNavigated="FrameNavigated",e.FrameRemoved="FrameRemoved",e.ResourceAdded="ResourceAdded",e.OutermostFrameNavigated="OutermostFrameNavigated"}(Et||(Et={}));var At=Object.freeze({__proto__:null,FrameManager:Lt,get Events(){return Et}});class Ot extends c{constructor(e){super(e)}async read(t,n,r){const s=await this.target().ioAgent().invoke_read({handle:t,offset:r,size:n});if(s.getError())throw new Error(s.getError());return s.eof?null:s.base64Encoded?e.Base64.decode(s.data):s.data}async close(e){(await this.target().ioAgent().invoke_close({handle:e})).getError()&&console.error("Could not close stream.")}async resolveBlob(e){const t=e instanceof Le?e.objectId:e;if(!t)throw new Error("Remote object has undefined objectId");const n=await this.target().ioAgent().invoke_resolveBlob({objectId:t});if(n.getError())throw new Error(n.getError());return`blob:${n.uuid}`}async readToString(e){const t=[],n=new TextDecoder;for(;;){const r=await this.read(e,1048576);if(null===r){t.push(n.decode());break}r instanceof ArrayBuffer?t.push(n.decode(r,{stream:!0})):t.push(r)}return t.join("")}}c.register(Ot,{capabilities:z.IO,autostart:!0});var Nt=Object.freeze({__proto__:null,IOModel:Ot});const Ft={loadCanceledDueToReloadOf:"Load canceled due to reload of inspected page"},Bt=s.i18n.registerUIStrings("core/sdk/PageResourceLoader.ts",Ft),Dt=s.i18n.getLocalizedString.bind(void 0,Bt);let Ut=null;class Ht extends e.ObjectWrapper.ObjectWrapper{#ur;#gr;#pr;#mr;#fr;constructor(e,t){super(),this.#ur=0,this.#gr=t,this.#pr=new Map,this.#mr=[],K.instance().addModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),this.#fr=e}static instance({forceNew:e,loadOverride:t,maxConcurrentLoads:n}={forceNew:!1,loadOverride:null,maxConcurrentLoads:500}){return Ut&&!e||(Ut=new Ht(t,n)),Ut}static removeInstance(){Ut=null}onPrimaryPageChanged(e){if(e.data.frame.isOutermostFrame()){for(const{reject:e}of this.#mr)e(new Error(Dt(Ft.loadCanceledDueToReloadOf)));this.#mr=[],this.#pr.clear(),this.dispatchEventToListeners(_t.Update)}}getResourcesLoaded(){return this.#pr}getNumberOfResources(){return{loading:this.#ur,queued:this.#mr.length,resources:this.#pr.size}}async acquireLoadSlot(){if(this.#ur++,this.#ur>this.#gr){const e={resolve:()=>{},reject:()=>{}},t=new Promise(((t,n)=>{e.resolve=t,e.reject=n}));this.#mr.push(e),await t}}releaseLoadSlot(){this.#ur--;const e=this.#mr.shift();e&&e.resolve()}static makeKey(e,t){if(t.frameId)return`${e}-${t.frameId}`;if(t.target)return`${e}-${t.target.id()}`;throw new Error("Invalid initiator")}async loadResource(e,t){const n=Ht.makeKey(e,t),r={success:null,size:null,errorMessage:void 0,url:e,initiator:t};this.#pr.set(n,r),this.dispatchEventToListeners(_t.Update);try{await this.acquireLoadSlot();const n=this.dispatchLoad(e,t),s=await n;if(r.errorMessage=s.errorDescription.message,r.success=s.success,s.success)return r.size=s.content.length,{content:s.content};throw new Error(s.errorDescription.message)}catch(e){throw void 0===r.errorMessage&&(r.errorMessage=e.message),null===r.success&&(r.success=!1),e}finally{this.releaseLoadSlot(),this.dispatchEventToListeners(_t.Update)}}async dispatchLoad(t,n){let r=null;if(this.#fr)return this.#fr(t);const s=new e.ParsedURL.ParsedURL(t),a=qt().get()&&s&&"file"!==s.scheme&&"data"!==s.scheme&&"devtools"!==s.scheme;if(i.userMetrics.developerResourceScheme(this.getDeveloperResourceScheme(s)),a){try{if(n.target){i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageViaTarget);return await this.loadFromTarget(n.target,n.frameId,t)}const e=Lt.instance().getFrame(n.frameId);if(e){i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageViaFrame);return await this.loadFromTarget(e.resourceTreeModel().target(),n.frameId,t)}}catch(e){e instanceof Error&&(i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageFailure),r=e.message)}i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageFallback),console.warn("Fallback triggered",t,n)}else{const e=qt().get()?i.UserMetrics.DeveloperResourceLoaded.FallbackPerProtocol:i.UserMetrics.DeveloperResourceLoaded.FallbackPerOverride;i.userMetrics.developerResourceLoaded(e)}const o=await ue.instance().loadResource(t);return a&&!o.success&&i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.FallbackFailure),r&&(o.errorDescription.message=`Fetch through target failed: ${r}; Fallback: ${o.errorDescription.message}`),o}getDeveloperResourceScheme(e){if(!e||""===e.scheme)return i.UserMetrics.DeveloperResourceScheme.SchemeUnknown;const t="localhost"===e.host||e.host.endsWith(".localhost");switch(e.scheme){case"file":return i.UserMetrics.DeveloperResourceScheme.SchemeFile;case"data":return i.UserMetrics.DeveloperResourceScheme.SchemeData;case"blob":return i.UserMetrics.DeveloperResourceScheme.SchemeBlob;case"http":return t?i.UserMetrics.DeveloperResourceScheme.SchemeHttpLocalhost:i.UserMetrics.DeveloperResourceScheme.SchemeHttp;case"https":return t?i.UserMetrics.DeveloperResourceScheme.SchemeHttpsLocalhost:i.UserMetrics.DeveloperResourceScheme.SchemeHttps}return i.UserMetrics.DeveloperResourceScheme.SchemeOther}async loadFromTarget(t,n,r){const s=t.model(ne),a=t.model(Ot),o=e.Settings.Settings.instance().moduleSetting("cacheDisabled").get(),l=await s.loadNetworkResource(n,r,{disableCache:o,includeCredentials:!0});try{const e=l.stream?await a.readToString(l.stream):"";return{success:l.success,content:e,errorDescription:{statusCode:l.httpStatusCode||0,netError:l.netError,netErrorName:l.netErrorName,message:i.ResourceLoader.netErrorToMessage(l.netError,l.httpStatusCode,l.netErrorName)||"",urlValid:void 0}}}finally{l.stream&&a.close(l.stream)}}}function qt(){return e.Settings.Settings.instance().createSetting("loadThroughTarget",!0)}var _t;(_t||(_t={})).Update="Update";var zt=Object.freeze({__proto__:null,PageResourceLoader:Ht,getLoadThroughTargetSetting:qt,get Events(){return _t}});function jt(e){return e.startsWith(")]}")&&(e=e.substring(e.indexOf("\n"))),65279===e.charCodeAt(0)&&(e=e.slice(1)),JSON.parse(e)}class Wt{lineNumber;columnNumber;sourceURL;sourceLineNumber;sourceColumnNumber;name;constructor(e,t,n,r,s,i){this.lineNumber=e,this.columnNumber=t,this.sourceURL=n,this.sourceLineNumber=r,this.sourceColumnNumber=s,this.name=i}static compare(e,t){return e.lineNumber!==t.lineNumber?e.lineNumber-t.lineNumber:e.columnNumber-t.columnNumber}}const Vt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Gt=new Map;for(let e=0;e"url"in e))&&e.Console.Console.instance().warn(`SourceMap "${n}" contains unsupported "URL" field in one of its sections.`),this.eachSection(this.parseSources.bind(this))}compiledURL(){return this.#yr}url(){return this.#vr}sourceURLs(){return[...this.#Sr.keys()]}embeddedContentByURL(e){const t=this.#Sr.get(e);return t?t.content:null}findEntry(e,n){const r=this.mappings(),s=t.ArrayUtilities.upperBound(r,void 0,((t,r)=>e-r.lineNumber||n-r.columnNumber));return s?r[s-1]:null}findEntryRanges(e,n){const s=this.mappings(),i=t.ArrayUtilities.upperBound(s,void 0,((t,r)=>e-r.lineNumber||n-r.columnNumber));if(!i)return null;const a=i-1,o=s[a].sourceURL;if(!o)return null;const l=iu-s[t].sourceLineNumber||g-s[t].sourceColumnNumber));if(!p)return null;const m=p=i.length||s[i[a]].sourceLineNumber!==n)return null;const l=i.slice(a,o);if(!l.length)return null;const d=t.ArrayUtilities.lowerBound(l,r,((e,t)=>e-s[t].sourceColumnNumber));return d>=l.length?s[l[l.length-1]]:s[l[d]];function c(e,t){return e-s[t].sourceLineNumber}}findReverseIndices(e,n,r){const s=this.mappings(),i=this.reversedMappings(e),a=t.ArrayUtilities.upperBound(i,void 0,((e,t)=>n-s[t].sourceLineNumber||r-s[t].sourceColumnNumber));let o=a;for(;o>0&&s[i[o-1]].sourceLineNumber===s[i[a-1]].sourceLineNumber&&s[i[o-1]].sourceColumnNumber===s[i[a-1]].sourceColumnNumber;)--o;return i.slice(o,a)}findReverseEntries(e,t,n){const r=this.mappings();return this.findReverseIndices(e,t,n).map((e=>r[e]))}findReverseRanges(e,t,n){const s=this.mappings(),i=this.findReverseIndices(e,t,n),a=[];for(let e=0;e>=1,s?-t:t}reverseMapTextRanges(e,n){const s=this.reversedMappings(e),i=this.mappings();if(0===s.length)return[];let a=t.ArrayUtilities.lowerBound(s,n,(({startLine:e,startColumn:t},n)=>{const{sourceLineNumber:r,sourceColumnNumber:s}=i[n];return e-r||t-s}));for(;a===s.length||a>0&&(i[s[a]].sourceLineNumber>n.startLine||i[s[a]].sourceColumnNumber>n.startColumn);)a--;let o=a+1;for(;o0){const t=e[0];return 0===t?.lineNumber||0===t.columnNumber}return!1}hasIgnoreListHint(e){return this.#Sr.get(e)?.ignoreListHint??!1}findRanges(e,t){const n=this.mappings(),s=[];if(!n.length)return[];let i=null;0===n[0].lineNumber&&0===n[0].columnNumber||!t?.isStartMatching||(i=r.TextRange.TextRange.createUnboundedFromLocation(0,0),s.push(i));for(const{sourceURL:t,lineNumber:a,columnNumber:o}of n){const n=t&&e(t);i||!n?i&&!n&&(i.endLine=a,i.endColumn=o,i=null):(i=r.TextRange.TextRange.createUnboundedFromLocation(a,o),s.push(i))}return s}compatibleForURL(e,t){return this.embeddedContentByURL(e)===t.embeddedContentByURL(e)&&this.hasIgnoreListHint(e)===t.hasIgnoreListHint(e)}}!function(e){e._VLQ_BASE_SHIFT=5,e._VLQ_BASE_MASK=31,e._VLQ_CONTINUATION_MASK=32;e.StringCharIterator=class{string;position;constructor(e){this.string=e,this.position=0}next(){return this.string.charAt(this.position++)}peek(){return this.string.charAt(this.position)}hasNext(){return this.position{const n=new $t(i,a,e);return this.#Rr.get(t)===s&&(s.sourceMap=n,this.#xr.set(n,t),this.dispatchEventToListeners(Qt.SourceMapAttached,{client:t,sourceMap:n})),n}),(n=>{e.Console.Console.instance().warn(`DevTools failed to load source map: ${n.message}`),this.#Rr.get(t)===s&&this.dispatchEventToListeners(Qt.SourceMapFailedToAttach,{client:t})}))}}this.#Rr.set(t,s)}detachSourceMap(e){const t=this.#Rr.get(e);if(!t)return;if(this.#Rr.delete(e),!this.#Tr)return;const{sourceMap:n}=t;n?(this.#xr.delete(n),this.dispatchEventToListeners(Qt.SourceMapDetached,{client:e,sourceMap:n})):this.dispatchEventToListeners(Qt.SourceMapFailedToAttach,{client:e})}dispose(){K.instance().removeEventListener($.InspectedURLChanged,this.inspectedURLChanged,this)}}!function(e){e.SourceMapWillAttach="SourceMapWillAttach",e.SourceMapFailedToAttach="SourceMapFailedToAttach",e.SourceMapAttached="SourceMapAttached",e.SourceMapDetached="SourceMapDetached"}(Qt||(Qt={}));var Yt,Zt=Object.freeze({__proto__:null,SourceMapManager:Jt,get Events(){return Qt}});class en extends c{agent;#Mr;#Pr;#Lr;#Er;#Ar;#Or;#Nr;#Fr;#Br;#Dr;#Ur;#Hr;#qr;#Tr;#_r;#zr;constructor(t){super(t),this.#Tr=!1,this.#Dr=null,this.#Ur=null,this.#Mr=t.model(Pn),this.#Ar=new Jt(t),this.agent=t.cssAgent(),this.#Or=new an(this),this.#Er=t.model(jn),this.#Er&&this.#Er.addEventListener(_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),t.registerCSSDispatcher(new sn(this)),t.suspended()||this.enable(),this.#Br=new Map,this.#Fr=new Map,this.#Lr=new Map,this.#_r=!1,this.#Pr=new Map,this.#Hr=null,this.#qr=!1,this.#zr=!1,this.#Nr=new e.Throttler.Throttler(dn),this.#Ar.setEnabled(e.Settings.Settings.instance().moduleSetting("cssSourceMapsEnabled").get()),e.Settings.Settings.instance().moduleSetting("cssSourceMapsEnabled").addChangeListener((e=>this.#Ar.setEnabled(e.data)))}headersForSourceURL(e){const t=[];for(const n of this.getStyleSheetIdsForURL(e)){const e=this.styleSheetHeaderForId(n);e&&t.push(e)}return t}createRawLocationsByURL(e,n,r=0){const s=this.headersForSourceURL(e);s.sort((function(e,t){return e.startLine-t.startLine||e.startColumn-t.startColumn||e.id.localeCompare(t.id)}));const i=t.ArrayUtilities.upperBound(s,void 0,((e,t)=>n-t.startLine||r-t.startColumn));if(!i)return[];const a=[],o=s[i-1];for(let e=i-1;e>=0&&s[e].startLine===o.startLine&&s[e].startColumn===o.startColumn;--e)s[e].containsLocation(n,r)&&a.push(new rn(s[e],n,r));return a}sourceMapManager(){return this.#Ar}static readableLayerName(e){return e||""}static trimSourceURL(e){let t=e.lastIndexOf("/*# sourceURL=");if(-1===t&&(t=e.lastIndexOf("/*@ sourceURL="),-1===t))return e;const n=e.lastIndexOf("\n",t);if(-1===n)return e;const r=e.substr(n+1).split("\n",1)[0];return-1===r.search(/[\040\t]*\/\*[#@] sourceURL=[\040\t]*([^\s]*)[\040\t]*\*\/[\040\t]*$/)?e:e.substr(0,n)+e.substr(n+r.length+1)}domModel(){return this.#Mr}async setStyleText(e,t,n,r){try{await this.ensureOriginalStyleSheetText(e);const{styles:s}=await this.agent.invoke_setStyleTexts({edits:[{styleSheetId:e,range:t.serializeToObject(),text:n}]});if(!s||1!==s.length)return!1;this.#Mr.markUndoableState(!r);const i=new nn(e,t,n,s[0]);return this.fireStyleSheetChanged(e,i),!0}catch(e){return!1}}async setSelectorText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{selectorList:r}=await this.agent.invoke_setRuleSelector({styleSheetId:e,range:t,selector:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setKeyframeKey(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{keyText:r}=await this.agent.invoke_setKeyframeKey({styleSheetId:e,range:t,keyText:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}startCoverage(){return this.#_r=!0,this.agent.invoke_startRuleUsageTracking()}async takeCoverageDelta(){const e=await this.agent.invoke_takeCoverageDelta();return{timestamp:e&&e.timestamp||0,coverage:e&&e.coverage||[]}}setLocalFontsEnabled(e){return this.agent.invoke_setLocalFontsEnabled({enabled:e})}async stopCoverage(){this.#_r=!1,await this.agent.invoke_stopRuleUsageTracking()}async getMediaQueries(){const{medias:e}=await this.agent.invoke_getMediaQueries();return e?et.parseMediaArrayPayload(this,e):[]}async getRootLayer(e){const{rootLayer:t}=await this.agent.invoke_getLayersForNode({nodeId:e});return t}isEnabled(){return this.#Tr}async enable(){await this.agent.invoke_enable(),this.#Tr=!0,this.#_r&&await this.startCoverage(),this.dispatchEventToListeners(Yt.ModelWasEnabled)}async getMatchedStyles(e){const t=await this.agent.invoke_getMatchedStylesForNode({nodeId:e});if(t.getError())return null;const n=this.#Mr.nodeForId(e);return n?new It({cssModel:this,node:n,inlinePayload:t.inlineStyle||null,attributesPayload:t.attributesStyle||null,matchedPayload:t.matchedCSSRules||[],pseudoPayload:t.pseudoElements||[],inheritedPayload:t.inherited||[],inheritedPseudoPayload:t.inheritedPseudoElements||[],animationsPayload:t.cssKeyframesRules||[],parentLayoutNodeId:t.parentLayoutNodeId,positionFallbackRules:t.cssPositionFallbackRules||[]}):null}async getClassNames(e){const{classNames:t}=await this.agent.invoke_collectClassNames({styleSheetId:e});return t||[]}async getComputedStyle(e){return this.isEnabled()||await this.enable(),this.#Or.computedStylePromise(e)}async getBackgroundColors(e){const t=await this.agent.invoke_getBackgroundColors({nodeId:e});return t.getError()?null:{backgroundColors:t.backgroundColors||null,computedFontSize:t.computedFontSize||"",computedFontWeight:t.computedFontWeight||""}}async getPlatformFonts(e){const{fonts:t}=await this.agent.invoke_getPlatformFontsForNode({nodeId:e});return t}allStyleSheets(){const e=[...this.#Br.values()];return e.sort((function(e,t){return e.sourceURLt.sourceURL?1:e.startLine-t.startLine||e.startColumn-t.startColumn})),e}async getInlineStyles(e){const t=await this.agent.invoke_getInlineStylesForNode({nodeId:e});if(t.getError()||!t.inlineStyle)return null;const n=new dt(this,null,t.inlineStyle,ot.Inline),r=t.attributesStyle?new dt(this,null,t.attributesStyle,ot.Attributes):null;return new on(n,r)}forcePseudoState(e,n,r){const s=e.marker(tn)||[],i=s.includes(n);if(r){if(i)return!1;s.push(n),e.setMarker(tn,s)}else{if(!i)return!1;t.ArrayUtilities.removeElement(s,n),s.length?e.setMarker(tn,s):e.setMarker(tn,null)}return void 0!==e.id&&(this.agent.invoke_forcePseudoState({nodeId:e.id,forcedPseudoClasses:s}),this.dispatchEventToListeners(Yt.PseudoStateForced,{node:e,pseudoClass:n,enable:r}),!0)}pseudoState(e){return e.marker(tn)||[]}async setMediaText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{media:r}=await this.agent.invoke_setMediaText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setContainerQueryText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{containerQuery:r}=await this.agent.invoke_setContainerQueryText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setSupportsText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{supports:r}=await this.agent.invoke_setSupportsText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setScopeText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{scope:r}=await this.agent.invoke_setScopeText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return console.error(e),!1}}async addRule(e,t,n){try{await this.ensureOriginalStyleSheetText(e);const{rule:r}=await this.agent.invoke_addRule({styleSheetId:e,ruleText:t,location:n});if(!r)return null;this.#Mr.markUndoableState();const s=new nn(e,n,t,r);return this.fireStyleSheetChanged(e,s),new gt(this,r)}catch(e){return null}}async requestViaInspectorStylesheet(e){const t=e.frameId()||(this.#Er&&this.#Er.mainFrame?this.#Er.mainFrame.id:null),n=[...this.#Br.values()].find((e=>e.frameId===t&&e.isViaInspector()));if(n)return n;if(!t)return null;try{const{styleSheetId:e}=await this.agent.invoke_createStyleSheet({frameId:t});return e&&this.#Br.get(e)||null}catch(e){return null}}mediaQueryResultChanged(){this.dispatchEventToListeners(Yt.MediaQueryResultChanged)}fontsUpdated(e){e&&this.#Pr.set(e.src,new _e(e)),this.dispatchEventToListeners(Yt.FontsUpdated)}fontFaces(){return[...this.#Pr.values()]}fontFaceForSource(e){return this.#Pr.get(e)}styleSheetHeaderForId(e){return this.#Br.get(e)||null}styleSheetHeaders(){return[...this.#Br.values()]}fireStyleSheetChanged(e,t){this.dispatchEventToListeners(Yt.StyleSheetChanged,{styleSheetId:e,edit:t})}ensureOriginalStyleSheetText(e){const t=this.styleSheetHeaderForId(e);if(!t)return Promise.resolve(null);let n=this.#Lr.get(t);return n||(n=this.getStyleSheetText(t.id),this.#Lr.set(t,n),this.originalContentRequestedForTest(t)),n}originalContentRequestedForTest(e){}originalStyleSheetText(e){return this.ensureOriginalStyleSheetText(e.id)}getAllStyleSheetHeaders(){return this.#Br.values()}styleSheetAdded(e){console.assert(!this.#Br.get(e.styleSheetId)),e.loadingFailed&&(e.hasSourceURL=!1,e.isConstructed=!0,e.isInline=!1,e.isMutable=!1,e.sourceURL="",e.sourceMapURL=void 0);const t=new xt(this,e);this.#Br.set(e.styleSheetId,t);const n=t.resourceURL();let r=this.#Fr.get(n);if(r||(r=new Map,this.#Fr.set(n,r)),r){let e=r.get(t.frameId);e||(e=new Set,r.set(t.frameId,e)),e.add(t.id)}this.#Ar.attachSourceMap(t,t.sourceURL,t.sourceMapURL),this.dispatchEventToListeners(Yt.StyleSheetAdded,t)}styleSheetRemoved(e){const t=this.#Br.get(e);if(console.assert(Boolean(t)),!t)return;this.#Br.delete(e);const n=t.resourceURL(),r=this.#Fr.get(n);if(console.assert(Boolean(r),"No frameId to styleSheetId map is available for given style sheet URL."),r){const s=r.get(t.frameId);s&&(s.delete(e),s.size||(r.delete(t.frameId),r.size||this.#Fr.delete(n)))}this.#Lr.delete(t),this.#Ar.detachSourceMap(t),this.dispatchEventToListeners(Yt.StyleSheetRemoved,t)}getStyleSheetIdsForURL(e){const t=this.#Fr.get(e);if(!t)return[];const n=[];for(const e of t.values())n.push(...e);return n}async setStyleSheetText(e,t,n){const r=this.#Br.get(e);if(!r)return"Unknown stylesheet in CSS.setStyleSheetText";t=en.trimSourceURL(t),r.hasSourceURL&&(t+="\n/*# sourceURL="+r.sourceURL+" */"),await this.ensureOriginalStyleSheetText(e);const s=(await this.agent.invoke_setStyleSheetText({styleSheetId:r.id,text:t})).sourceMapURL;return this.#Ar.detachSourceMap(r),r.setSourceMapURL(s),this.#Ar.attachSourceMap(r,r.sourceURL,r.sourceMapURL),null===s?"Error in CSS.setStyleSheetText":(this.#Mr.markUndoableState(!n),this.fireStyleSheetChanged(e),null)}async getStyleSheetText(e){try{const{text:t}=await this.agent.invoke_getStyleSheetText({styleSheetId:e});return t&&en.trimSourceURL(t)}catch(e){return null}}async onPrimaryPageChanged(e){e.data.frame.backForwardCacheDetails.restoredFromCache?(await this.suspendModel(),await this.resumeModel()):(this.resetStyleSheets(),this.resetFontFaces())}resetStyleSheets(){const e=[...this.#Br.values()];this.#Fr.clear(),this.#Br.clear();for(const t of e)this.#Ar.detachSourceMap(t),this.dispatchEventToListeners(Yt.StyleSheetRemoved,t)}resetFontFaces(){this.#Pr.clear()}async suspendModel(){this.#Tr=!1,await this.agent.invoke_disable(),this.resetStyleSheets(),this.resetFontFaces()}async resumeModel(){return this.enable()}setEffectivePropertyValueForNode(e,t,n){this.agent.invoke_setEffectivePropertyValueForNode({nodeId:e,propertyName:t,value:n})}cachedMatchedCascadeForNode(e){if(this.#Dr!==e&&this.discardCachedMatchedCascade(),this.#Dr=e,!this.#Ur){if(!e.id)return Promise.resolve(null);this.#Ur=this.getMatchedStyles(e.id)}return this.#Ur}discardCachedMatchedCascade(){this.#Dr=null,this.#Ur=null}createCSSPropertyTracker(e){return new ln(this,e)}enableCSSPropertyTracker(e){const t=e.getTrackedProperties();0!==t.length&&(this.agent.invoke_trackComputedStyleUpdates({propertiesToTrack:t}),this.#qr=!0,this.#Hr=e,this.pollComputedStyleUpdates())}disableCSSPropertyTracker(){this.#qr=!1,this.#Hr=null,this.agent.invoke_trackComputedStyleUpdates({propertiesToTrack:[]})}async pollComputedStyleUpdates(){if(!this.#zr){if(this.#qr){this.#zr=!0;const e=await this.agent.invoke_takeComputedStyleUpdates();if(this.#zr=!1,e.getError()||!e.nodeIds||!this.#qr)return;this.#Hr&&this.#Hr.dispatchEventToListeners(cn.TrackedCSSPropertiesUpdated,e.nodeIds.map((e=>this.#Mr.nodeForId(e))))}this.#qr&&this.#Nr.schedule(this.pollComputedStyleUpdates.bind(this))}}dispose(){this.disableCSSPropertyTracker(),super.dispose(),this.#Ar.dispose()}getAgent(){return this.agent}}!function(e){e.FontsUpdated="FontsUpdated",e.MediaQueryResultChanged="MediaQueryResultChanged",e.ModelWasEnabled="ModelWasEnabled",e.PseudoStateForced="PseudoStateForced",e.StyleSheetAdded="StyleSheetAdded",e.StyleSheetChanged="StyleSheetChanged",e.StyleSheetRemoved="StyleSheetRemoved"}(Yt||(Yt={}));const tn="pseudo-state-marker";class nn{styleSheetId;oldRange;newRange;newText;payload;constructor(e,t,n,s){this.styleSheetId=e,this.oldRange=t,this.newRange=r.TextRange.TextRange.fromEdit(t,n),this.newText=n,this.payload=s}}class rn{#Sn;styleSheetId;url;lineNumber;columnNumber;constructor(e,t,n){this.#Sn=e.cssModel(),this.styleSheetId=e.id,this.url=e.resourceURL(),this.lineNumber=t,this.columnNumber=n||0}cssModel(){return this.#Sn}header(){return this.#Sn.styleSheetHeaderForId(this.styleSheetId)}}class sn{#jr;constructor(e){this.#jr=e}mediaQueryResultChanged(){this.#jr.mediaQueryResultChanged()}fontsUpdated({font:e}){this.#jr.fontsUpdated(e)}styleSheetChanged({styleSheetId:e}){this.#jr.fireStyleSheetChanged(e)}styleSheetAdded({header:e}){this.#jr.styleSheetAdded(e)}styleSheetRemoved({styleSheetId:e}){this.#jr.styleSheetRemoved(e)}}class an{#jr;#Wr;constructor(e){this.#jr=e,this.#Wr=new Map}computedStylePromise(e){let t=this.#Wr.get(e);return t||(t=this.#jr.getAgent().invoke_getComputedStyleForNode({nodeId:e}).then((({computedStyle:t})=>{if(this.#Wr.delete(e),!t||!t.length)return null;const n=new Map;for(const e of t)n.set(e.name,e.value);return n})),this.#Wr.set(e,t),t)}}class on{inlineStyle;attributesStyle;constructor(e,t){this.inlineStyle=e,this.attributesStyle=t}}class ln extends e.ObjectWrapper.ObjectWrapper{#jr;#Vr;constructor(e,t){super(),this.#jr=e,this.#Vr=t}start(){this.#jr.enableCSSPropertyTracker(this)}stop(){this.#jr.disableCSSPropertyTracker()}getTrackedProperties(){return this.#Vr}}const dn=1e3;var cn;!function(e){e.TrackedCSSPropertiesUpdated="TrackedCSSPropertiesUpdated"}(cn||(cn={})),c.register(en,{capabilities:z.DOM,autostart:!0});var hn=Object.freeze({__proto__:null,CSSModel:en,get Events(){return Yt},Edit:nn,CSSLocation:rn,InlineStyleResult:on,CSSPropertyTracker:ln,get CSSPropertyTrackerEvents(){return cn}});class un{#Gr;#Kr;constructor(){const t="rgba";this.#Gr=[new e.Color.Legacy([.9607843137254902,.592156862745098,.5803921568627451,1],t),new e.Color.Legacy([.9411764705882353,.7490196078431373,.2980392156862745,1],t),new e.Color.Legacy([.8313725490196079,.9294117647058824,.19215686274509805,1],t),new e.Color.Legacy([.6196078431372549,.9215686274509803,.2784313725490196,1],t),new e.Color.Legacy([.3568627450980392,.8196078431372549,.8431372549019608,1],t),new e.Color.Legacy([.7372549019607844,.807843137254902,.984313725490196,1],t),new e.Color.Legacy([.7764705882352941,.7450980392156863,.9333333333333333,1],t),new e.Color.Legacy([.8156862745098039,.5803921568627451,.9176470588235294,1],t),new e.Color.Legacy([.9215686274509803,.5803921568627451,.8117647058823529,1],t)],this.#Kr=0}next(){const e=this.#Gr[this.#Kr];return this.#Kr++,this.#Kr>=this.#Gr.length&&(this.#Kr=0),e}}var gn=Object.freeze({__proto__:null,OverlayColorGenerator:un});class pn{#$r;#Qr;#Xr;#Jr;#Yr;#Zr;#Gr;#es;#ts;#ns;#rs;#ss;#is;#as;constructor(t,n=!0){this.#$r=t,this.#Qr=new Map,this.#Xr=new Map,this.#Jr=new Map,this.#Yr=new Map,this.#Zr=new Map,this.#Gr=new Map,this.#es=new un,this.#ts=new un,this.#ns=n,this.#rs=e.Settings.Settings.instance().moduleSetting("showGridLineLabels"),this.#rs.addChangeListener(this.onSettingChange,this),this.#ss=e.Settings.Settings.instance().moduleSetting("extendGridLines"),this.#ss.addChangeListener(this.onSettingChange,this),this.#is=e.Settings.Settings.instance().moduleSetting("showGridAreas"),this.#is.addChangeListener(this.onSettingChange,this),this.#as=e.Settings.Settings.instance().moduleSetting("showGridTrackSizes"),this.#as.addChangeListener(this.onSettingChange,this)}onSettingChange(){this.resetOverlay()}buildGridHighlightConfig(e){const t=this.colorOfGrid(e).asLegacyColor(),n=t.setAlpha(.1).asLegacyColor(),r=t.setAlpha(.3).asLegacyColor(),s=t.setAlpha(.8).asLegacyColor(),i=this.#ss.get(),a="lineNumbers"===this.#rs.get(),o=a,l="lineNames"===this.#rs.get();return{rowGapColor:r.toProtocolRGBA(),rowHatchColor:s.toProtocolRGBA(),columnGapColor:r.toProtocolRGBA(),columnHatchColor:s.toProtocolRGBA(),gridBorderColor:t.toProtocolRGBA(),gridBorderDash:!1,rowLineColor:t.toProtocolRGBA(),columnLineColor:t.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0,showGridExtensionLines:i,showPositiveLineNumbers:a,showNegativeLineNumbers:o,showLineNames:l,showAreaNames:this.#is.get(),showTrackSizes:this.#as.get(),areaBorderColor:t.toProtocolRGBA(),gridBackgroundColor:n.toProtocolRGBA()}}buildFlexContainerHighlightConfig(e){const t=this.colorOfFlex(e).asLegacyColor();return{containerBorder:{color:t.toProtocolRGBA(),pattern:"dashed"},itemSeparator:{color:t.toProtocolRGBA(),pattern:"dotted"},lineSeparator:{color:t.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:t.toProtocolRGBA()},crossDistributedSpace:{hatchColor:t.toProtocolRGBA()}}}buildScrollSnapContainerHighlightConfig(t){return{snapAreaBorder:{color:e.Color.PageHighlight.GridBorder.toProtocolRGBA(),pattern:"dashed"},snapportBorder:{color:e.Color.PageHighlight.GridBorder.toProtocolRGBA()},scrollMarginColor:e.Color.PageHighlight.Margin.toProtocolRGBA(),scrollPaddingColor:e.Color.PageHighlight.Padding.toProtocolRGBA()}}highlightGridInOverlay(e){this.#Qr.set(e,this.buildGridHighlightConfig(e)),this.updateHighlightsInOverlay()}isGridHighlighted(e){return this.#Qr.has(e)}colorOfGrid(e){let t=this.#Gr.get(e);return t||(t=this.#es.next(),this.#Gr.set(e,t)),t}setColorOfGrid(e,t){this.#Gr.set(e,t)}hideGridInOverlay(e){this.#Qr.has(e)&&(this.#Qr.delete(e),this.updateHighlightsInOverlay())}highlightScrollSnapInOverlay(e){this.#Xr.set(e,this.buildScrollSnapContainerHighlightConfig(e)),this.updateHighlightsInOverlay()}isScrollSnapHighlighted(e){return this.#Xr.has(e)}hideScrollSnapInOverlay(e){this.#Xr.has(e)&&(this.#Xr.delete(e),this.updateHighlightsInOverlay())}highlightFlexInOverlay(e){this.#Jr.set(e,this.buildFlexContainerHighlightConfig(e)),this.updateHighlightsInOverlay()}isFlexHighlighted(e){return this.#Jr.has(e)}colorOfFlex(e){let t=this.#Gr.get(e);return t||(t=this.#ts.next(),this.#Gr.set(e,t)),t}setColorOfFlex(e,t){this.#Gr.set(e,t)}hideFlexInOverlay(e){this.#Jr.has(e)&&(this.#Jr.delete(e),this.updateHighlightsInOverlay())}highlightContainerQueryInOverlay(e){this.#Yr.set(e,this.buildContainerQueryContainerHighlightConfig()),this.updateHighlightsInOverlay()}hideContainerQueryInOverlay(e){this.#Yr.has(e)&&(this.#Yr.delete(e),this.updateHighlightsInOverlay())}isContainerQueryHighlighted(e){return this.#Yr.has(e)}buildContainerQueryContainerHighlightConfig(){return{containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},descendantBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}}}highlightIsolatedElementInOverlay(e){this.#Zr.set(e,this.buildIsolationModeHighlightConfig()),this.updateHighlightsInOverlay()}hideIsolatedElementInOverlay(e){this.#Zr.has(e)&&(this.#Zr.delete(e),this.updateHighlightsInOverlay())}isIsolatedElementHighlighted(e){return this.#Zr.has(e)}buildIsolationModeHighlightConfig(){return{resizerColor:e.Color.IsolationModeHighlight.Resizer.toProtocolRGBA(),resizerHandleColor:e.Color.IsolationModeHighlight.ResizerHandle.toProtocolRGBA(),maskColor:e.Color.IsolationModeHighlight.Mask.toProtocolRGBA()}}hideAllInOverlay(){this.#Jr.clear(),this.#Qr.clear(),this.#Xr.clear(),this.#Yr.clear(),this.#Zr.clear(),this.updateHighlightsInOverlay()}refreshHighlights(){const e=this.updateHighlightsForDeletedNodes(this.#Qr),t=this.updateHighlightsForDeletedNodes(this.#Jr),n=this.updateHighlightsForDeletedNodes(this.#Xr),r=this.updateHighlightsForDeletedNodes(this.#Yr),s=this.updateHighlightsForDeletedNodes(this.#Zr);(t||e||n||r||s)&&this.updateHighlightsInOverlay()}updateHighlightsForDeletedNodes(e){let t=!1;for(const n of e.keys())null===this.#$r.getDOMModel().nodeForId(n)&&(e.delete(n),t=!0);return t}resetOverlay(){for(const e of this.#Qr.keys())this.#Qr.set(e,this.buildGridHighlightConfig(e));for(const e of this.#Jr.keys())this.#Jr.set(e,this.buildFlexContainerHighlightConfig(e));for(const e of this.#Xr.keys())this.#Xr.set(e,this.buildScrollSnapContainerHighlightConfig(e));for(const e of this.#Yr.keys())this.#Yr.set(e,this.buildContainerQueryContainerHighlightConfig());for(const e of this.#Zr.keys())this.#Zr.set(e,this.buildIsolationModeHighlightConfig());this.updateHighlightsInOverlay()}updateHighlightsInOverlay(){const e=this.#Qr.size>0||this.#Jr.size>0||this.#Yr.size>0||this.#Zr.size>0;this.#$r.setShowViewportSizeOnResize(!e),this.updateGridHighlightsInOverlay(),this.updateFlexHighlightsInOverlay(),this.updateScrollSnapHighlightsInOverlay(),this.updateContainerQueryHighlightsInOverlay(),this.updateIsolatedElementHighlightsInOverlay()}updateGridHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Qr.entries())t.push({nodeId:e,gridHighlightConfig:n});e.target().overlayAgent().invoke_setShowGridOverlays({gridNodeHighlightConfigs:t})}updateFlexHighlightsInOverlay(){if(!this.#ns)return;const e=this.#$r,t=[];for(const[e,n]of this.#Jr.entries())t.push({nodeId:e,flexContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowFlexOverlays({flexNodeHighlightConfigs:t})}updateScrollSnapHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Xr.entries())t.push({nodeId:e,scrollSnapContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowScrollSnapOverlays({scrollSnapHighlightConfigs:t})}updateContainerQueryHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Yr.entries())t.push({nodeId:e,containerQueryContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowContainerQueryOverlays({containerQueryHighlightConfigs:t})}updateIsolatedElementHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Zr.entries())t.push({nodeId:e,isolationModeHighlightConfig:n});e.target().overlayAgent().invoke_setShowIsolatedElements({isolatedElementHighlightConfigs:t})}}var mn=Object.freeze({__proto__:null,OverlayPersistentHighlighter:pn});const fn={pausedInDebugger:"Paused in debugger"},bn=s.i18n.registerUIStrings("core/sdk/OverlayModel.ts",fn),yn=s.i18n.getLocalizedString.bind(void 0,bn);class vn extends c{#Mr;overlayAgent;#os;#ls;#ds;#cs;#hs;#us;#gs;#ps;#ms;#fs;#bs;#ys;#vs;#Is;#ks;#Ss;#ws;constructor(t){super(t),this.#Mr=t.model(Pn),t.registerOverlayDispatcher(this),this.overlayAgent=t.overlayAgent(),this.#os=t.model(or),this.#os&&(e.Settings.Settings.instance().moduleSetting("disablePausedStateOverlay").addChangeListener(this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.DebuggerPaused,this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.DebuggerResumed,this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.GlobalObjectCleared,this.updatePausedInDebuggerMessage,this)),this.#ls=!1,this.#ds=null,this.#cs=new kn(this),this.#hs=this.#cs,this.#us=e.Settings.Settings.instance().moduleSetting("showPaintRects"),this.#gs=e.Settings.Settings.instance().moduleSetting("showLayoutShiftRegions"),this.#ps=e.Settings.Settings.instance().moduleSetting("showAdHighlights"),this.#ms=e.Settings.Settings.instance().moduleSetting("showDebugBorders"),this.#fs=e.Settings.Settings.instance().moduleSetting("showFPSCounter"),this.#bs=e.Settings.Settings.instance().moduleSetting("showScrollBottleneckRects"),this.#ys=e.Settings.Settings.instance().moduleSetting("showWebVitals"),this.#vs=[],this.#Is=!0,t.suspended()||(this.overlayAgent.invoke_enable(),this.wireAgentToSettings()),this.#ks=new pn(this),this.#Mr.addEventListener(wn.NodeRemoved,(()=>{this.#ks&&this.#ks.refreshHighlights()})),this.#Mr.addEventListener(wn.DocumentUpdated,(()=>{this.#ks&&this.#ks.hideAllInOverlay()})),this.#Ss=new Sn(this),this.#ws=!1}static highlightObjectAsDOMNode(e){const t=e.runtimeModel().target().model(Pn);t&&t.overlayModel().highlightInOverlay({object:e,selectorList:void 0})}static hideDOMNodeHighlight(){for(const e of K.instance().models(vn))e.delayedHideHighlight(0)}static async muteHighlight(){return Promise.all(K.instance().models(vn).map((e=>e.suspendModel())))}static async unmuteHighlight(){return Promise.all(K.instance().models(vn).map((e=>e.resumeModel())))}static highlightRect(e){for(const t of K.instance().models(vn))t.highlightRect(e)}static clearHighlight(){for(const e of K.instance().models(vn))e.clearHighlight()}getDOMModel(){return this.#Mr}highlightRect({x:e,y:t,width:n,height:r,color:s,outlineColor:i}){const a=s||{r:255,g:0,b:255,a:.3},o=i||{r:255,g:0,b:255,a:.5};return this.overlayAgent.invoke_highlightRect({x:e,y:t,width:n,height:r,color:a,outlineColor:o})}clearHighlight(){return this.overlayAgent.invoke_hideHighlight()}async wireAgentToSettings(){this.#vs=[this.#us.addChangeListener((()=>this.overlayAgent.invoke_setShowPaintRects({result:this.#us.get()}))),this.#gs.addChangeListener((()=>this.overlayAgent.invoke_setShowLayoutShiftRegions({result:this.#gs.get()}))),this.#ps.addChangeListener((()=>this.overlayAgent.invoke_setShowAdHighlights({show:this.#ps.get()}))),this.#ms.addChangeListener((()=>this.overlayAgent.invoke_setShowDebugBorders({show:this.#ms.get()}))),this.#fs.addChangeListener((()=>this.overlayAgent.invoke_setShowFPSCounter({show:this.#fs.get()}))),this.#bs.addChangeListener((()=>this.overlayAgent.invoke_setShowScrollBottleneckRects({show:this.#bs.get()}))),this.#ys.addChangeListener((()=>this.overlayAgent.invoke_setShowWebVitals({show:this.#ys.get()})))],this.#us.get()&&this.overlayAgent.invoke_setShowPaintRects({result:!0}),this.#gs.get()&&this.overlayAgent.invoke_setShowLayoutShiftRegions({result:!0}),this.#ps.get()&&this.overlayAgent.invoke_setShowAdHighlights({show:!0}),this.#ms.get()&&this.overlayAgent.invoke_setShowDebugBorders({show:!0}),this.#fs.get()&&this.overlayAgent.invoke_setShowFPSCounter({show:!0}),this.#bs.get()&&this.overlayAgent.invoke_setShowScrollBottleneckRects({show:!0}),this.#ys.get()&&this.overlayAgent.invoke_setShowWebVitals({show:!0}),this.#os&&this.#os.isPaused()&&this.updatePausedInDebuggerMessage(),await this.overlayAgent.invoke_setShowViewportSizeOnResize({show:this.#Is})}async suspendModel(){e.EventTarget.removeEventListeners(this.#vs),await this.overlayAgent.invoke_disable()}async resumeModel(){await Promise.all([this.overlayAgent.invoke_enable(),this.wireAgentToSettings()])}setShowViewportSizeOnResize(e){this.#Is!==e&&(this.#Is=e,this.target().suspended()||this.overlayAgent.invoke_setShowViewportSizeOnResize({show:e}))}updatePausedInDebuggerMessage(){if(this.target().suspended())return;const t=this.#os&&this.#os.isPaused()&&!e.Settings.Settings.instance().moduleSetting("disablePausedStateOverlay").get()?yn(fn.pausedInDebugger):void 0;this.overlayAgent.invoke_setPausedInDebuggerMessage({message:t})}setHighlighter(e){this.#hs=e||this.#cs}async setInspectMode(e,t=!0){await this.#Mr.requestDocument(),this.#ls="none"!==e,this.dispatchEventToListeners(In.InspectModeWillBeToggled,this),this.#hs.setInspectMode(e,this.buildHighlightConfig("all",t))}inspectModeEnabled(){return this.#ls}highlightInOverlay(e,t,n){if(this.#ws)return;this.#ds&&(clearTimeout(this.#ds),this.#ds=null);const r=this.buildHighlightConfig(t);void 0!==n&&(r.showInfo=n),this.#hs.highlightInOverlay(e,r)}highlightInOverlayForTwoSeconds(e){this.highlightInOverlay(e),this.delayedHideHighlight(2e3)}highlightGridInPersistentOverlay(e){this.#ks&&(this.#ks.highlightGridInOverlay(e),this.dispatchEventToListeners(In.PersistentGridOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedGridInPersistentOverlay(e){return!!this.#ks&&this.#ks.isGridHighlighted(e)}hideGridInPersistentOverlay(e){this.#ks&&(this.#ks.hideGridInOverlay(e),this.dispatchEventToListeners(In.PersistentGridOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightScrollSnapInPersistentOverlay(e){this.#ks&&(this.#ks.highlightScrollSnapInOverlay(e),this.dispatchEventToListeners(In.PersistentScrollSnapOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedScrollSnapInPersistentOverlay(e){return!!this.#ks&&this.#ks.isScrollSnapHighlighted(e)}hideScrollSnapInPersistentOverlay(e){this.#ks&&(this.#ks.hideScrollSnapInOverlay(e),this.dispatchEventToListeners(In.PersistentScrollSnapOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightFlexContainerInPersistentOverlay(e){this.#ks&&(this.#ks.highlightFlexInOverlay(e),this.dispatchEventToListeners(In.PersistentFlexContainerOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedFlexContainerInPersistentOverlay(e){return!!this.#ks&&this.#ks.isFlexHighlighted(e)}hideFlexContainerInPersistentOverlay(e){this.#ks&&(this.#ks.hideFlexInOverlay(e),this.dispatchEventToListeners(In.PersistentFlexContainerOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightContainerQueryInPersistentOverlay(e){this.#ks&&(this.#ks.highlightContainerQueryInOverlay(e),this.dispatchEventToListeners(In.PersistentContainerQueryOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedContainerQueryInPersistentOverlay(e){return!!this.#ks&&this.#ks.isContainerQueryHighlighted(e)}hideContainerQueryInPersistentOverlay(e){this.#ks&&(this.#ks.hideContainerQueryInOverlay(e),this.dispatchEventToListeners(In.PersistentContainerQueryOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightSourceOrderInOverlay(t){const n={parentOutlineColor:e.Color.SourceOrderHighlight.ParentOutline.toProtocolRGBA(),childOutlineColor:e.Color.SourceOrderHighlight.ChildOutline.toProtocolRGBA()};this.#Ss.highlightSourceOrderInOverlay(t,n)}colorOfGridInPersistentOverlay(e){return this.#ks?this.#ks.colorOfGrid(e).asString("hex"):null}setColorOfGridInPersistentOverlay(t,n){if(!this.#ks)return;const r=e.Color.parse(n);r&&(this.#ks.setColorOfGrid(t,r),this.#ks.resetOverlay())}colorOfFlexInPersistentOverlay(e){return this.#ks?this.#ks.colorOfFlex(e).asString("hex"):null}setColorOfFlexInPersistentOverlay(t,n){if(!this.#ks)return;const r=e.Color.parse(n);r&&(this.#ks.setColorOfFlex(t,r),this.#ks.resetOverlay())}hideSourceOrderInOverlay(){this.#Ss.hideSourceOrderHighlight()}setSourceOrderActive(e){this.#ws=e}sourceOrderModeActive(){return this.#ws}highlightIsolatedElementInPersistentOverlay(e){this.#ks&&this.#ks.highlightIsolatedElementInOverlay(e)}hideIsolatedElementInPersistentOverlay(e){this.#ks&&this.#ks.hideIsolatedElementInOverlay(e)}isHighlightedIsolatedElementInPersistentOverlay(e){return!!this.#ks&&this.#ks.isIsolatedElementHighlighted(e)}delayedHideHighlight(e){null===this.#ds&&(this.#ds=window.setTimeout((()=>this.highlightInOverlay({clear:!0})),e))}highlightFrame(e){this.#ds&&(clearTimeout(this.#ds),this.#ds=null),this.#hs.highlightFrame(e)}showHingeForDualScreen(e){if(e){const{x:t,y:n,width:r,height:s,contentColor:i,outlineColor:a}=e;this.overlayAgent.invoke_setShowHinge({hingeConfig:{rect:{x:t,y:n,width:r,height:s},contentColor:i,outlineColor:a}})}else this.overlayAgent.invoke_setShowHinge({})}buildHighlightConfig(t="all",n=!1){const r=e.Settings.Settings.instance().moduleSetting("showMetricsRulers").get(),s=e.Settings.Settings.instance().moduleSetting("colorFormat").get(),i={showInfo:"all"===t||"container-outline"===t,showRulers:r,showStyles:n,showAccessibilityInfo:n,showExtensionLines:r,gridHighlightConfig:{},flexContainerHighlightConfig:{},flexItemHighlightConfig:{},contrastAlgorithm:o.Runtime.experiments.isEnabled("APCA")?"apca":"aa"};"all"!==t&&"content"!==t||(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA()),"all"!==t&&"padding"!==t||(i.paddingColor=e.Color.PageHighlight.Padding.toProtocolRGBA()),"all"!==t&&"border"!==t||(i.borderColor=e.Color.PageHighlight.Border.toProtocolRGBA()),"all"!==t&&"margin"!==t||(i.marginColor=e.Color.PageHighlight.Margin.toProtocolRGBA()),"all"===t&&(i.eventTargetColor=e.Color.PageHighlight.EventTarget.toProtocolRGBA(),i.shapeColor=e.Color.PageHighlight.Shape.toProtocolRGBA(),i.shapeMarginColor=e.Color.PageHighlight.ShapeMargin.toProtocolRGBA(),i.gridHighlightConfig={rowGapColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA(),rowHatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),columnGapColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA(),columnHatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0},i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},itemSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},lineSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},crossDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},rowGapSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},columnGapSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}},i.flexItemHighlightConfig={baseSizeBox:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA()},baseSizeBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},flexibilityArrow:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),t.endsWith("gap")&&(i.gridHighlightConfig={gridBorderColor:e.Color.PageHighlight.GridBorder.toProtocolRGBA(),gridBorderDash:!0},"gap"!==t&&"row-gap"!==t||(i.gridHighlightConfig.rowGapColor=e.Color.PageHighlight.GapBackground.toProtocolRGBA(),i.gridHighlightConfig.rowHatchColor=e.Color.PageHighlight.GapHatch.toProtocolRGBA()),"gap"!==t&&"column-gap"!==t||(i.gridHighlightConfig.columnGapColor=e.Color.PageHighlight.GapBackground.toProtocolRGBA(),i.gridHighlightConfig.columnHatchColor=e.Color.PageHighlight.GapHatch.toProtocolRGBA())),t.endsWith("gap")&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}},"gap"!==t&&"row-gap"!==t||(i.flexContainerHighlightConfig.rowGapSpace={hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}),"gap"!==t&&"column-gap"!==t||(i.flexContainerHighlightConfig.columnGapSpace={hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()})),"grid-areas"===t&&(i.gridHighlightConfig={rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0,showAreaNames:!0,areaBorderColor:e.Color.PageHighlight.GridAreaBorder.toProtocolRGBA()}),"grid-template-columns"===t&&(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA(),i.gridHighlightConfig={columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineDash:!0}),"grid-template-rows"===t&&(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA(),i.gridHighlightConfig={rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0}),"justify-content"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}}),"align-content"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},crossDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}}),"align-items"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},lineSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},crossAlignment:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),"flexibility"===t&&(i.flexItemHighlightConfig={baseSizeBox:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA()},baseSizeBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},flexibilityArrow:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),"container-outline"===t&&(i.containerQueryContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}});return new Set(["rgb","hsl","hex"]).has(s)&&(i.colorFormat=s),i}nodeHighlightRequested({nodeId:e}){const t=this.#Mr.nodeForId(e);t&&this.dispatchEventToListeners(In.HighlightNodeRequested,t)}static setInspectNodeHandler(e){vn.inspectNodeHandler=e}inspectNodeRequested({backendNodeId:t}){const n=new Rn(this.target(),t);vn.inspectNodeHandler?n.resolvePromise().then((e=>{e&&vn.inspectNodeHandler&&vn.inspectNodeHandler(e)})):e.Revealer.reveal(n),this.dispatchEventToListeners(In.ExitedInspectMode)}screenshotRequested({viewport:e}){this.dispatchEventToListeners(In.ScreenshotRequested,e),this.dispatchEventToListeners(In.ExitedInspectMode)}inspectModeCanceled(){this.dispatchEventToListeners(In.ExitedInspectMode)}static inspectNodeHandler=null;getOverlayAgent(){return this.overlayAgent}}var In;!function(e){e.InspectModeWillBeToggled="InspectModeWillBeToggled",e.ExitedInspectMode="InspectModeExited",e.HighlightNodeRequested="HighlightNodeRequested",e.ScreenshotRequested="ScreenshotRequested",e.PersistentGridOverlayStateChanged="PersistentGridOverlayStateChanged",e.PersistentFlexContainerOverlayStateChanged="PersistentFlexContainerOverlayStateChanged",e.PersistentScrollSnapOverlayStateChanged="PersistentScrollSnapOverlayStateChanged",e.PersistentContainerQueryOverlayStateChanged="PersistentContainerQueryOverlayStateChanged"}(In||(In={}));class kn{#$r;constructor(e){this.#$r=e}highlightInOverlay(e,t){const{node:n,deferredNode:r,object:s,selectorList:i}={node:void 0,deferredNode:void 0,object:void 0,selectorList:void 0,...e},a=n?n.id:void 0,o=r?r.backendNodeId():void 0,l=s?s.objectId:void 0;a||o||l?this.#$r.target().overlayAgent().invoke_highlightNode({highlightConfig:t,nodeId:a,backendNodeId:o,objectId:l,selector:i}):this.#$r.target().overlayAgent().invoke_hideHighlight()}async setInspectMode(e,t){await this.#$r.target().overlayAgent().invoke_setInspectMode({mode:e,highlightConfig:t})}highlightFrame(t){this.#$r.target().overlayAgent().invoke_highlightFrame({frameId:t,contentColor:e.Color.PageHighlight.Content.toProtocolRGBA(),contentOutlineColor:e.Color.PageHighlight.ContentOutline.toProtocolRGBA()})}}class Sn{#$r;constructor(e){this.#$r=e}highlightSourceOrderInOverlay(e,t){this.#$r.setSourceOrderActive(!0),this.#$r.setShowViewportSizeOnResize(!1),this.#$r.getOverlayAgent().invoke_highlightSourceOrder({sourceOrderConfig:t,nodeId:e.id})}hideSourceOrderHighlight(){this.#$r.setSourceOrderActive(!1),this.#$r.setShowViewportSizeOnResize(!0),this.#$r.clearHighlight()}}c.register(vn,{capabilities:z.DOM,autostart:!0});var wn,Cn=Object.freeze({__proto__:null,OverlayModel:vn,get Events(){return In},SourceOrderHighlighter:Sn});class Tn{#Cs;#Ts;ownerDocument;#Rs;id;index;#xs;#Ms;#Ps;#Ls;nodeValueInternal;#Es;#As;#Os;#Ns;#Fs;#Bs;#Ds;#Us;#Hs;assignedSlot;shadowRootsInternal;#qs;#_s;#zs;childNodeCountInternal;childrenInternal;nextSibling;previousSibling;firstChild;lastChild;parentNode;templateContentInternal;contentDocumentInternal;childDocumentPromiseForTesting;#js;publicId;systemId;internalSubset;name;value;constructor(e){this.#Cs=e,this.#Ts=this.#Cs.getAgent(),this.index=void 0,this.#Ds=null,this.#Us=new Map,this.#Hs=[],this.assignedSlot=null,this.shadowRootsInternal=[],this.#qs=new Map,this.#_s=new Map,this.#zs=0,this.childrenInternal=null,this.nextSibling=null,this.previousSibling=null,this.firstChild=null,this.lastChild=null,this.parentNode=null}static create(e,t,n,r){const s=new Tn(e);return s.init(t,n,r),s}init(e,t,n){if(this.#Ts=this.#Cs.getAgent(),this.ownerDocument=e,this.#Rs=t,this.id=n.nodeId,this.#xs=n.backendNodeId,this.#Cs.registerNode(this),this.#Ms=n.nodeType,this.#Ps=n.nodeName,this.#Ls=n.localName,this.nodeValueInternal=n.nodeValue,this.#Es=n.pseudoType,this.#As=n.pseudoIdentifier,this.#Os=n.shadowRootType,this.#Ns=n.frameId||null,this.#Fs=n.xmlVersion,this.#Bs=Boolean(n.isSVG),n.attributes&&this.setAttributesPayload(n.attributes),this.childNodeCountInternal=n.childNodeCount||0,n.shadowRoots)for(let e=0;ee.creation||null)),this.#Ds}get subtreeMarkerCount(){return this.#zs}domModel(){return this.#Cs}backendNodeId(){return this.#xs}children(){return this.childrenInternal?this.childrenInternal.slice():null}setChildren(e){this.childrenInternal=e}hasAttributes(){return this.#qs.size>0}childNodeCount(){return this.childNodeCountInternal}setChildNodeCount(e){this.childNodeCountInternal=e}hasShadowRoots(){return Boolean(this.shadowRootsInternal.length)}shadowRoots(){return this.shadowRootsInternal.slice()}templateContent(){return this.templateContentInternal||null}contentDocument(){return this.contentDocumentInternal||null}setContentDocument(e){this.contentDocumentInternal=e}isIframe(){return"IFRAME"===this.#Ps}isPortal(){return"PORTAL"===this.#Ps}importedDocument(){return this.#js||null}nodeType(){return this.#Ms}nodeName(){return this.#Ps}pseudoType(){return this.#Es}pseudoIdentifier(){return this.#As}hasPseudoElements(){return this.#Us.size>0}pseudoElements(){return this.#Us}beforePseudoElement(){return this.#Us.get("before")?.at(-1)}afterPseudoElement(){return this.#Us.get("after")?.at(-1)}markerPseudoElement(){return this.#Us.get("marker")?.at(-1)}backdropPseudoElement(){return this.#Us.get("backdrop")?.at(-1)}viewTransitionPseudoElements(){return[...this.#Us.get("view-transition")||[],...this.#Us.get("view-transition-group")||[],...this.#Us.get("view-transition-image-pair")||[],...this.#Us.get("view-transition-old")||[],...this.#Us.get("view-transition-new")||[]]}hasAssignedSlot(){return null!==this.assignedSlot}isInsertionPoint(){return!this.isXMLNode()&&("SHADOW"===this.#Ps||"CONTENT"===this.#Ps||"SLOT"===this.#Ps)}distributedNodes(){return this.#Hs}isInShadowTree(){return this.#Rs}ancestorShadowHost(){const e=this.ancestorShadowRoot();return e?e.parentNode:null}ancestorShadowRoot(){if(!this.#Rs)return null;let e=this;for(;e&&!e.isShadowRoot();)e=e.parentNode;return e}ancestorUserAgentShadowRoot(){const e=this.ancestorShadowRoot();return e&&e.shadowRootType()===Tn.ShadowRootTypes.UserAgent?e:null}isShadowRoot(){return Boolean(this.#Os)}shadowRootType(){return this.#Os||null}nodeNameInCorrectCase(){const e=this.shadowRootType();return e?"#shadow-root ("+e+")":this.localName()?this.localName().length!==this.nodeName().length?this.nodeName():this.localName():this.nodeName()}setNodeName(e,t){this.#Ts.invoke_setNodeName({nodeId:this.id,name:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}localName(){return this.#Ls}nodeValue(){return this.nodeValueInternal}setNodeValueInternal(e){this.nodeValueInternal=e}setNodeValue(e,t){this.#Ts.invoke_setNodeValue({nodeId:this.id,value:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null)}))}getAttribute(e){const t=this.#qs.get(e);return t?t.value:void 0}setAttribute(e,t,n){this.#Ts.invoke_setAttributesAsText({nodeId:this.id,text:t,name:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null)}))}setAttributeValue(e,t,n){this.#Ts.invoke_setAttributeValue({nodeId:this.id,name:e,value:t}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null)}))}setAttributeValuePromise(e,t){return new Promise((n=>this.setAttributeValue(e,t,n)))}attributes(){return[...this.#qs.values()]}async removeAttribute(e){(await this.#Ts.invoke_removeAttribute({nodeId:this.id,name:e})).getError()||(this.#qs.delete(e),this.#Cs.markUndoableState())}getChildNodes(e){this.childrenInternal?e(this.children()):this.#Ts.invoke_requestChildNodes({nodeId:this.id}).then((t=>{e(t.getError()?null:this.children())}))}async getSubtree(e,t){return(await this.#Ts.invoke_requestChildNodes({nodeId:this.id,depth:e,pierce:t})).getError()?null:this.childrenInternal}async getOuterHTML(){const{outerHTML:e}=await this.#Ts.invoke_getOuterHTML({nodeId:this.id});return e}setOuterHTML(e,t){this.#Ts.invoke_setOuterHTML({nodeId:this.id,outerHTML:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null)}))}removeNode(e){return this.#Ts.invoke_removeNode({nodeId:this.id}).then((t=>{t.getError()||this.#Cs.markUndoableState(),e&&e(t.getError()||null)}))}async copyNode(){const{outerHTML:e}=await this.#Ts.invoke_getOuterHTML({nodeId:this.id});return null!==e&&i.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(e),e}path(){function e(e){return(void 0!==e.index||e.isShadowRoot()&&e.parentNode)&&e.#Ps.length}const t=[];let n=this;for(;n&&e(n);){const e="number"==typeof n.index?n.index:n.shadowRootType()===Tn.ShadowRootTypes.UserAgent?"u":"a";t.push([e,n.#Ps]),n=n.parentNode}return t.reverse(),t.join(",")}isAncestor(e){if(!e)return!1;let t=e.parentNode;for(;t;){if(this===t)return!0;t=t.parentNode}return!1}isDescendant(e){return null!==e&&e.isAncestor(this)}frameOwnerFrameId(){return this.#Ns}frameId(){let e=this.parentNode||this;for(;!e.#Ns&&e.parentNode;)e=e.parentNode;return e.#Ns}setAttributesPayload(e){let t=!this.#qs||e.length!==2*this.#qs.size;const n=this.#qs||new Map;this.#qs=new Map;for(let r=0;rt!==e));n&&n.length>0?this.#Us.set(t,n):this.#Us.delete(t)}else{const t=this.shadowRootsInternal.indexOf(e);if(-1!==t)this.shadowRootsInternal.splice(t,1);else{if(!this.childrenInternal)throw new Error("DOMNode._children is expected to not be null.");if(-1===this.childrenInternal.indexOf(e))throw new Error("DOMNode._children is expected to contain the node to be removed.");this.childrenInternal.splice(this.childrenInternal.indexOf(e),1)}}e.parentNode=null,this.#zs-=e.#zs,e.#zs&&this.#Cs.dispatchEventToListeners(wn.MarkersChanged,this),this.renumber()}setChildrenPayload(e){this.childrenInternal=[];for(let t=0;t=0?this.childrenInternal[e-1]:null,t.parentNode=this}}addAttribute(e,t){const n={name:e,value:t,_node:this};this.#qs.set(e,n)}setAttributeInternal(e,t){const n=this.#qs.get(e);n?n.value=t:this.addAttribute(e,t)}removeAttributeInternal(e){this.#qs.delete(e)}copyTo(e,t,n){this.#Ts.invoke_copyTo({nodeId:this.id,targetNodeId:e.id,insertBeforeNodeId:t?t.id:void 0}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}moveTo(e,t,n){this.#Ts.invoke_moveTo({nodeId:this.id,targetNodeId:e.id,insertBeforeNodeId:t?t.id:void 0}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}isXMLNode(){return Boolean(this.#Fs)}setMarker(e,t){if(null!==t){if(this.parentNode&&!this.#_s.has(e))for(let e=this;e;e=e.parentNode)++e.#zs;this.#_s.set(e,t);for(let e=this;e;e=e.parentNode)this.#Cs.dispatchEventToListeners(wn.MarkersChanged,e)}else{if(!this.#_s.has(e))return;this.#_s.delete(e);for(let e=this;e;e=e.parentNode)--e.#zs;for(let e=this;e;e=e.parentNode)this.#Cs.dispatchEventToListeners(wn.MarkersChanged,e)}}marker(e){return this.#_s.get(e)||null}getMarkerKeysForTest(){return[...this.#_s.keys()]}traverseMarkers(e){!function t(n){if(n.#zs){for(const t of n.#_s.keys())e(n,t);if(n.childrenInternal)for(const e of n.childrenInternal)t(e)}}(this)}resolveURL(t){if(!t)return t;for(let n=this;n;n=n.parentNode)if(n instanceof Mn&&n.baseURL)return e.ParsedURL.ParsedURL.completeURL(n.baseURL,t);return null}highlight(e){this.#Cs.overlayModel().highlightInOverlay({node:this,selectorList:void 0},e)}highlightForTwoSeconds(){this.#Cs.overlayModel().highlightInOverlayForTwoSeconds({node:this,selectorList:void 0})}async resolveToObject(e){const{object:t}=await this.#Ts.invoke_resolveNode({nodeId:this.id,backendNodeId:void 0,objectGroup:e});return t&&this.#Cs.runtimeModelInternal.createRemoteObject(t)||null}async boxModel(){const{model:e}=await this.#Ts.invoke_getBoxModel({nodeId:this.id});return e}async setAsInspectedNode(){let e=this;for(e&&e.pseudoType()&&(e=e.parentNode);e;){let t=e.ancestorUserAgentShadowRoot();if(!t)break;if(t=e.ancestorShadowHost(),!t)break;e=t}if(!e)throw new Error("In DOMNode.setAsInspectedNode: node is expected to not be null.");await this.#Ts.invoke_setInspectedNode({nodeId:e.id})}enclosingElementOrSelf(){let e=this;return e&&e.nodeType()===Node.TEXT_NODE&&e.parentNode&&(e=e.parentNode),e&&e.nodeType()!==Node.ELEMENT_NODE&&(e=null),e}async scrollIntoView(){const e=this.enclosingElementOrSelf();if(!e)return;const t=await e.resolveToObject();t&&(t.callFunction((function(){this.scrollIntoViewIfNeeded(!0)})),t.release(),e.highlightForTwoSeconds())}async focus(){const e=this.enclosingElementOrSelf();if(!e)throw new Error("DOMNode.focus expects node to not be null.");const t=await e.resolveToObject();t&&(await t.callFunction((function(){this.focus()})),t.release(),e.highlightForTwoSeconds(),await this.#Cs.target().pageAgent().invoke_bringToFront())}simpleSelector(){const e=this.localName()||this.nodeName().toLowerCase();if(this.nodeType()!==Node.ELEMENT_NODE)return e;const t=this.getAttribute("type"),n=this.getAttribute("id"),r=this.getAttribute("class");if("input"===e&&t&&!n&&!r)return e+'[type="'+CSS.escape(t)+'"]';if(n)return e+"#"+CSS.escape(n);if(r){return("div"===e?"":e)+"."+r.trim().split(/\s+/g).map((e=>CSS.escape(e))).join(".")}return e}}!function(e){let t;!function(e){e.UserAgent="user-agent",e.Open="open",e.Closed="closed"}(t=e.ShadowRootTypes||(e.ShadowRootTypes={}))}(Tn||(Tn={}));class Rn{#Cs;#xs;constructor(e,t){this.#Cs=e.model(Pn),this.#xs=t}resolve(e){this.resolvePromise().then(e)}async resolvePromise(){const e=await this.#Cs.pushNodesByBackendIdsToFrontend(new Set([this.#xs]));return e&&e.get(this.#xs)||null}backendNodeId(){return this.#xs}domModel(){return this.#Cs}highlight(){this.#Cs.overlayModel().highlightInOverlay({deferredNode:this,selectorList:void 0})}}class xn{nodeType;nodeName;deferredNode;constructor(e,t,n,r){this.nodeType=n,this.nodeName=r,this.deferredNode=new Rn(e,t)}}class Mn extends Tn{body;documentElement;documentURL;baseURL;constructor(e,t){super(e),this.body=null,this.documentElement=null,this.init(this,!1,t),this.documentURL=t.documentURL||"",this.baseURL=t.baseURL||""}}class Pn extends c{agent;idToDOMNode=new Map;#Ws;#Vs;runtimeModelInternal;#Gs;#Ks;#$s;#Qs;#Xs;constructor(e){super(e),this.agent=e.domAgent(),this.#Ws=null,this.#Vs=new Set,e.registerDOMDispatcher(new Ln(this)),this.runtimeModelInternal=e.model(Cr),this.#Ks=null,e.suspended()||this.agent.invoke_enable({}),o.Runtime.experiments.isEnabled("captureNodeCreationStacks")&&this.agent.invoke_setNodeStackTracesEnabled({enable:!0})}runtimeModel(){return this.runtimeModelInternal}cssModel(){return this.target().model(en)}overlayModel(){return this.target().model(vn)}static cancelSearch(){for(const e of K.instance().models(Pn))e.cancelSearch()}scheduleMutationEvent(e){this.hasEventListeners(wn.DOMMutated)&&(this.#Gs=(this.#Gs||0)+1,Promise.resolve().then(function(e,t){if(!this.hasEventListeners(wn.DOMMutated)||this.#Gs!==t)return;this.dispatchEventToListeners(wn.DOMMutated,e)}.bind(this,e,this.#Gs)))}requestDocument(){return this.#Ws?Promise.resolve(this.#Ws):(this.#Ks||(this.#Ks=this.requestDocumentInternal()),this.#Ks)}async getOwnerNodeForFrame(e){const t=await this.agent.invoke_getFrameOwner({frameId:e});return t.getError()?null:new Rn(this.target(),t.backendNodeId)}async requestDocumentInternal(){const e=await this.agent.invoke_getDocument({});if(e.getError())return null;const{root:t}=e;if(this.#Ks=null,t&&this.setDocument(t),!this.#Ws)return console.error("No document"),null;const n=this.parentModel();if(n&&!this.#$s){await n.requestDocument();const e=this.target().model(jn)?.mainFrame;if(e){const t=await n.agent.invoke_getFrameOwner({frameId:e.id});!t.getError()&&t.nodeId&&(this.#$s=n.nodeForId(t.nodeId))}}if(this.#$s){const e=this.#$s.contentDocument();this.#$s.setContentDocument(this.#Ws),this.#$s.setChildren([]),this.#Ws?(this.#Ws.parentNode=this.#$s,this.dispatchEventToListeners(wn.NodeInserted,this.#Ws)):e&&this.dispatchEventToListeners(wn.NodeRemoved,{node:e,parent:this.#$s})}return this.#Ws}existingDocument(){return this.#Ws}async pushNodeToFrontend(e){await this.requestDocument();const{nodeId:t}=await this.agent.invoke_requestNode({objectId:e});return t?this.nodeForId(t):null}pushNodeByPathToFrontend(e){return this.requestDocument().then((()=>this.agent.invoke_pushNodeByPathToFrontend({path:e}))).then((({nodeId:e})=>e))}async pushNodesByBackendIdsToFrontend(e){await this.requestDocument();const t=[...e],{nodeIds:n}=await this.agent.invoke_pushNodesByBackendIdsToFrontend({backendNodeIds:t});if(!n)return null;const r=new Map;for(let e=0;e{if(!t)return;const n=this.idToDOMNode.get(e);n&&n.setAttributesPayload(t)&&(this.dispatchEventToListeners(wn.AttrModified,{node:n,name:"style"}),this.scheduleMutationEvent(n))}));this.#Vs.clear()}characterDataModified(e,t){const n=this.idToDOMNode.get(e);n?(n.setNodeValueInternal(t),this.dispatchEventToListeners(wn.CharacterDataModified,n),this.scheduleMutationEvent(n)):console.error("nodeId could not be resolved to a node")}nodeForId(e){return e&&this.idToDOMNode.get(e)||null}documentUpdated(){const e=this.#Ks;this.setDocument(null),this.parentModel()&&!e&&this.requestDocument()}setDocument(e){this.idToDOMNode=new Map,this.#Ws=e&&"nodeId"in e?new Mn(this,e):null,An.instance().dispose(this),this.parentModel()||this.dispatchEventToListeners(wn.DocumentUpdated,this)}setDetachedRoot(e){"#document"===e.nodeName?new Mn(this,e):Tn.create(this,null,!1,e)}setChildNodes(e,t){if(!e&&t.length)return void this.setDetachedRoot(t[0]);this.idToDOMNode.get(e)?.setChildrenPayload(t)}childNodeCountUpdated(e,t){const n=this.idToDOMNode.get(e);n?(n.setChildNodeCount(t),this.dispatchEventToListeners(wn.ChildNodeCountUpdated,n),this.scheduleMutationEvent(n)):console.error("nodeId could not be resolved to a node")}childNodeInserted(e,t,n){const r=this.idToDOMNode.get(e),s=this.idToDOMNode.get(t);if(!r)return void console.error("parentId could not be resolved to a node");const i=r.insertChild(s,n);this.idToDOMNode.set(i.id,i),this.dispatchEventToListeners(wn.NodeInserted,i),this.scheduleMutationEvent(i)}childNodeRemoved(e,t){const n=this.idToDOMNode.get(e),r=this.idToDOMNode.get(t);n&&r?(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r)):console.error("parentId or nodeId could not be resolved to a node")}shadowRootPushed(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=Tn.create(this,n.ownerDocument,!0,t);r.parentNode=n,this.idToDOMNode.set(r.id,r),n.shadowRootsInternal.unshift(r),this.dispatchEventToListeners(wn.NodeInserted,r),this.scheduleMutationEvent(r)}shadowRootPopped(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=this.idToDOMNode.get(t);r&&(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r))}pseudoElementAdded(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=Tn.create(this,n.ownerDocument,!1,t);r.parentNode=n,this.idToDOMNode.set(r.id,r);const s=r.pseudoType();if(!s)throw new Error("DOMModel._pseudoElementAdded expects pseudoType to be defined.");const i=n.pseudoElements().get(s);i?i.push(r):n.pseudoElements().set(s,[r]),this.dispatchEventToListeners(wn.NodeInserted,r),this.scheduleMutationEvent(r)}topLayerElementsUpdated(){this.dispatchEventToListeners(wn.TopLayerElementsChanged)}pseudoElementRemoved(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=this.idToDOMNode.get(t);r&&(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r))}distributedNodesUpdated(e,t){const n=this.idToDOMNode.get(e);n&&(n.setDistributedNodePayloads(t),this.dispatchEventToListeners(wn.DistributedNodesChanged,n),this.scheduleMutationEvent(n))}unbind(e){this.idToDOMNode.delete(e.id);const t=e.children();for(let e=0;t&&ee||[]))}querySelector(e,t){return this.agent.invoke_querySelector({nodeId:e,selector:t}).then((({nodeId:e})=>e))}querySelectorAll(e,t){return this.agent.invoke_querySelectorAll({nodeId:e,selector:t}).then((({nodeIds:e})=>e))}getTopLayerElements(){return this.agent.invoke_getTopLayerElements().then((({nodeIds:e})=>e))}markUndoableState(e){An.instance().markUndoableState(this,e||!1)}async nodeForLocation(e,t,n){const r=await this.agent.invoke_getNodeForLocation({x:e,y:t,includeUserAgentShadowDOM:n});return r.getError()||!r.nodeId?null:this.nodeForId(r.nodeId)}async getContainerForNode(e,t,n,r){const{nodeId:s}=await this.agent.invoke_getContainerForNode({nodeId:e,containerName:t,physicalAxes:n,logicalAxes:r});return s?this.nodeForId(s):null}pushObjectAsNodeToFrontend(e){return e.isNode()&&e.objectId?this.pushNodeToFrontend(e.objectId):Promise.resolve(null)}suspendModel(){return this.agent.invoke_disable().then((()=>this.setDocument(null)))}async resumeModel(){await this.agent.invoke_enable({})}dispose(){An.instance().dispose(this)}parentModel(){const e=this.target().parentTarget();return e?e.model(Pn):null}getAgent(){return this.agent}registerNode(e){this.idToDOMNode.set(e.id,e)}}!function(e){e.AttrModified="AttrModified",e.AttrRemoved="AttrRemoved",e.CharacterDataModified="CharacterDataModified",e.DOMMutated="DOMMutated",e.NodeInserted="NodeInserted",e.NodeRemoved="NodeRemoved",e.DocumentUpdated="DocumentUpdated",e.ChildNodeCountUpdated="ChildNodeCountUpdated",e.DistributedNodesChanged="DistributedNodesChanged",e.MarkersChanged="MarkersChanged",e.TopLayerElementsChanged="TopLayerElementsChanged"}(wn||(wn={}));class Ln{#Mr;constructor(e){this.#Mr=e}documentUpdated(){this.#Mr.documentUpdated()}attributeModified({nodeId:e,name:t,value:n}){this.#Mr.attributeModified(e,t,n)}attributeRemoved({nodeId:e,name:t}){this.#Mr.attributeRemoved(e,t)}inlineStyleInvalidated({nodeIds:e}){this.#Mr.inlineStyleInvalidated(e)}characterDataModified({nodeId:e,characterData:t}){this.#Mr.characterDataModified(e,t)}setChildNodes({parentId:e,nodes:t}){this.#Mr.setChildNodes(e,t)}childNodeCountUpdated({nodeId:e,childNodeCount:t}){this.#Mr.childNodeCountUpdated(e,t)}childNodeInserted({parentNodeId:e,previousNodeId:t,node:n}){this.#Mr.childNodeInserted(e,t,n)}childNodeRemoved({parentNodeId:e,nodeId:t}){this.#Mr.childNodeRemoved(e,t)}shadowRootPushed({hostId:e,root:t}){this.#Mr.shadowRootPushed(e,t)}shadowRootPopped({hostId:e,rootId:t}){this.#Mr.shadowRootPopped(e,t)}pseudoElementAdded({parentId:e,pseudoElement:t}){this.#Mr.pseudoElementAdded(e,t)}pseudoElementRemoved({parentId:e,pseudoElementId:t}){this.#Mr.pseudoElementRemoved(e,t)}distributedNodesUpdated({insertionPointId:e,distributedNodes:t}){this.#Mr.distributedNodesUpdated(e,t)}topLayerElementsUpdated(){this.#Mr.topLayerElementsUpdated()}}let En;class An{#Js;#Kr;#Ys;constructor(){this.#Js=[],this.#Kr=0,this.#Ys=null}static instance(e={forceNew:null}){const{forceNew:t}=e;return En&&!t||(En=new An),En}async markUndoableState(e,t){this.#Ys&&e!==this.#Ys&&(this.#Ys.markUndoableState(),this.#Ys=null),t&&this.#Ys===e||(this.#Js=this.#Js.slice(0,this.#Kr),this.#Js.push(e),this.#Kr=this.#Js.length,t?this.#Ys=e:(await e.getAgent().invoke_markUndoableState(),this.#Ys=null))}async undo(){if(0===this.#Kr)return Promise.resolve();--this.#Kr,this.#Ys=null,await this.#Js[this.#Kr].getAgent().invoke_undo()}async redo(){if(this.#Kr>=this.#Js.length)return Promise.resolve();++this.#Kr,this.#Ys=null,await this.#Js[this.#Kr-1].getAgent().invoke_redo()}dispose(e){let n=0;for(let t=0;t{this.#ai.push(e),this.#Zs&&!this.#Zs.finished||this.innerRequestContent()}))}canonicalMimeType(){return this.contentType().canonicalMimeType()||this.mimeType}async searchInContent(e,t,n){if(!this.frameId)return[];if(this.request)return this.request.searchInContent(e,t,n);return(await this.#Er.target().pageAgent().invoke_searchInResource({frameId:this.frameId,url:this.url,query:e,caseSensitive:t,isRegex:n})).result||[]}async populateImageSource(e){const{content:t}=await this.requestContent(),n=this.#ii;e.src=r.ContentProvider.contentAsDataURL(t,this.#kt,n)||this.#mt}requestFinished(){this.#Zs&&this.#Zs.removeEventListener(Te.FinishedLoading,this.requestFinished,this),this.#ai.length&&this.innerRequestContent()}async innerRequestContent(){if(this.#oi)return;this.#oi=!0;let e=null;if(this.request){const t=await this.request.contentData();t.error||(this.#si=t.content,this.#ii=t.encoded,e={content:t.content,isEncoded:t.encoded})}if(!e){const t=await this.#Er.target().pageAgent().invoke_getResourceContent({frameId:this.frameId,url:this.url}),n=t.getError();n?(this.#si=null,e={content:null,error:n,isEncoded:!1}):(this.#si=t.content,e={content:t.content,isEncoded:t.base64Encoded}),this.#ii=t.base64Encoded}null===this.#si&&(this.#ii=!1);for(const t of this.#ai.splice(0))t(e);this.#oi=void 0}hasTextContent(){return!!this.#ei.isTextType()||this.#ei===e.ResourceType.resourceTypes.Other&&(Boolean(this.#si)&&!this.#ii)}frame(){return this.#Ce?this.#Er.frameForId(this.#Ce):null}statusCode(){return this.#Zs?this.#Zs.statusCode:0}}var Fn,Bn=Object.freeze({__proto__:null,Resource:Nn});class Dn extends c{#li;#di;#ci;constructor(e){super(e),this.#li="",this.#di="",this.#ci=new Set}updateSecurityOrigins(e){const t=this.#ci;this.#ci=e;for(const e of t)this.#ci.has(e)||this.dispatchEventToListeners(Fn.SecurityOriginRemoved,e);for(const e of this.#ci)t.has(e)||this.dispatchEventToListeners(Fn.SecurityOriginAdded,e)}securityOrigins(){return[...this.#ci]}mainSecurityOrigin(){return this.#li}unreachableMainSecurityOrigin(){return this.#di}setMainSecurityOrigin(e,t){this.#li=e,this.#di=t||null,this.dispatchEventToListeners(Fn.MainSecurityOriginChanged,{mainSecurityOrigin:this.#li,unreachableMainSecurityOrigin:this.#di})}}!function(e){e.SecurityOriginAdded="SecurityOriginAdded",e.SecurityOriginRemoved="SecurityOriginRemoved",e.MainSecurityOriginChanged="MainSecurityOriginChanged"}(Fn||(Fn={})),c.register(Dn,{capabilities:z.None,autostart:!1});var Un,Hn=Object.freeze({__proto__:null,SecurityOriginManager:Dn,get Events(){return Fn}});class qn extends c{#hi;#ui;constructor(e){super(e),this.#hi="",this.#ui=new Set}updateStorageKeys(e){const t=this.#ui;this.#ui=e;for(const e of t)this.#ui.has(e)||this.dispatchEventToListeners(Un.StorageKeyRemoved,e);for(const e of this.#ui)t.has(e)||this.dispatchEventToListeners(Un.StorageKeyAdded,e)}storageKeys(){return[...this.#ui]}mainStorageKey(){return this.#hi}setMainStorageKey(e){this.#hi=e,this.dispatchEventToListeners(Un.MainStorageKeyChanged,{mainStorageKey:this.#hi})}}!function(e){e.StorageKeyAdded="StorageKeyAdded",e.StorageKeyRemoved="StorageKeyRemoved",e.MainStorageKeyChanged="MainStorageKeyChanged"}(Un||(Un={})),c.register(qn,{capabilities:z.None,autostart:!1});var _n,zn=Object.freeze({__proto__:null,StorageKeyManager:qn,parseStorageKey:function(t){const n=t.split("^"),r={origin:e.ParsedURL.ParsedURL.extractOrigin(n[0]),components:new Map};for(let e=1;e{this.processCachedResources(e.getError()?null:e.frameTree),this.mainFrame&&this.processPendingEvents(this.mainFrame)}))}static frameForRequest(e){const t=ne.forRequest(e),n=t?t.target().model(jn):null;return n&&e.frameId?n.frameForId(e.frameId):null}static frames(){const e=[];for(const t of K.instance().models(jn))e.push(...t.frames());return e}static resourceForURL(e){for(const t of K.instance().models(jn)){const n=t.mainFrame,r=n?n.resourceForURL(e):null;if(r)return r}return null}static reloadAllPages(e,t){for(const n of K.instance().models(jn))n.target().parentTarget()?.type()!==_.Frame&&n.reloadPage(e,t)}async storageKeyForFrame(e){if(!this.framesInternal.has(e))return null;const t=await this.storageAgent.invoke_getStorageKeyForFrame({frameId:e});return"Frame tree node for given frame not found"===t.getError()?null:t.storageKey}domModel(){return this.target().model(Pn)}processCachedResources(e){e&&":"!==e.frame.url&&(this.dispatchEventToListeners(_n.WillLoadCachedResources),this.addFramesRecursively(null,e),this.target().setInspectedURL(e.frame.url)),this.#mi=!0;const t=this.target().model(Cr);t&&(t.setExecutionContextComparator(this.executionContextComparator.bind(this)),t.fireExecutionContextOrderChanged()),this.dispatchEventToListeners(_n.CachedResourcesLoaded,this)}cachedResourcesLoaded(){return this.#mi}addFrame(e,t){this.framesInternal.set(e.id,e),e.isMainFrame()&&(this.mainFrame=e),this.dispatchEventToListeners(_n.FrameAdded,e),this.updateSecurityOrigins(),this.updateStorageKeys()}frameAttached(e,t,n){const r=t&&this.framesInternal.get(t)||null;if(!this.#mi&&r)return null;if(this.framesInternal.has(e))return null;const s=new Wn(this,r,e,null,n||null);return t&&!r&&(s.crossTargetParentFrameId=t),s.isMainFrame()&&this.mainFrame&&this.frameDetached(this.mainFrame.id,!1),this.addFrame(s,!0),s}frameNavigated(e,t){const n=e.parentId&&this.framesInternal.get(e.parentId)||null;if(!this.#mi&&n)return;let r=this.framesInternal.get(e.id)||null;if(!r&&(r=this.frameAttached(e.id,e.parentId||null),console.assert(Boolean(r)),!r))return;this.dispatchEventToListeners(_n.FrameWillNavigate,r),r.navigate(e),t&&(r.backForwardCacheDetails.restoredFromCache="BackForwardCacheRestore"===t),this.dispatchEventToListeners(_n.FrameNavigated,r),r.isPrimaryFrame()&&this.primaryPageChanged(r,"Navigation");const s=r.resources();for(let e=0;e=0,"Unbalanced call to ResourceTreeModel.resumeReload()"),!this.#bi&&this.#fi){const{ignoreCache:e,scriptToEvaluateOnLoad:t}=this.#fi;this.reloadPage(e,t)}}reloadPage(e,t){if(this.#fi||this.dispatchEventToListeners(_n.PageReloadRequested,this),this.#bi)return void(this.#fi={ignoreCache:e,scriptToEvaluateOnLoad:t});this.#fi=null;const n=this.target().model(ne);n&&n.clearRequests(),this.dispatchEventToListeners(_n.WillReloadPage),this.agent.invoke_reload({ignoreCache:e,scriptToEvaluateOnLoad:t})}navigate(e){return this.agent.invoke_navigate({url:e})}async navigationHistory(){const e=await this.agent.invoke_getNavigationHistory();return e.getError()?null:{currentIndex:e.currentIndex,entries:e.entries}}navigateToHistoryEntry(e){this.agent.invoke_navigateToHistoryEntry({entryId:e.id})}setLifecycleEventsEnabled(e){return this.agent.invoke_setLifecycleEventsEnabled({enabled:e})}async fetchAppManifest(){const e=await this.agent.invoke_getAppManifest();return e.getError()?{url:e.url,data:null,errors:[]}:{url:e.url,data:e.data||null,errors:e.errors}}async getInstallabilityErrors(){return(await this.agent.invoke_getInstallabilityErrors()).installabilityErrors||[]}async getAppId(){return this.agent.invoke_getAppId()}executionContextComparator(e,t){function n(e){let t=e;const n=[];for(;t;)n.push(t),t=t.sameTargetParentFrame();return n.reverse()}if(e.target()!==t.target())return Mr.comparator(e,t);const r=e.frameId?n(this.frameForId(e.frameId)):[],s=t.frameId?n(this.frameForId(t.frameId)):[];let i,a;for(let e=0;;e++)if(!r[e]||!s[e]||r[e]!==s[e]){i=r[e],a=s[e];break}return!i&&a?-1:!a&&i?1:i&&a?i.id.localeCompare(a.id):Mr.comparator(e,t)}getSecurityOriginData(){const t=new Set;let n=null,r=null;for(const s of this.framesInternal.values()){const i=s.securityOrigin;if(i&&(t.add(i),s.isMainFrame()&&(n=i,s.unreachableUrl()))){r=new e.ParsedURL.ParsedURL(s.unreachableUrl()).securityOrigin()}}return{securityOrigins:t,mainSecurityOrigin:n,unreachableMainSecurityOrigin:r}}async getStorageKeyData(){const e=new Set;let t=null;for(const{isMainFrame:n,storageKey:r}of await Promise.all([...this.framesInternal.values()].map((e=>e.getStorageKey(!1).then((t=>({isMainFrame:e.isMainFrame(),storageKey:t})))))))n&&(t=r),r&&e.add(r);return{storageKeys:e,mainStorageKey:t}}updateSecurityOrigins(){const e=this.getSecurityOriginData();this.#gi.setMainSecurityOrigin(e.mainSecurityOrigin||"",e.unreachableMainSecurityOrigin||""),this.#gi.updateSecurityOrigins(e.securityOrigins)}async updateStorageKeys(){const e=await this.getStorageKeyData();this.#pi.setMainStorageKey(e.mainStorageKey||""),this.#pi.updateStorageKeys(e.storageKeys)}async getMainStorageKey(){return this.mainFrame?this.mainFrame.getStorageKey(!1):null}getMainSecurityOrigin(){const e=this.getSecurityOriginData();return e.mainSecurityOrigin||e.unreachableMainSecurityOrigin}onBackForwardCacheNotUsed(e){this.mainFrame&&this.mainFrame.id===e.frameId&&this.mainFrame.loaderId===e.loaderId?(this.mainFrame.setBackForwardCacheDetails(e),this.dispatchEventToListeners(_n.BackForwardCacheDetailsUpdated,this.mainFrame)):this.#yi.add(e)}onPrerenderAttemptCompleted(e){this.mainFrame&&this.mainFrame.id===e.initiatingFrameId?(this.mainFrame.setPrerenderFinalStatus(e.finalStatus),this.dispatchEventToListeners(_n.PrerenderingStatusUpdated,this.mainFrame),e.disallowedApiMethod&&this.mainFrame.setPrerenderDisallowedApiMethod(e.disallowedApiMethod)):this.#vi.add(e),this.dispatchEventToListeners(_n.PrerenderAttemptCompleted,e)}processPendingEvents(e){if(e.isMainFrame()){for(const t of this.#yi)if(e.id===t.frameId&&e.loaderId===t.loaderId){e.setBackForwardCacheDetails(t),this.#yi.delete(t);break}for(const t of this.#vi)if(e.id===t.initiatingFrameId){e.setPrerenderFinalStatus(t.finalStatus),t.disallowedApiMethod&&e.setPrerenderDisallowedApiMethod(t.disallowedApiMethod),this.#vi.delete(t);break}}}}!function(e){e.FrameAdded="FrameAdded",e.FrameNavigated="FrameNavigated",e.FrameDetached="FrameDetached",e.FrameResized="FrameResized",e.FrameWillNavigate="FrameWillNavigate",e.PrimaryPageChanged="PrimaryPageChanged",e.ResourceAdded="ResourceAdded",e.WillLoadCachedResources="WillLoadCachedResources",e.CachedResourcesLoaded="CachedResourcesLoaded",e.DOMContentLoaded="DOMContentLoaded",e.LifecycleEvent="LifecycleEvent",e.Load="Load",e.PageReloadRequested="PageReloadRequested",e.WillReloadPage="WillReloadPage",e.InterstitialShown="InterstitialShown",e.InterstitialHidden="InterstitialHidden",e.BackForwardCacheDetailsUpdated="BackForwardCacheDetailsUpdated",e.PrerenderingStatusUpdated="PrerenderingStatusUpdated",e.PrerenderAttemptCompleted="PrerenderAttemptCompleted",e.JavaScriptDialogOpening="JavaScriptDialogOpening"}(_n||(_n={}));class Wn{#$r;#ki;#E;crossTargetParentFrameId;#Te;#u;#mt;#Si;#wi;#Ci;#Ti;#Ri;#xi;#Mi;#Pi;#Li;#Ei;#Ai;resourcesMap;backForwardCacheDetails={restoredFromCache:void 0,explanations:[],explanationsTree:void 0};prerenderFinalStatus;prerenderDisallowedApiMethod;constructor(e,n,r,s,i){this.#$r=e,this.#ki=n,this.#E=r,this.crossTargetParentFrameId=null,this.#Te=s&&s.loaderId||"",this.#u=s&&s.name,this.#mt=s&&s.url||t.DevToolsPath.EmptyUrlString,this.#Si=s&&s.domainAndRegistry||"",this.#wi=s&&s.securityOrigin,this.#Ti=s&&s.unreachableUrl||t.DevToolsPath.EmptyUrlString,this.#Ri=s?.adFrameStatus,this.#xi=s&&s.secureContextType,this.#Mi=s&&s.crossOriginIsolatedContextType,this.#Pi=s&&s.gatedAPIFeatures,this.#Li=i,this.#Ei=null,this.#Ai=new Set,this.resourcesMap=new Map,this.prerenderFinalStatus=null,this.prerenderDisallowedApiMethod=null,this.#ki&&this.#ki.#Ai.add(this)}isSecureContext(){return null!==this.#xi&&this.#xi.startsWith("Secure")}getSecureContextType(){return this.#xi}isCrossOriginIsolated(){return null!==this.#Mi&&this.#Mi.startsWith("Isolated")}getCrossOriginIsolatedContextType(){return this.#Mi}getGatedAPIFeatures(){return this.#Pi}getCreationStackTraceData(){return{creationStackTrace:this.#Li,creationStackTraceTarget:this.#Ei||this.resourceTreeModel().target()}}navigate(e){this.#Te=e.loaderId,this.#u=e.name,this.#mt=e.url,this.#Si=e.domainAndRegistry,this.#wi=e.securityOrigin,this.getStorageKey(!0),this.#Ti=e.unreachableUrl||t.DevToolsPath.EmptyUrlString,this.#Ri=e?.adFrameStatus,this.#xi=e.secureContextType,this.#Mi=e.crossOriginIsolatedContextType,this.#Pi=e.gatedAPIFeatures,this.backForwardCacheDetails={restoredFromCache:void 0,explanations:[],explanationsTree:void 0};const n=this.resourcesMap.get(this.#mt);this.resourcesMap.clear(),this.removeChildFrames(),n&&n.loaderId===this.#Te&&this.addResource(n)}resourceTreeModel(){return this.#$r}get id(){return this.#E}get name(){return this.#u||""}get url(){return this.#mt}domainAndRegistry(){return this.#Si}async getAdScriptId(e){return(await this.#$r.agent.invoke_getAdScriptId({frameId:e})).adScriptId||null}get securityOrigin(){return this.#wi}getStorageKey(e){return this.#Ci&&!e||(this.#Ci=this.#$r.storageKeyForFrame(this.#E)),this.#Ci}unreachableUrl(){return this.#Ti}get loaderId(){return this.#Te}adFrameType(){return this.#Ri?.adFrameType||"none"}adFrameStatus(){return this.#Ri}get childFrames(){return[...this.#Ai]}sameTargetParentFrame(){return this.#ki}crossTargetParentFrame(){if(!this.crossTargetParentFrameId)return null;const e=this.#$r.target().parentTarget();if(e?.type()!==_.Frame)return null;const t=e.model(jn);return t&&t.framesInternal.get(this.crossTargetParentFrameId)||null}parentFrame(){return this.sameTargetParentFrame()||this.crossTargetParentFrame()}isMainFrame(){return!this.#ki}isOutermostFrame(){return this.#$r.target().parentTarget()?.type()!==_.Frame&&!this.#ki&&!this.crossTargetParentFrameId}isPrimaryFrame(){return!this.#ki&&this.#$r.target()===K.instance().primaryPageTarget()}removeChildFrame(e,t){this.#Ai.delete(e),e.remove(t)}removeChildFrames(){const e=this.#Ai;this.#Ai=new Set;for(const t of e)t.remove(!1)}remove(e){this.removeChildFrames(),this.#$r.framesInternal.delete(this.id),this.#$r.dispatchEventToListeners(_n.FrameDetached,{frame:this,isSwap:e})}addResource(e){this.resourcesMap.get(e.url)!==e&&(this.resourcesMap.set(e.url,e),this.#$r.dispatchEventToListeners(_n.ResourceAdded,e))}addRequest(e){let t=this.resourcesMap.get(e.url());t&&t.request===e||(t=new Nn(this.#$r,e,e.url(),e.documentURL,e.frameId,e.loaderId,e.resourceType(),e.mimeType,null,null),this.resourcesMap.set(t.url,t),this.#$r.dispatchEventToListeners(_n.ResourceAdded,t))}resources(){return Array.from(this.resourcesMap.values())}resourceForURL(e){const t=this.resourcesMap.get(e);if(t)return t;for(const t of this.#Ai){const n=t.resourceForURL(e);if(n)return n}return null}callForFrameResources(e){for(const t of this.resourcesMap.values())if(e(t))return!0;for(const t of this.#Ai)if(t.callForFrameResources(e))return!0;return!1}displayName(){if(this.isOutermostFrame())return s.i18n.lockedString("top");const t=new e.ParsedURL.ParsedURL(this.#mt).displayName;return t?this.#u?this.#u+" ("+t+")":t:s.i18n.lockedString("iframe")}async getOwnerDeferredDOMNode(){const e=this.parentFrame();return e?e.resourceTreeModel().domModel().getOwnerNodeForFrame(this.#E):null}async getOwnerDOMNodeOrDocument(){const e=await this.getOwnerDeferredDOMNode();return e?e.resolvePromise():this.isOutermostFrame()?this.resourceTreeModel().domModel().requestDocument():null}async highlight(){const e=this.parentFrame(),t=this.resourceTreeModel().target().parentTarget(),n=async e=>{const t=await e.getOwnerNodeForFrame(this.#E);t&&e.overlayModel().highlightInOverlay({deferredNode:t,selectorList:""},"all",!0)};if(e)return n(e.resourceTreeModel().domModel());if(t?.type()===_.Frame){const e=t.model(Pn);if(e)return n(e)}const r=await this.resourceTreeModel().domModel().requestDocument();r&&this.resourceTreeModel().domModel().overlayModel().highlightInOverlay({node:r,selectorList:""},"all",!0)}async getPermissionsPolicyState(){const e=await this.resourceTreeModel().target().pageAgent().invoke_getPermissionsPolicyState({frameId:this.#E});return e.getError()?null:e.states}async getOriginTrials(){const e=await this.resourceTreeModel().target().pageAgent().invoke_getOriginTrials({frameId:this.#E});return e.getError()?[]:e.originTrials}setCreationStackTrace(e){this.#Li=e.creationStackTrace,this.#Ei=e.creationStackTraceTarget}setBackForwardCacheDetails(e){this.backForwardCacheDetails.restoredFromCache=!1,this.backForwardCacheDetails.explanations=e.notRestoredExplanations,this.backForwardCacheDetails.explanationsTree=e.notRestoredExplanationsTree}getResourcesMap(){return this.resourcesMap}setPrerenderFinalStatus(e){this.prerenderFinalStatus=e}setPrerenderDisallowedApiMethod(e){this.prerenderDisallowedApiMethod=e}}class Vn{#Er;constructor(e){this.#Er=e}backForwardCacheNotUsed(e){this.#Er.onBackForwardCacheNotUsed(e)}domContentEventFired({timestamp:e}){this.#Er.dispatchEventToListeners(_n.DOMContentLoaded,e)}loadEventFired({timestamp:e}){this.#Er.dispatchEventToListeners(_n.Load,{resourceTreeModel:this.#Er,loadTime:e})}lifecycleEvent({frameId:e,name:t}){this.#Er.dispatchEventToListeners(_n.LifecycleEvent,{frameId:e,name:t})}frameAttached({frameId:e,parentFrameId:t,stack:n}){this.#Er.frameAttached(e,t,n)}frameNavigated({frame:e,type:t}){this.#Er.frameNavigated(e,t)}documentOpened({frame:e}){this.#Er.documentOpened(e)}frameDetached({frameId:e,reason:t}){this.#Er.frameDetached(e,"swap"===t)}frameStartedLoading({}){}frameStoppedLoading({}){}frameRequestedNavigation({}){}frameScheduledNavigation({}){}frameClearedScheduledNavigation({}){}navigatedWithinDocument({}){}frameResized(){this.#Er.dispatchEventToListeners(_n.FrameResized)}javascriptDialogOpening(e){this.#Er.dispatchEventToListeners(_n.JavaScriptDialogOpening,e),e.hasBrowserHandler||this.#Er.agent.invoke_handleJavaScriptDialog({accept:!1})}javascriptDialogClosed({}){}screencastFrame({}){}screencastVisibilityChanged({}){}interstitialShown(){this.#Er.isInterstitialShowing=!0,this.#Er.dispatchEventToListeners(_n.InterstitialShown)}interstitialHidden(){this.#Er.isInterstitialShowing=!1,this.#Er.dispatchEventToListeners(_n.InterstitialHidden)}windowOpen({}){}compilationCacheProduced({}){}fileChooserOpened({}){}downloadWillBegin({}){}downloadProgress(){}}class Gn{#Er;constructor(e){this.#Er=e}ruleSetUpdated(e){}ruleSetRemoved(e){}prerenderAttemptCompleted(e){this.#Er.onPrerenderAttemptCompleted(e)}prefetchStatusUpdated(e){}prerenderStatusUpdated(e){}preloadEnabledStateUpdated(e){}preloadingAttemptSourcesUpdated(){}}c.register(jn,{capabilities:z.DOM,autostart:!0,early:!0});var Kn=Object.freeze({__proto__:null,ResourceTreeModel:jn,get Events(){return _n},ResourceTreeFrame:Wn,PageDispatcher:Vn});const $n={scriptRemovedOrDeleted:"Script removed or deleted.",unableToFetchScriptSource:"Unable to fetch script source."},Qn=s.i18n.registerUIStrings("core/sdk/Script.ts",$n),Xn=s.i18n.getLocalizedString.bind(void 0,Qn);let Jn=null;class Yn{debuggerModel;scriptId;sourceURL;lineOffset;columnOffset;endLine;endColumn;executionContextId;hash;#Oi;#Ni;sourceMapURL;debugSymbols;hasSourceURL;contentLength;originStackTrace;#Fi;#Bi;#Di;#Ui;isModule;constructor(e,t,n,r,s,i,a,o,l,d,c,h,u,g,p,m,f,b,y,v){this.debuggerModel=e,this.scriptId=t,this.sourceURL=n,this.lineOffset=r,this.columnOffset=s,this.endLine=i,this.endColumn=a,this.isModule=p,this.executionContextId=o,this.hash=l,this.#Oi=d,this.#Ni=c,this.sourceMapURL=h,this.debugSymbols=y,this.hasSourceURL=u,this.contentLength=g,this.originStackTrace=m,this.#Fi=f,this.#Bi=b,this.#Di=null,this.#Ui=v}embedderName(){return this.#Ui}target(){return this.debuggerModel.target()}static trimSourceURLComment(e){let t=e.lastIndexOf("//# sourceURL=");if(-1===t&&(t=e.lastIndexOf("//@ sourceURL="),-1===t))return e;const n=e.lastIndexOf("\n",t);if(-1===n)return e;return e.substr(n+1).match(er)?e.substr(0,n):e}isContentScript(){return this.#Oi}codeOffset(){return this.#Fi}isJavaScript(){return"JavaScript"===this.#Bi}isWasm(){return"WebAssembly"===this.#Bi}scriptLanguage(){return this.#Bi}executionContext(){return this.debuggerModel.runtimeModel().executionContext(this.executionContextId)}isLiveEdit(){return this.#Ni}contentURL(){return this.sourceURL}contentType(){return e.ResourceType.resourceTypes.Script}async loadTextContent(){const e=await this.debuggerModel.target().debuggerAgent().invoke_getScriptSource({scriptId:this.scriptId});if(e.getError())throw new Error(e.getError());const{scriptSource:t,bytecode:n}=e;if(n)return{content:n,isEncoded:!0};let r=t||"";return this.hasSourceURL&&this.sourceURL.startsWith("snippet://")&&(r=Yn.trimSourceURLComment(r)),{content:r,isEncoded:!1}}async loadWasmContent(){if(!this.isWasm())throw new Error("Not a wasm script");const t=await this.debuggerModel.target().debuggerAgent().invoke_disassembleWasmModule({scriptId:this.scriptId});if(t.getError())return this.loadTextContent();const{streamId:n,functionBodyOffsets:r,chunk:{lines:s,bytecodeOffsets:i}}=t,a=[],o=[];let l=s.reduce(((e,t)=>e+t.length+1),0);const d="",c=1e9-d.length;if(n)for(;;){const e=await this.debuggerModel.target().debuggerAgent().invoke_nextWasmDisassemblyChunk({streamId:n});if(e.getError())throw new Error(e.getError());const{chunk:{lines:t,bytecodeOffsets:r}}=e;if(l+=t.reduce(((e,t)=>e+t.length+1),0),0===t.length)break;if(l>=c){a.push([d]),o.push([0]);break}a.push(t),o.push(r)}const h=[];for(let e=0;ee){Jn||(Jn={cache:new Map,registry:new FinalizationRegistry((e=>Jn?.cache.delete(e)))});const e=[this.#Bi,this.contentLength,this.lineOffset,this.columnOffset,this.endLine,this.endColumn,this.#Fi,this.hash].join(":"),t=Jn.cache.get(e)?.deref();t?this.#Di=t:(this.#Di=this.requestContentInternal(),Jn.cache.set(e,new WeakRef(this.#Di)),Jn.registry.register(this.#Di,e))}else this.#Di=this.requestContentInternal()}return this.#Di}async requestContentInternal(){if(!this.scriptId)return{content:null,error:Xn($n.scriptRemovedOrDeleted),isEncoded:!1};try{return this.isWasm()?await this.loadWasmContent():await this.loadTextContent()}catch(e){return{content:null,error:Xn($n.unableToFetchScriptSource),isEncoded:!1}}}async getWasmBytecode(){const e=await this.debuggerModel.target().debuggerAgent().invoke_getWasmBytecode({scriptId:this.scriptId});return(await fetch(`data:application/wasm;base64,${e.bytecode}`)).arrayBuffer()}originalContentProvider(){return new r.StaticContentProvider.StaticContentProvider(this.contentURL(),this.contentType(),(()=>this.requestContent()))}async searchInContent(e,t,n){if(!this.scriptId)return[];return((await this.debuggerModel.target().debuggerAgent().invoke_searchInContent({scriptId:this.scriptId,query:e,caseSensitive:t,isRegex:n})).result||[]).map((e=>new r.ContentProvider.SearchMatch(e.lineNumber,e.lineContent)))}appendSourceURLCommentIfNeeded(e){return this.hasSourceURL?e+"\n //# sourceURL="+this.sourceURL:e}async editSource(e){e=Yn.trimSourceURLComment(e),e=this.appendSourceURLCommentIfNeeded(e);const{content:t}=await this.requestContent();if(t===e)return{changed:!1,status:"Ok"};const n=await this.debuggerModel.target().debuggerAgent().invoke_setScriptSource({scriptId:this.scriptId,scriptSource:e,allowTopFrameEditing:!0});if(n.getError())throw new Error(`Script#editSource failed for script with id ${this.scriptId}: ${n.getError()}`);return n.getError()||"Ok"!==n.status||(this.#Di=Promise.resolve({content:e,isEncoded:!1})),this.debuggerModel.dispatchEventToListeners(cr.ScriptSourceWasEdited,{script:this,status:n.status}),{changed:!0,status:n.status,exceptionDetails:n.exceptionDetails}}rawLocation(e,t){return this.containsLocation(e,t)?new ur(this.debuggerModel,this.scriptId,e,t):null}isInlineScript(){const e=!this.lineOffset&&!this.columnOffset;return!this.isWasm()&&Boolean(this.sourceURL)&&!e}isAnonymousScript(){return!this.sourceURL}async setBlackboxedRanges(e){return!(await this.debuggerModel.target().debuggerAgent().invoke_setBlackboxedRanges({scriptId:this.scriptId,positions:e})).getError()}containsLocation(e,t){const n=e===this.lineOffset&&t>=this.columnOffset||e>this.lineOffset,r=e=0:!(r>0)||t(e.start,n.end)<=0}if(0===e.length)return[];e.sort(((e,n)=>e.scriptIdn.scriptId?1:t(e.start,n.start)||t(e.end,n.end)));let r=e[0];const s=[];for(let i=1;ithis.#Hi.setEnabled(e.data)));const n=t.model(jn);n&&n.addEventListener(_n.FrameNavigated,this.onFrameNavigated,this)}sourceMapManager(){return this.#Hi}runtimeModel(){return this.runtimeModelInternal}debuggerEnabled(){return Boolean(this.#Vi)}debuggerId(){return this.#Gi}async enableDebugger(){if(this.#Vi)return;this.#Vi=!0;const t=o.Runtime.Runtime.queryParam("remoteFrontend")||o.Runtime.Runtime.queryParam("ws")?1e7:1e8,n=this.agent.invoke_enable({maxScriptsCacheSize:t});let r;o.Runtime.experiments.isEnabled(o.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)&&(r=this.agent.invoke_setInstrumentationBreakpoint({instrumentation:"beforeScriptExecution"})),this.pauseOnExceptionStateChanged(),this.asyncStackTracesStateChanged(),e.Settings.Settings.instance().moduleSetting("breakpointsActive").get()||this.breakpointsActiveChanged(),this.dispatchEventToListeners(cr.DebuggerWasEnabled,this);const[s]=await Promise.all([n,r]);this.registerDebugger(s)}async syncDebuggerId(){const e=o.Runtime.Runtime.queryParam("remoteFrontend")||o.Runtime.Runtime.queryParam("ws")?1e7:1e8,t=this.agent.invoke_enable({maxScriptsCacheSize:e});return t.then(this.registerDebugger.bind(this)),t}onFrameNavigated(){or.shouldResyncDebuggerId||(or.shouldResyncDebuggerId=!0)}registerDebugger(e){if(e.getError())return;const{debuggerId:t}=e;lr.set(t,this),this.#Gi=t,this.dispatchEventToListeners(cr.DebuggerIsReadyToPause,this)}isReadyToPause(){return Boolean(this.#Gi)}static async modelForDebuggerId(e){return or.shouldResyncDebuggerId&&(await or.resyncDebuggerIdForModels(),or.shouldResyncDebuggerId=!1),lr.get(e)||null}static async resyncDebuggerIdForModels(){const e=lr.values();for(const t of e)t.debuggerEnabled()&&await t.syncDebuggerId()}async disableDebugger(){this.#Vi&&(this.#Vi=!1,await this.asyncStackTracesStateChanged(),await this.agent.invoke_disable(),this.#ea=!1,this.globalObjectCleared(),this.dispatchEventToListeners(cr.DebuggerWasDisabled,this),"string"==typeof this.#Gi&&lr.delete(this.#Gi),this.#Gi=null)}skipAllPauses(e){this.#Ki&&(clearTimeout(this.#Ki),this.#Ki=0),this.agent.invoke_setSkipAllPauses({skip:e})}skipAllPausesUntilReloadOrTimeout(e){this.#Ki&&clearTimeout(this.#Ki),this.agent.invoke_setSkipAllPauses({skip:!0}),this.#Ki=window.setTimeout(this.skipAllPauses.bind(this,!1),e)}pauseOnExceptionStateChanged(){const t=e.Settings.Settings.instance().moduleSetting("pauseOnCaughtException").get();let n;const r=e.Settings.Settings.instance().moduleSetting("pauseOnUncaughtException").get();n=t&&r?"all":t?"caught":r?"uncaught":"none",this.agent.invoke_setPauseOnExceptions({state:n})}asyncStackTracesStateChanged(){const t=!e.Settings.Settings.instance().moduleSetting("disableAsyncStackTraces").get()&&this.#Vi?32:0;return this.agent.invoke_setAsyncCallStackDepth({maxDepth:t})}breakpointsActiveChanged(){this.agent.invoke_setBreakpointsActive({active:e.Settings.Settings.instance().moduleSetting("breakpointsActive").get()})}setComputeAutoStepRangesCallback(e){this.#Qi=e}async computeAutoStepSkipList(e){let t=[];if(this.#Qi&&this.#qi&&this.#qi.callFrames.length>0){const[n]=this.#qi.callFrames;t=await this.#Qi.call(null,e,n)}return ir(t.map((({start:e,end:t})=>({scriptId:e.scriptId,start:{lineNumber:e.lineNumber,columnNumber:e.columnNumber},end:{lineNumber:t.lineNumber,columnNumber:t.columnNumber}}))))}async stepInto(){const e=await this.computeAutoStepSkipList(ar.StepInto);this.agent.invoke_stepInto({breakOnAsyncCall:!1,skipList:e})}async stepOver(){this.#Zi=this.#qi?.callFrames[0]?.functionLocation()??null;const e=await this.computeAutoStepSkipList(ar.StepOver);this.agent.invoke_stepOver({skipList:e})}async stepOut(){const e=await this.computeAutoStepSkipList(ar.StepOut);0!==e.length?this.agent.invoke_stepOver({skipList:e}):this.agent.invoke_stepOut()}scheduleStepIntoAsync(){this.computeAutoStepSkipList(ar.StepInto).then((e=>{this.agent.invoke_stepInto({breakOnAsyncCall:!0,skipList:e})}))}resume(){this.agent.invoke_resume({terminateOnResume:!1}),this.#ea=!1}pause(){this.#ea=!0,this.skipAllPauses(!1),this.agent.invoke_pause()}async setBreakpointByURL(n,r,s,a){let o;if(this.target().type()===_.Node&&n.startsWith("file://")){const r=e.ParsedURL.ParsedURL.urlToRawPathString(n,i.Platform.isWin());o=`${t.StringUtilities.escapeForRegExp(r)}|${t.StringUtilities.escapeForRegExp(n)}`,i.Platform.isWin()&&r.match(/^.:\\/)&&(o=`[${r[0].toUpperCase()}${r[0].toLowerCase()}]`+o.substr(1))}let l=0;const d=this.#zi.get(n)||[];for(let e=0,t=d.length;eur.fromPayload(this,e)))),{locations:h,breakpointId:c.breakpointId}}async setBreakpointInAnonymousScript(e,t,n,r){const s=await this.agent.invoke_setBreakpointByUrl({lineNumber:t,scriptHash:e,columnNumber:n,condition:r});if(s.getError())return{locations:[],breakpointId:null};let i=[];return s.locations&&(i=s.locations.map((e=>ur.fromPayload(this,e)))),{locations:i,breakpointId:s.breakpointId}}async removeBreakpoint(e){await this.agent.invoke_removeBreakpoint({breakpointId:e})}async getPossibleBreakpoints(e,t,n){const r=await this.agent.invoke_getPossibleBreakpoints({start:e.payload(),end:t?t.payload():void 0,restrictToFunction:n});return r.getError()||!r.locations?[]:r.locations.map((e=>gr.fromPayload(this,e)))}async fetchAsyncStackTrace(e){const t=await this.agent.invoke_getStackTrace({stackTraceId:e});return t.getError()?null:t.stackTrace}breakpointResolved(e,t){this.#Yi.dispatchEventToListeners(e,ur.fromPayload(this,t))}globalObjectCleared(){this.resetDebuggerPausedDetails(),this.reset(),this.dispatchEventToListeners(cr.GlobalObjectCleared,this)}reset(){for(const e of this.#_i.values())this.#Hi.detachSourceMap(e);this.#_i.clear(),this.#zi.clear(),this.#ji=[],this.#Zi=null}scripts(){return Array.from(this.#_i.values())}scriptForId(e){return this.#_i.get(e)||null}scriptsForSourceURL(e){return this.#zi.get(e)||[]}scriptsForExecutionContext(e){const t=[];for(const n of this.#_i.values())n.executionContextId===e.id&&t.push(n);return t}get callFrames(){return this.#qi?this.#qi.callFrames:null}debuggerPausedDetails(){return this.#qi}async setDebuggerPausedDetails(e){return this.#ea=!1,this.#qi=e,!(this.#$i&&!await this.#$i.call(null,e,this.#Zi))&&(this.#Zi=null,this.dispatchEventToListeners(cr.DebuggerPaused,this),this.setSelectedCallFrame(e.callFrames[0]),!0)}resetDebuggerPausedDetails(){this.#ea=!1,this.#qi=null,this.setSelectedCallFrame(null)}setBeforePausedCallback(e){this.#$i=e}setExpandCallFramesCallback(e){this.#Xi=e}setEvaluateOnCallFrameCallback(e){this.evaluateOnCallFrameCallback=e}setSynchronizeBreakpointsCallback(e){this.#Ji=e}async pausedScript(t,n,r,s,i,a){if("instrumentation"===n){const e=this.scriptForId(r.scriptId);return this.#Ji&&e&&await this.#Ji(e),void this.resume()}const o=new fr(this,t,n,r,s,i,a);if(this.#Xi&&(o.callFrames=await this.#Xi.call(null,o.callFrames)),this.continueToLocationCallback){const e=this.continueToLocationCallback;if(this.continueToLocationCallback=null,e(o))return}await this.setDebuggerPausedDetails(o)?e.EventTarget.fireEvent("DevTools.DebuggerPaused"):this.#Zi?this.stepOver():this.stepInto()}resumedScript(){this.resetDebuggerPausedDetails(),this.dispatchEventToListeners(cr.DebuggerResumed,this)}parsedScriptSource(e,t,n,r,s,a,o,l,d,c,h,u,g,p,m,f,b,y,v,I){const k=this.#_i.get(e);if(k)return k;let S=!1;d&&"isDefault"in d&&(S=!d.isDefault);const w=new Yn(this,e,t,n,r,s,a,o,l,S,c,h,u,p,m,f,b,y,v,I);this.registerScript(w),this.dispatchEventToListeners(cr.ParsedScriptSource,w),w.isInlineScript()&&!w.hasSourceURL&&(w.isModule?i.userMetrics.inlineScriptParsed(0):i.userMetrics.inlineScriptParsed(1)),w.sourceMapURL&&!g&&this.#Hi.attachSourceMap(w,w.sourceURL,w.sourceMapURL);return g&&w.isAnonymousScript()&&(this.#ji.push(w),this.collectDiscardedScripts()),w}setSourceMapURL(e,t){this.#Hi.detachSourceMap(e),e.sourceMapURL=t,this.#Hi.attachSourceMap(e,e.sourceURL,e.sourceMapURL)}async setDebugInfoURL(e,t){this.#Xi&&this.#qi&&(this.#qi.callFrames=await this.#Xi.call(null,this.#qi.callFrames)),this.dispatchEventToListeners(cr.DebugInfoAttached,e)}executionContextDestroyed(e){for(const t of this.#_i.values())t.executionContextId===e.id&&this.#Hi.detachSourceMap(t)}registerScript(e){if(this.#_i.set(e.scriptId,e),e.isAnonymousScript())return;let t=this.#zi.get(e.sourceURL);t||(t=[],this.#zi.set(e.sourceURL,t)),t.unshift(e)}unregisterScript(e){console.assert(e.isAnonymousScript()),this.#_i.delete(e.scriptId)}collectDiscardedScripts(){if(this.#ji.length<1e3)return;const e=this.#ji.splice(0,100);for(const t of e)this.unregisterScript(t),this.dispatchEventToListeners(cr.DiscardedAnonymousScriptSource,t)}createRawLocation(e,t,n,r){return this.createRawLocationByScriptId(e.scriptId,t,n,r)}createRawLocationByURL(e,t,n,r){for(const s of this.#zi.get(e)||[])if(!(s.lineOffset>t||s.lineOffset===t&&void 0!==n&&s.columnOffset>n||s.endLinenull===this.#Ta.axNodeForId(e)))}hasUnloadedChildren(){return!(!this.#Na||!this.#Na.length)&&this.#Na.some((e=>null===this.#Ta.axNodeForId(e)))}getFrameId(){return this.#Oa||this.parentNode()?.getFrameId()||null}}(Lr||(Lr={})).TreeUpdated="TreeUpdated";class Or extends c{agent;#Fa;#Ba;#Da;#Ua;#Ha;constructor(e){super(e),e.registerAccessibilityDispatcher(this),this.agent=e.accessibilityAgent(),this.resumeModel(),this.#Fa=new Map,this.#Ba=new Map,this.#Da=new Map,this.#Ua=new Map,this.#Ha=null}clear(){this.#Ha=null,this.#Fa.clear(),this.#Ba.clear(),this.#Da.clear()}async resumeModel(){await this.agent.invoke_enable()}async suspendModel(){await this.agent.invoke_disable()}async requestPartialAXTree(e){const{nodes:t}=await this.agent.invoke_getPartialAXTree({nodeId:e.id,fetchRelatives:!0});if(!t)return;const n=[];for(const e of t)n.push(new Ar(this,e))}loadComplete({root:e}){this.clear(),this.#Ha=new Ar(this,e),this.dispatchEventToListeners(Lr.TreeUpdated,{root:this.#Ha})}nodesUpdated({nodes:e}){this.createNodesFromPayload(e),this.dispatchEventToListeners(Lr.TreeUpdated,{})}createNodesFromPayload(e){return e.map((e=>new Ar(this,e)))}async requestRootNode(e){if(e&&this.#Da.has(e))return this.#Da.get(e);if(!e&&this.#Ha)return this.#Ha;const{node:t}=await this.agent.invoke_getRootAXNode({frameId:e});return t?this.createNodesFromPayload([t])[0]:void 0}async requestAXChildren(e,t){const n=this.#Fa.get(e);if(!n)throw Error("Cannot request children before parent");if(!n.hasUnloadedChildren())return n.children();const r=this.#Ua.get(e);if(r)await r;else{const n=this.agent.invoke_getChildAXNodes({id:e,frameId:t});this.#Ua.set(e,n);const r=await n;r.getError()||(this.createNodesFromPayload(r.nodes),this.#Ua.delete(e))}return n.children()}async requestAndLoadSubTreeToNode(e){const t=[];let n=this.axNodeForDOMNode(e);for(;n;){t.push(n);const e=n.parentNode();if(!e)return t;n=e}const{nodes:r}=await this.agent.invoke_getAXNodeAndAncestors({backendNodeId:e.backendNodeId()});if(!r)return null;return this.createNodesFromPayload(r)}axNodeForId(e){return this.#Fa.get(e)||null}setRootAXNodeForFrameId(e,t){this.#Da.set(e,t)}axNodeForFrameId(e){return this.#Da.get(e)??null}setAXNodeForAXId(e,t){this.#Fa.set(e,t)}axNodeForDOMNode(e){return e?this.#Ba.get(e.backendNodeId())??null:null}setAXNodeForBackendDOMNodeId(e,t){this.#Ba.set(e,t)}getAgent(){return this.agent}}c.register(Or,{capabilities:z.DOM,autostart:!1});var Nr=Object.freeze({__proto__:null,get CoreAxPropertyName(){return Pr},AccessibilityNode:Ar,get Events(){return Lr},AccessibilityModel:Or});class Fr{#qa;titleInternal;enabledInternal;constructor(e,t){this.#qa=e,this.titleInternal=t,this.enabledInternal=!1}category(){return this.#qa}enabled(){return this.enabledInternal}setEnabled(e){this.enabledInternal=e}title(){return this.titleInternal}setTitle(e){this.titleInternal=e}}var Br=Object.freeze({__proto__:null,CategorizedBreakpoint:Fr});class Dr{onMessage;#_a;#za;#ja;#ar;constructor(){this.onMessage=null,this.#_a=null,this.#za="",this.#ja=0,this.#ar=[i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.DispatchMessage,this.dispatchMessage,this),i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.DispatchMessageChunk,this.dispatchMessageChunk,this)]}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}sendRawMessage(e){this.onMessage&&i.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(e)}dispatchMessage(e){this.onMessage&&this.onMessage.call(null,e.data)}dispatchMessageChunk(e){const{messageChunk:t,messageSize:n}=e.data;n&&(this.#za="",this.#ja=n),this.#za+=t,this.#za.length===this.#ja&&this.onMessage&&(this.onMessage.call(null,this.#za),this.#za="",this.#ja=0)}async disconnect(){const t=this.#_a;e.EventTarget.removeEventListeners(this.#ar),this.#_a=null,this.onMessage=null,t&&t.call(null,"force disconnect")}}class Ur{#Wa;onMessage;#_a;#Va;#Ga;#Ka;constructor(e,t){this.#Wa=new WebSocket(e),this.#Wa.onerror=this.onError.bind(this),this.#Wa.onopen=this.onOpen.bind(this),this.#Wa.onmessage=e=>{this.onMessage&&this.onMessage.call(null,e.data)},this.#Wa.onclose=this.onClose.bind(this),this.onMessage=null,this.#_a=null,this.#Va=t,this.#Ga=!1,this.#Ka=[]}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}onError(){this.#Va&&this.#Va.call(null),this.#_a&&this.#_a.call(null,"connection failed"),this.close()}onOpen(){if(this.#Ga=!0,this.#Wa){this.#Wa.onerror=console.error;for(const e of this.#Ka)this.#Wa.send(e)}this.#Ka=[]}onClose(){this.#Va&&this.#Va.call(null),this.#_a&&this.#_a.call(null,"websocket closed"),this.close()}close(e){this.#Wa&&(this.#Wa.onerror=null,this.#Wa.onopen=null,this.#Wa.onclose=e||null,this.#Wa.onmessage=null,this.#Wa.close(),this.#Wa=null),this.#Va=null}sendRawMessage(e){this.#Ga&&this.#Wa?this.#Wa.send(e):this.#Ka.push(e)}disconnect(){return new Promise((e=>{this.close((()=>{this.#_a&&this.#_a.call(null,"force disconnect"),e()}))}))}}class Hr{onMessage;#_a;constructor(){this.onMessage=null,this.#_a=null}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}sendRawMessage(e){window.setTimeout(this.respondWithError.bind(this,e),0)}respondWithError(e){const t=JSON.parse(e),n={message:"This is a stub connection, can't dispatch message.",code:a.InspectorBackend.DevToolsStubErrorCode,data:t};this.onMessage&&this.onMessage.call(null,{id:t.id,error:n})}async disconnect(){this.#_a&&this.#_a.call(null,"force disconnect"),this.#_a=null,this.onMessage=null}}class qr{#$a;#Qa;onMessage;#_a;constructor(e,t){this.#$a=e,this.#Qa=t,this.onMessage=null,this.#_a=null}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}getOnDisconnect(){return this.#_a}sendRawMessage(e){const t=JSON.parse(e);t.sessionId||(t.sessionId=this.#Qa),this.#$a.sendRawMessage(JSON.stringify(t))}getSessionId(){return this.#Qa}async disconnect(){this.#_a&&this.#_a.call(null,"force disconnect"),this.#_a=null,this.onMessage=null}}function _r(e){const t=o.Runtime.Runtime.queryParam("ws"),n=o.Runtime.Runtime.queryParam("wss");if(t||n){return new Ur(t?`ws://${t}`:`wss://${n}`,e)}return i.InspectorFrontendHost.InspectorFrontendHostInstance.isHostedMode()?new Hr:new Dr}var zr,jr=Object.freeze({__proto__:null,MainConnection:Dr,WebSocketConnection:Ur,StubConnection:Hr,ParallelConnection:qr,initMainConnection:async function(e,t){a.InspectorBackend.Connection.setFactory(_r.bind(null,t)),await e(),i.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady(),i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.ReattachRootTarget,(()=>{const t=K.instance().rootTarget();if(t){const e=t.router();e&&e.connection().disconnect()}e()}))}});class Wr extends c{#Xa;#Ja;#Ya;#Za=new Map;#eo=new Map;#to=new Map;#no=new Map;#ro=null;constructor(e){super(e),this.#Xa=e.targetManager(),this.#Ja=e,this.#Ya=e.targetAgent(),e.registerTargetDispatcher(this);const t=this.#Xa.browserTarget();t?t!==e&&t.targetAgent().invoke_autoAttachRelated({targetId:e.id(),waitForDebuggerOnStart:!0}):this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0}),e.parentTarget()?.type()===_.Frame||i.InspectorFrontendHost.isUnderTest()||(this.#Ya.invoke_setDiscoverTargets({discover:!0}),this.#Ya.invoke_setRemoteLocations({locations:[{host:"localhost",port:9229}]}))}static install(e){Wr.attachCallback=e,c.register(Wr,{capabilities:z.Target,autostart:!0})}childTargets(){return Array.from(this.#eo.values())}async suspendModel(){await this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!1,flatten:!0})}async resumeModel(){await this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0})}dispose(){for(const e of this.#eo.keys())this.detachedFromTarget({sessionId:e,targetId:void 0})}targetCreated({targetInfo:e}){this.#Za.set(e.targetId,e),this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetCreated,e)}targetInfoChanged({targetInfo:e}){this.#Za.set(e.targetId,e);const t=this.#to.get(e.targetId);if(t)if("prerender"!==t.targetInfo()?.subtype||e.subtype)t.updateTargetInfo(e);else{const n=t.model(jn);t.updateTargetInfo(e),n&&n.mainFrame&&n.primaryPageChanged(n.mainFrame,"Activation")}this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetInfoChanged,e)}targetDestroyed({targetId:e}){this.#Za.delete(e),this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetDestroyed,e)}targetCrashed({targetId:e,status:t,errorCode:n}){}fireAvailableTargetsChanged(){K.instance().dispatchEventToListeners($.AvailableTargetsChanged,[...this.#Za.values()])}async getParentTargetId(){return this.#ro||(this.#ro=(await this.#Ja.targetAgent().invoke_getTargetInfo({})).targetInfo.targetId),this.#ro}async attachedToTarget({sessionId:t,targetInfo:n,waitingForDebugger:r}){if(this.#ro===n.targetId)return;let s=_.Browser,i="";if("worker"===n.type&&n.title&&n.title!==n.url)i=n.title;else if(!["page","iframe","webview"].includes(n.type))if("chrome://print/"===n.url||n.url.startsWith("chrome://")&&n.url.endsWith(".top-chrome/"))s=_.Frame;else{const t=e.ParsedURL.ParsedURL.fromString(n.url);i=t?t.lastPathComponentWithFragment():"#"+ ++Wr.lastAnonymousTargetId,"devtools"===t?.scheme&&"other"===n.type&&(s=_.Frame)}"iframe"===n.type||"webview"===n.type||"background_page"===n.type||"app"===n.type||"popup_page"===n.type||"page"===n.type?s=_.Frame:"worker"===n.type?s=_.Worker:"shared_worker"===n.type?s=_.SharedWorker:"service_worker"===n.type?s=_.ServiceWorker:"auction_worklet"===n.type&&(s=_.AuctionWorklet);const a=this.#Xa.createTarget(n.targetId,i,s,this.#Ja,t,void 0,void 0,n);this.#eo.set(t,a),this.#to.set(a.id(),a),Wr.attachCallback&&await Wr.attachCallback({target:a,waitingForDebugger:r}),r&&a.runtimeAgent().invoke_runIfWaitingForDebugger()}detachedFromTarget({sessionId:e}){if(this.#no.has(e))this.#no.delete(e);else{const t=this.#eo.get(e);t&&(t.dispose("target terminated"),this.#eo.delete(e),this.#to.delete(t.id()))}}receivedMessageFromTarget({}){}async createParallelConnection(e){const t=await this.getParentTargetId(),{connection:n,sessionId:r}=await this.createParallelConnectionAndSessionForTarget(this.#Ja,t);return n.setOnMessage(e),this.#no.set(r,n),{connection:n,sessionId:r}}async createParallelConnectionAndSessionForTarget(e,t){const n=e.targetAgent(),r=e.router(),s=(await n.invoke_attachToTarget({targetId:t,flatten:!0})).sessionId,i=new qr(r.connection(),s);return r.registerSession(e,s,i),i.setOnDisconnect((()=>{r.unregisterSession(s),n.invoke_detachFromTarget({sessionId:s})})),{connection:i,sessionId:s}}targetInfos(){return Array.from(this.#Za.values())}static lastAnonymousTargetId=0;static attachCallback}!function(e){e.TargetCreated="TargetCreated",e.TargetDestroyed="TargetDestroyed",e.TargetInfoChanged="TargetInfoChanged"}(zr||(zr={}));var Vr=Object.freeze({__proto__:null,ChildTargetManager:Wr,get Events(){return zr}});const Gr={couldNotLoadContentForSS:"Could not load content for {PH1} ({PH2})"},Kr=s.i18n.registerUIStrings("core/sdk/CompilerSourceMappingContentProvider.ts",Gr),$r=s.i18n.getLocalizedString.bind(void 0,Kr);var Qr,Xr,Jr=Object.freeze({__proto__:null,CompilerSourceMappingContentProvider:class{#so;#io;#ao;constructor(e,t,n){this.#so=e,this.#io=t,this.#ao=n}contentURL(){return this.#so}contentType(){return this.#io}async requestContent(){try{const{content:e}=await Ht.instance().loadResource(this.#so,this.#ao);return{content:e,isEncoded:!1}}catch(e){const t=$r(Gr.couldNotLoadContentForSS,{PH1:this.#so,PH2:e.message});return console.error(t),{content:null,error:t,isEncoded:!1}}}async searchInContent(e,t,n){const{content:s}=await this.requestContent();return"string"!=typeof s?[]:r.TextUtils.performSearchInContent(s,e,t,n)}}});!function(e){e.Result="result",e.Command="command",e.System="system",e.QueryObjectResult="queryObjectResult"}(Qr||(Qr={})),function(e){e.CSS="css",e.ConsoleAPI="console-api"}(Xr||(Xr={}));const Yr={profileD:"Profile {PH1}"},Zr=s.i18n.registerUIStrings("core/sdk/CPUProfilerModel.ts",Yr),es=s.i18n.getLocalizedString.bind(void 0,Zr);class ts extends c{#oo;#lo;#do;#co;#ho;#uo;registeredConsoleProfileMessages=[];constructor(e){super(e),this.#oo=!1,this.#lo=1,this.#do=new Map,this.#co=e.profilerAgent(),this.#ho=null,e.registerProfilerDispatcher(this),this.#co.invoke_enable(),this.#uo=e.model(or)}runtimeModel(){return this.#uo.runtimeModel()}debuggerModel(){return this.#uo}consoleProfileStarted({id:e,location:t,title:n}){n||(n=es(Yr.profileD,{PH1:this.#lo++}),this.#do.set(e,n));const r=this.createEventDataFrom(e,t,n);this.dispatchEventToListeners(ns.ConsoleProfileStarted,r)}consoleProfileFinished({id:e,location:t,profile:n,title:r}){r||(r=this.#do.get(e),this.#do.delete(e));const s={...this.createEventDataFrom(e,t,r),cpuProfile:n};this.registeredConsoleProfileMessages.push(s),this.dispatchEventToListeners(ns.ConsoleProfileFinished,s)}createEventDataFrom(e,t,n){const r=ur.fromPayload(this.#uo,t);return{id:this.target().id()+"."+e,scriptLocation:r,title:n||"",cpuProfilerModel:this}}isRecordingProfile(){return this.#oo}startRecording(){this.#oo=!0;return this.#co.invoke_setSamplingInterval({interval:100}),this.#co.invoke_start()}stopRecording(){return this.#oo=!1,this.#co.invoke_stop().then((e=>e.profile||null))}startPreciseCoverage(e,t){this.#ho=t;return this.#co.invoke_startPreciseCoverage({callCount:!1,detailed:e,allowTriggeredUpdates:!0})}async takePreciseCoverage(){const e=await this.#co.invoke_takePreciseCoverage();return{timestamp:e&&e.timestamp||0,coverage:e&&e.result||[]}}stopPreciseCoverage(){return this.#ho=null,this.#co.invoke_stopPreciseCoverage()}preciseCoverageDeltaUpdate({timestamp:e,occasion:t,result:n}){this.#ho&&this.#ho(e,t,n)}}var ns;!function(e){e.ConsoleProfileStarted="ConsoleProfileStarted",e.ConsoleProfileFinished="ConsoleProfileFinished"}(ns||(ns={})),c.register(ts,{capabilities:z.JS,autostart:!0});var rs,ss=Object.freeze({__proto__:null,CPUProfilerModel:ts,get Events(){return ns}});class is extends c{#go;constructor(e){super(e),e.registerLogDispatcher(this),this.#go=e.logAgent(),this.#go.invoke_enable(),i.InspectorFrontendHost.isUnderTest()||this.#go.invoke_startViolationsReport({config:[{name:"longTask",threshold:200},{name:"longLayout",threshold:30},{name:"blockedEvent",threshold:100},{name:"blockedParser",threshold:-1},{name:"handler",threshold:150},{name:"recurringHandler",threshold:50},{name:"discouragedAPIUse",threshold:-1}]})}entryAdded({entry:e}){this.dispatchEventToListeners(rs.EntryAdded,{logModel:this,entry:e})}requestClear(){this.#go.invoke_clear()}}(rs||(rs={})).EntryAdded="EntryAdded",c.register(is,{capabilities:z.Log,autostart:!0});var as=Object.freeze({__proto__:null,LogModel:is,get Events(){return rs}});const os={navigatedToS:"Navigated to {PH1}",bfcacheNavigation:"Navigation to {PH1} was restored from back/forward cache (see https://web.dev/bfcache/)",profileSStarted:"Profile ''{PH1}'' started.",profileSFinished:"Profile ''{PH1}'' finished.",failedToSaveToTempVariable:"Failed to save to temp variable."},ls=s.i18n.registerUIStrings("core/sdk/ConsoleModel.ts",os),ds=s.i18n.getLocalizedString.bind(void 0,ls);class cs extends c{#po;#mo;#fo;#bo;#yo;#vo;#Io;#ko;constructor(n){super(n),this.#po=[],this.#mo=new t.MapUtilities.Multimap,this.#fo=new Map,this.#bo=0,this.#yo=0,this.#vo=0,this.#Io=0,this.#ko=new WeakMap;const r=n.model(jn);if(!r||r.cachedResourcesLoaded())return void this.initTarget(n);const s=r.addEventListener(_n.CachedResourcesLoaded,(()=>{e.EventTarget.removeEventListeners([s]),this.initTarget(n)}))}initTarget(e){const t=[],n=e.model(ts);n&&(t.push(n.addEventListener(ns.ConsoleProfileStarted,this.consoleProfileStarted.bind(this,n))),t.push(n.addEventListener(ns.ConsoleProfileFinished,this.consoleProfileFinished.bind(this,n))));const r=e.model(jn);r&&e.parentTarget()?.type()!==_.Frame&&t.push(r.addEventListener(_n.PrimaryPageChanged,this.primaryPageChanged,this));const s=e.model(Cr);s&&(t.push(s.addEventListener(Rr.ExceptionThrown,this.exceptionThrown.bind(this,s))),t.push(s.addEventListener(Rr.ExceptionRevoked,this.exceptionRevoked.bind(this,s))),t.push(s.addEventListener(Rr.ConsoleAPICalled,this.consoleAPICalled.bind(this,s))),e.parentTarget()?.type()!==_.Frame&&t.push(s.debuggerModel().addEventListener(cr.GlobalObjectCleared,this.clearIfNecessary,this)),t.push(s.addEventListener(Rr.QueryObjectRequested,this.queryObjectRequested.bind(this,s)))),this.#ko.set(e,t)}targetRemoved(t){const n=t.model(Cr);n&&this.#fo.delete(n),e.EventTarget.removeEventListeners(this.#ko.get(t)||[])}async evaluateCommandInConsole(t,n,r,s){const a=await t.evaluate({expression:r,objectGroup:"console",includeCommandLineAPI:s,silent:!1,returnByValue:!1,generatePreview:!0,replMode:!0,allowUnsafeEvalBlockedByCSP:!1},e.Settings.Settings.instance().moduleSetting("consoleUserActivationEval").get(),!1);i.userMetrics.actionTaken(i.UserMetrics.Action.ConsoleEvaluated),"error"in a||(await e.Console.Console.instance().showPromise(),this.dispatchEventToListeners(hs.CommandEvaluated,{result:a.object,commandMessage:n,exceptionDetails:a.exceptionDetails}))}addCommandMessage(e,t){const n=new gs(e.runtimeModel,"javascript",null,t,{type:Qr.Command});return n.setExecutionContextId(e.id),this.addMessage(n),n}addMessage(e){e.setPageLoadSequenceNumber(this.#Io),e.source===Xr.ConsoleAPI&&"clear"===e.type&&this.clearIfNecessary(),this.#po.push(e),this.#mo.set(e.timestamp,e);const t=e.runtimeModel(),n=e.getExceptionId();if(n&&t){let r=this.#fo.get(t);r||(r=new Map,this.#fo.set(t,r)),r.set(n,e)}this.incrementErrorWarningCount(e),this.dispatchEventToListeners(hs.MessageAdded,e)}exceptionThrown(e,t){const n=t.data,r=function(e){if(!e)return;return{requestId:e.requestId||void 0,issueId:e.issueId||void 0}}(n.details.exceptionMetaData),s=gs.fromException(e,n.details,void 0,n.timestamp,void 0,r);s.setExceptionId(n.details.exceptionId),this.addMessage(s)}exceptionRevoked(e,t){const n=t.data,r=this.#fo.get(e),s=r?r.get(n):null;s&&(this.#yo--,s.level="verbose",this.dispatchEventToListeners(hs.MessageUpdated,s))}consoleAPICalled(e,t){const n=t.data;let r="info";"debug"===n.type?r="verbose":"error"===n.type||"assert"===n.type?r="error":"warning"===n.type?r="warning":"info"!==n.type&&"log"!==n.type||(r="info");let s="";n.args.length&&n.args[0].unserializableValue?s=n.args[0].unserializableValue:!n.args.length||"object"==typeof n.args[0].value&&null!==n.args[0].value?n.args.length&&n.args[0].description&&(s=n.args[0].description):s=String(n.args[0].value);const i=n.stackTrace&&n.stackTrace.callFrames.length?n.stackTrace.callFrames[0]:null,a={type:n.type,url:i?.url,line:i?.lineNumber,column:i?.columnNumber,parameters:n.args,stackTrace:n.stackTrace,timestamp:n.timestamp,executionContextId:n.executionContextId,context:n.context},o=new gs(e,Xr.ConsoleAPI,r,s,a);for(const e of this.#mo.get(o.timestamp).values())if(o.isEqual(e))return;this.addMessage(o)}queryObjectRequested(e,t){const{objects:n,executionContextId:r}=t.data,s={type:Qr.QueryObjectResult,parameters:[n],executionContextId:r},i=new gs(e,Xr.ConsoleAPI,"info","",s);this.addMessage(i)}clearIfNecessary(){e.Settings.Settings.instance().moduleSetting("preserveConsoleLog").get()||this.clear(),++this.#Io}primaryPageChanged(t){if(e.Settings.Settings.instance().moduleSetting("preserveConsoleLog").get()){const{frame:n}=t.data;n.backForwardCacheDetails.restoredFromCache?e.Console.Console.instance().log(ds(os.bfcacheNavigation,{PH1:n.url})):e.Console.Console.instance().log(ds(os.navigatedToS,{PH1:n.url}))}}consoleProfileStarted(e,t){const{data:n}=t;this.addConsoleProfileMessage(e,"profile",n.scriptLocation,ds(os.profileSStarted,{PH1:n.title}))}consoleProfileFinished(e,t){const{data:n}=t;this.addConsoleProfileMessage(e,"profileEnd",n.scriptLocation,ds(os.profileSFinished,{PH1:n.title}))}addConsoleProfileMessage(e,t,n,r){const s=n.script(),i=[{functionName:"",scriptId:n.scriptId,url:s?s.contentURL():"",lineNumber:n.lineNumber,columnNumber:n.columnNumber||0}];this.addMessage(new gs(e.runtimeModel(),Xr.ConsoleAPI,"info",r,{type:t,stackTrace:{callFrames:i}}))}incrementErrorWarningCount(e){if("violation"!==e.source)switch(e.level){case"warning":this.#bo++;break;case"error":this.#yo++}else this.#vo++}messages(){return this.#po}static allMessagesUnordered(){const e=[];for(const t of K.instance().targets()){const n=t.model(cs)?.messages()||[];e.push(...n)}return e}static requestClearMessages(){for(const e of K.instance().models(is))e.requestClear();for(const e of K.instance().models(Cr))e.discardConsoleEntries();for(const e of K.instance().targets())e.model(cs)?.clear()}clear(){this.#po=[],this.#mo.clear(),this.#fo.clear(),this.#yo=0,this.#bo=0,this.#vo=0,this.dispatchEventToListeners(hs.ConsoleCleared)}errors(){return this.#yo}static allErrors(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.errors()||0;return e}warnings(){return this.#bo}static allWarnings(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.warnings()||0;return e}violations(){return this.#vo}static allViolations(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.violations()||0;return e}async saveToTempVariable(t,n){if(!n||!t)return void o(null);const r=t,s=await r.globalObject("",!1);if("error"in s||Boolean(s.exceptionDetails)||!s.object)return void o("object"in s&&s.object||null);const i=s.object,a=await i.callFunction((function(e){const t="temp";let n=1;for(;t+n in this;)++n;const r=t+n;return this[r]=e,r}),[Le.toCallArgument(n)]);if(i.release(),a.wasThrown||!a.object||"string"!==a.object.type)o(a.object||null);else{const e=a.object.value,t=this.addCommandMessage(r,e);this.evaluateCommandInConsole(r,t,e,!1)}function o(t){let n=ds(os.failedToSaveToTempVariable);t&&(n=n+" "+t.description),e.Console.Console.instance().error(n)}a.object&&a.object.release()}}var hs;function us(e,t){if(!e!=!t)return!1;if(!e||!t)return!0;const n=e.callFrames,r=t.callFrames;if(n.length!==r.length)return!1;for(let e=0,t=n.length;et.includes(e)));if(-1===n||n===e.length-1)return{callFrame:null,type:null};const r=e[n].url===br?"LOGPOINT":"CONDITIONAL_BREAKPOINT";return{callFrame:e[n+1],type:r}}}c.register(cs,{capabilities:z.JS,autostart:!0});const ps=new Map([["xml","xml"],["javascript","javascript"],["network","network"],[Xr.ConsoleAPI,"console-api"],["storage","storage"],["appcache","appcache"],["rendering","rendering"],[Xr.CSS,"css"],["security","security"],["deprecation","deprecation"],["worker","worker"],["violation","violation"],["intervention","intervention"],["recommendation","recommendation"],["other","other"]]);var ms=Object.freeze({__proto__:null,ConsoleModel:cs,get Events(){return hs},ConsoleMessage:gs,MessageSourceDisplayName:ps,get FrontendMessageSource(){return Xr},get FrontendMessageType(){return Qr}});class fs extends c{#Mo;#Po;constructor(e){super(e),this.#Mo=new Map,this.#Po=new Map}addBlockedCookie(e,t){const n=e.key(),r=this.#Mo.get(n);this.#Mo.set(n,e),t?this.#Po.set(e,t):this.#Po.delete(e),r&&this.#Po.delete(r)}getCookieToBlockedReasonsMap(){return this.#Po}async getCookies(e){const t=await this.target().networkAgent().invoke_getCookies({urls:e});if(t.getError())return[];return t.cookies.map(F.fromProtocolCookie).concat(Array.from(this.#Mo.values()))}async deleteCookie(e){await this.deleteCookies([e])}async clear(e,t){const n=await this.getCookiesForDomain(e||null);if(t){const e=n.filter((e=>e.matchesSecurityOrigin(t)));await this.deleteCookies(e)}else await this.deleteCookies(n)}async saveCookie(e){let t,n=e.domain();n.startsWith(".")||(n=""),e.expires()&&(t=Math.floor(Date.parse(`${e.expires()}`)/1e3));const r=o.Runtime.experiments.isEnabled("experimentalCookieFeatures"),s={name:e.name(),value:e.value(),url:e.url()||void 0,domain:n,path:e.path(),secure:e.secure(),httpOnly:e.httpOnly(),sameSite:e.sameSite(),expires:t,priority:e.priority(),partitionKey:e.partitionKey(),sourceScheme:r?e.sourceScheme():(i=e.sourceScheme(),"Unset"===i?i:void 0),sourcePort:r?e.sourcePort():void 0};var i;const a=await this.target().networkAgent().invoke_setCookie(s);return!(a.getError()||!a.success)&&a.success}getCookiesForDomain(t){const n=[];const r=this.target().model(jn);return r&&(r.mainFrame&&r.mainFrame.unreachableUrl()&&n.push(r.mainFrame.unreachableUrl()),r.forAllResources((function(r){const s=e.ParsedURL.ParsedURL.fromString(r.documentURL);return!s||t&&s.securityOrigin()!==t||n.push(r.url),!1}))),this.getCookies(n)}async deleteCookies(e){const t=this.target().networkAgent();this.#Mo.clear(),this.#Po.clear(),await Promise.all(e.map((e=>t.invoke_deleteCookies({name:e.name(),url:void 0,domain:e.domain(),path:e.path()}))))}}c.register(fs,{capabilities:z.Network,autostart:!1});var bs=Object.freeze({__proto__:null,CookieModel:fs});class ys extends A{id;self;positionTicks;deoptReason;constructor(e,t,n){super(e.callFrame||{functionName:e.functionName,scriptId:e.scriptId,url:e.url,lineNumber:e.lineNumber-1,columnNumber:e.columnNumber-1},n),this.id=e.id,this.self=(e.hitCount||0)*t,this.positionTicks=e.positionTicks,this.deoptReason=e.deoptReason&&"no reason"!==e.deoptReason?e.deoptReason:null}}var vs=Object.freeze({__proto__:null,CPUProfileNode:ys,CPUProfileDataModel:class extends O{profileStartTime;profileEndTime;timestamps;samples;lines;totalHitCount;profileHead;#Lo;gcNode;programNode;idleNode;#Eo;#Ao;constructor(e,t){super(t);Boolean(e.head)?(this.profileStartTime=1e3*e.startTime,this.profileEndTime=1e3*e.endTime,this.timestamps=e.timestamps,this.compatibilityConversionHeadToNodes(e)):(this.profileStartTime=e.startTime/1e3,this.profileEndTime=e.endTime/1e3,this.timestamps=this.convertTimeDeltas(e)),this.samples=e.samples,this.lines=e.lines,this.totalHitCount=0,this.profileHead=this.translateProfileTree(e.nodes),this.initialize(this.profileHead),this.extractMetaNodes(),this.samples&&(this.sortSamples(),this.normalizeTimestamps(),this.fixMissingSamples())}compatibilityConversionHeadToNodes(e){if(!e.head||e.nodes)return;const t=[];!function e(n){return t.push(n),n.children=n.children.map(e),n.id}(e.head),e.nodes=t,delete e.head}convertTimeDeltas(e){if(!e.timeDeltas)return[];let t=e.startTime;const n=new Array(e.timeDeltas.length);for(let r=0;re+(t.hitCount||0)),0);const r=(this.profileEndTime-this.profileStartTime)/this.totalHitCount,s=Boolean(e.Settings.Settings.instance().moduleSetting("showNativeFunctionsInJSProfile").get()),i=t[0],a=new Map([[i.id,i.id]]);this.#Lo=new Map;const o=new ys(i,r,this.target());if(this.#Lo.set(i.id,o),!i.children)throw new Error("Missing children for root");const l=i.children.map((()=>o)),d=i.children.map((e=>n.get(e)));for(;d.length;){let e=l.pop();const t=d.pop();if(!t||!e)continue;t.children||(t.children=[]);const i=new ys(t,r,this.target());s||!((c=t).callFrame?Boolean(c.callFrame.url)&&c.callFrame.url.startsWith("native "):Boolean(c.url)&&c.url.startsWith("native "))?(e.children.push(i),e=i):e.self+=i.self,a.set(t.id,e.id),l.push.apply(l,t.children.map((()=>e))),d.push.apply(d,t.children.map((e=>n.get(e)))),this.#Lo.set(t.id,i)}var c;return this.samples&&(this.samples=this.samples.map((e=>a.get(e)))),o}sortSamples(){if(!this.timestamps||!this.samples)return;const e=this.timestamps,t=this.samples,n=e.map(((e,t)=>t));n.sort(((t,n)=>e[t]-e[n])),this.timestamps=[],this.samples=[];for(let r=0;r=s));I++){const t=i[I];if(t===p)continue;v=o.get(t);let r=o.get(p);if(v!==l){if(r===l&&m){const e=b[h],t=g-e;y[h-1]+=t,n(m.depth+1,l,e,t,t-y[h]),--h,r=m,p=r.id,m=null}for(;v&&v.depth>r.depth;)u.push(v),v=v.parent;for(;r!==v;){const e=b[h],t=g-e;y[h-1]+=t,n(r.depth,r,e,t,t-y[h]),--h,v&&v.depth===r.depth&&(u.push(v),v=v.parent),r=r.parent}for(;u.length;){const t=u.pop();v=t,e(t.depth,t,g),b[++h]=g,y[h]=0}p=t}else m=r,e(m.depth+1,l,g),b[++h]=g,y[h]=0,p=t}if(g=a[I]||this.profileEndTime,m&&o.get(p)===l){const e=b[h],t=g-e;y[h-1]+=t,n(m.depth+1,v,e,t,t-y[h]),--h,p=m.id}for(let e=o.get(p);e&&e.parent;e=e.parent){const t=b[h],r=g-t;y[h-1]+=r,n(e.depth,e,t,r,r-y[h]),--h}}nodeByIndex(e){return this.samples&&this.#Lo.get(this.samples[e])||null}nodes(){return this.#Lo?[...this.#Lo.values()]:null}}});class Is extends c{#Oo;#No;#jr;#Fo;#Bo;#Do;#Uo;#Ho;#qo;#_o;constructor(t){super(t),this.#Oo=t.emulationAgent(),this.#No=t.deviceOrientationAgent(),this.#jr=t.model(en),this.#Fo=t.model(vn),this.#Fo&&this.#Fo.addEventListener(In.InspectModeWillBeToggled,(()=>{this.updateTouch()}),this);const n=e.Settings.Settings.instance().moduleSetting("javaScriptDisabled");n.addChangeListener((async()=>await this.#Oo.invoke_setScriptExecutionDisabled({value:n.get()}))),n.get()&&this.#Oo.invoke_setScriptExecutionDisabled({value:!0});const r=e.Settings.Settings.instance().moduleSetting("emulation.touch");r.addChangeListener((()=>{const e=r.get();this.overrideEmulateTouch("force"===e)}));const s=e.Settings.Settings.instance().moduleSetting("emulation.idleDetection");s.addChangeListener((async()=>{const e=s.get();if("none"===e)return void await this.clearIdleOverride();const t=JSON.parse(e);await this.setIdleOverride(t)}));const i=e.Settings.Settings.instance().moduleSetting("emulatedCSSMedia"),a=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeatureColorGamut"),o=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersColorScheme"),l=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeatureForcedColors"),d=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersContrast"),c=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersReducedData"),h=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersReducedMotion");this.#Bo=new Map([["type",i.get()],["color-gamut",a.get()],["prefers-color-scheme",o.get()],["forced-colors",l.get()],["prefers-contrast",d.get()],["prefers-reduced-data",c.get()],["prefers-reduced-motion",h.get()]]),i.addChangeListener((()=>{this.#Bo.set("type",i.get()),this.updateCssMedia()})),a.addChangeListener((()=>{this.#Bo.set("color-gamut",a.get()),this.updateCssMedia()})),o.addChangeListener((()=>{this.#Bo.set("prefers-color-scheme",o.get()),this.updateCssMedia()})),l.addChangeListener((()=>{this.#Bo.set("forced-colors",l.get()),this.updateCssMedia()})),d.addChangeListener((()=>{this.#Bo.set("prefers-contrast",d.get()),this.updateCssMedia()})),c.addChangeListener((()=>{this.#Bo.set("prefers-reduced-data",c.get()),this.updateCssMedia()})),h.addChangeListener((()=>{this.#Bo.set("prefers-reduced-motion",h.get()),this.updateCssMedia()})),this.updateCssMedia();const u=e.Settings.Settings.instance().moduleSetting("emulateAutoDarkMode");u.addChangeListener((()=>{const e=u.get();o.setDisabled(e),o.set(e?"dark":""),this.emulateAutoDarkMode(e)})),u.get()&&(o.setDisabled(!0),o.set("dark"),this.emulateAutoDarkMode(!0));const g=e.Settings.Settings.instance().moduleSetting("emulatedVisionDeficiency");g.addChangeListener((()=>this.emulateVisionDeficiency(g.get()))),g.get()&&this.emulateVisionDeficiency(g.get());const p=e.Settings.Settings.instance().moduleSetting("localFontsDisabled");p.addChangeListener((()=>this.setLocalFontsDisabled(p.get()))),p.get()&&this.setLocalFontsDisabled(p.get());const m=e.Settings.Settings.instance().moduleSetting("avifFormatDisabled"),f=e.Settings.Settings.instance().moduleSetting("webpFormatDisabled"),b=()=>{const e=[];m.get()&&e.push("avif"),f.get()&&e.push("webp"),this.setDisabledImageTypes(e)};m.addChangeListener(b),f.addChangeListener(b),(m.get()||f.get())&&b(),this.#Ho=!0,this.#Do=!1,this.#Uo=!1,this.#qo=!1,this.#_o={enabled:!1,configuration:"mobile"}}setTouchEmulationAllowed(e){this.#Ho=e}supportsDeviceEmulation(){return this.target().hasAllCapabilities(z.DeviceEmulation)}async resetPageScaleFactor(){await this.#Oo.invoke_resetPageScaleFactor()}async emulateDevice(e){e?await this.#Oo.invoke_setDeviceMetricsOverride(e):await this.#Oo.invoke_clearDeviceMetricsOverride()}overlayModel(){return this.#Fo}async emulateLocation(e){if(!e||e.error)await Promise.all([this.#Oo.invoke_clearGeolocationOverride(),this.#Oo.invoke_setTimezoneOverride({timezoneId:""}),this.#Oo.invoke_setLocaleOverride({locale:""}),this.#Oo.invoke_setUserAgentOverride({userAgent:ue.instance().currentUserAgent()})]);else{function t(e,t){const n=t.getError();return n?Promise.reject({type:e,message:n}):Promise.resolve()}await Promise.all([this.#Oo.invoke_setGeolocationOverride({latitude:e.latitude,longitude:e.longitude,accuracy:ks.defaultGeoMockAccuracy}).then((e=>t("emulation-set-location",e))),this.#Oo.invoke_setTimezoneOverride({timezoneId:e.timezoneId}).then((e=>t("emulation-set-timezone",e))),this.#Oo.invoke_setLocaleOverride({locale:e.locale}).then((e=>t("emulation-set-locale",e))),this.#Oo.invoke_setUserAgentOverride({userAgent:ue.instance().currentUserAgent(),acceptLanguage:e.locale}).then((e=>t("emulation-set-user-agent",e)))])}}async emulateDeviceOrientation(e){e?await this.#No.invoke_setDeviceOrientationOverride({alpha:e.alpha,beta:e.beta,gamma:e.gamma}):await this.#No.invoke_clearDeviceOrientationOverride()}async setIdleOverride(e){await this.#Oo.invoke_setIdleOverride(e)}async clearIdleOverride(){await this.#Oo.invoke_clearIdleOverride()}async emulateCSSMedia(e,t){await this.#Oo.invoke_setEmulatedMedia({media:e,features:t}),this.#jr&&this.#jr.mediaQueryResultChanged()}async emulateAutoDarkMode(e){e&&(this.#Bo.set("prefers-color-scheme","dark"),await this.updateCssMedia()),await this.#Oo.invoke_setAutoDarkModeOverride({enabled:e||void 0})}async emulateVisionDeficiency(e){await this.#Oo.invoke_setEmulatedVisionDeficiency({type:e})}setLocalFontsDisabled(e){this.#jr&&this.#jr.setLocalFontsEnabled(!e)}setDisabledImageTypes(e){this.#Oo.invoke_setDisabledImageTypes({imageTypes:e})}async setCPUThrottlingRate(e){await this.#Oo.invoke_setCPUThrottlingRate({rate:e})}async setHardwareConcurrency(e){if(e<1)throw new Error("hardwareConcurrency must be a positive value");await this.#Oo.invoke_setHardwareConcurrencyOverride({hardwareConcurrency:e})}async emulateTouch(e,t){this.#Do=e&&this.#Ho,this.#Uo=t&&this.#Ho,await this.updateTouch()}async overrideEmulateTouch(e){this.#qo=e&&this.#Ho,await this.updateTouch()}async updateTouch(){let e={enabled:this.#Do,configuration:this.#Uo?"mobile":"desktop"};this.#qo&&(e={enabled:!0,configuration:"mobile"}),this.#Fo&&this.#Fo.inspectModeEnabled()&&(e={enabled:!1,configuration:"mobile"}),(this.#_o.enabled||e.enabled)&&(this.#_o.enabled&&e.enabled&&this.#_o.configuration===e.configuration||(this.#_o=e,await this.#Oo.invoke_setTouchEmulationEnabled({enabled:e.enabled,maxTouchPoints:1}),await this.#Oo.invoke_setEmitTouchEventsForMouse({enabled:e.enabled,configuration:e.configuration})))}async updateCssMedia(){const e=this.#Bo.get("type")??"",t=[{name:"color-gamut",value:this.#Bo.get("color-gamut")??""},{name:"prefers-color-scheme",value:this.#Bo.get("prefers-color-scheme")??""},{name:"forced-colors",value:this.#Bo.get("forced-colors")??""},{name:"prefers-contrast",value:this.#Bo.get("prefers-contrast")??""},{name:"prefers-reduced-data",value:this.#Bo.get("prefers-reduced-data")??""},{name:"prefers-reduced-motion",value:this.#Bo.get("prefers-reduced-motion")??""}];return this.emulateCSSMedia(e,t)}}class ks{latitude;longitude;timezoneId;locale;error;constructor(e,t,n,r,s){this.latitude=e,this.longitude=t,this.timezoneId=n,this.locale=r,this.error=s}static parseSetting(e){if(e){const[t,n,r,s]=e.split(":"),[i,a]=t.split("@");return new ks(parseFloat(i),parseFloat(a),n,r,Boolean(s))}return new ks(0,0,"","",!1)}static parseUserInput(e,t,n,r){if(!e&&!t)return null;const{valid:s}=ks.latitudeValidator(e),{valid:i}=ks.longitudeValidator(t);if(!s&&!i)return null;const a=s?parseFloat(e):-1,o=i?parseFloat(t):-1;return new ks(a,o,n,r,!1)}static latitudeValidator(e){const t=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&t>=-90&&t<=90,errorMessage:void 0}}static longitudeValidator(e){const t=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&t>=-180&&t<=180,errorMessage:void 0}}static timezoneIdValidator(e){return{valid:""===e||/[a-zA-Z]/.test(e),errorMessage:void 0}}static localeValidator(e){return{valid:""===e||/[a-zA-Z]{2}/.test(e),errorMessage:void 0}}toSetting(){return`${this.latitude}@${this.longitude}:${this.timezoneId}:${this.locale}:${this.error||""}`}static defaultGeoMockAccuracy=150}class Ss{alpha;beta;gamma;constructor(e,t,n){this.alpha=e,this.beta=t,this.gamma=n}static parseSetting(e){if(e){const t=JSON.parse(e);return new Ss(t.alpha,t.beta,t.gamma)}return new Ss(0,0,0)}static parseUserInput(e,t,n){if(!e&&!t&&!n)return null;const{valid:r}=Ss.alphaAngleValidator(e),{valid:s}=Ss.betaAngleValidator(t),{valid:i}=Ss.gammaAngleValidator(n);if(!r&&!s&&!i)return null;const a=r?parseFloat(e):-1,o=s?parseFloat(t):-1,l=i?parseFloat(n):-1;return new Ss(a,o,l)}static angleRangeValidator(e,t){const n=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&n>=t.minimum&&n{this.#Wo=n=>{e(n),t(n)}}:e=>{this.#Wo=e});const n=await e.runtimeAgent().invoke_evaluate({expression:"navigator.hardwareConcurrency",returnByValue:!0,silent:!0,throwOnSideEffect:!0}),r=n.getError();if(r)throw new Error(r);const{result:s,exceptionDetails:i}=n;if(i)throw new Error(i.text);return s.value}modelAdded(e){if(this.#zo!==xs.NoThrottling&&e.setCPUThrottlingRate(this.#zo),void 0!==this.#jo&&e.setHardwareConcurrency(this.#jo),this.#Wo){const e=this.#Wo;this.#Wo=void 0,this.getHardwareConcurrency().then(e)}}modelRemoved(e){}}var Rs,xs;!function(e){e.RateChanged="RateChanged",e.HardwareConcurrencyChanged="HardwareConcurrencyChanged"}(Rs||(Rs={})),function(e){e[e.NoThrottling=1]="NoThrottling",e[e.MidTierMobile=4]="MidTierMobile",e[e.LowEndMobile=6]="LowEndMobile"}(xs||(xs={}));var Ms=Object.freeze({__proto__:null,CPUThrottlingManager:Ts,get Events(){return Rs},throttlingManager:function(){return Ts.instance()},get CPUThrottlingRates(){return xs}});const Ps=new Set(["inherit","initial","unset"]),Ls=/[\x20-\x7E]{4}/,Es=new RegExp(`(?:'(${Ls.source})')|(?:"(${Ls.source})")\\s+(${/[+-]?(?:\d*\.)?\d+(?:[eE]\d+)?/.source})`);const As=/^"(.+)"|'(.+)'$/;function Os(e){return e.split(",").map((e=>e.trim()))}function Ns(e){return e.replaceAll(/(\/\*(?:.|\s)*?\*\/)/g,"")}var Fs=Object.freeze({__proto__:null,parseFontVariationSettings:function(e){if(Ps.has(e.trim())||"normal"===e.trim())return[];const t=[];for(const n of Os(Ns(e))){const e=n.match(Es);e&&t.push({tag:e[1]||e[2],value:parseFloat(e[3])})}return t},parseFontFamily:function(e){if(Ps.has(e.trim()))return[];const t=[];for(const n of Os(Ns(e))){const e=n.match(As);e?t.push(e[1]||e[2]):t.push(n)}return t},splitByComma:Os,stripComments:Ns});const Bs={trustedTypeViolations:"Trusted Type Violations",sinkViolations:"Sink Violations",policyViolations:"Policy Violations",animation:"Animation",canvas:"Canvas",geolocation:"Geolocation",notification:"Notification",parse:"Parse",script:"Script",timer:"Timer",window:"Window",webaudio:"WebAudio",media:"Media",pictureinpicture:"Picture-in-Picture",clipboard:"Clipboard",control:"Control",device:"Device",domMutation:"DOM Mutation",dragDrop:"Drag / drop",keyboard:"Keyboard",load:"Load",mouse:"Mouse",pointer:"Pointer",touch:"Touch",xhr:"XHR",setTimeoutOrIntervalFired:"{PH1} fired",scriptFirstStatement:"Script First Statement",scriptBlockedByContentSecurity:"Script Blocked by Content Security Policy",requestAnimationFrame:"Request Animation Frame",cancelAnimationFrame:"Cancel Animation Frame",animationFrameFired:"Animation Frame Fired",webglErrorFired:"WebGL Error Fired",webglWarningFired:"WebGL Warning Fired",setInnerhtml:"Set `innerHTML`",createCanvasContext:"Create canvas context",createAudiocontext:"Create `AudioContext`",closeAudiocontext:"Close `AudioContext`",resumeAudiocontext:"Resume `AudioContext`",suspendAudiocontext:"Suspend `AudioContext`",webglErrorFiredS:"WebGL Error Fired ({PH1})",scriptBlockedDueToContent:"Script blocked due to Content Security Policy directive: {PH1}",worker:"Worker"},Ds=s.i18n.registerUIStrings("core/sdk/DOMDebuggerModel.ts",Bs),Us=s.i18n.getLocalizedString.bind(void 0,Ds);class Hs extends c{agent;#ba;#Mr;#Vo;#Go;suspended=!1;constructor(t){super(t),this.agent=t.domdebuggerAgent(),this.#ba=t.model(Cr),this.#Mr=t.model(Pn),this.#Mr.addEventListener(wn.DocumentUpdated,this.documentUpdated,this),this.#Mr.addEventListener(wn.NodeRemoved,this.nodeRemoved,this),this.#Vo=[],this.#Go=e.Settings.Settings.instance().createLocalSetting("domBreakpoints",[]),this.#Mr.existingDocument()&&this.documentUpdated()}runtimeModel(){return this.#ba}async suspendModel(){this.suspended=!0}async resumeModel(){this.suspended=!1}async eventListeners(e){if(console.assert(e.runtimeModel()===this.#ba),!e.objectId)return[];const t=await this.agent.invoke_getEventListeners({objectId:e.objectId}),n=[];for(const r of t.listeners||[]){const t=this.#ba.debuggerModel().createRawLocationByScriptId(r.scriptId,r.lineNumber,r.columnNumber);t&&n.push(new js(this,e,r.type,r.useCapture,r.passive,r.once,r.handler?this.#ba.createRemoteObject(r.handler):null,r.originalHandler?this.#ba.createRemoteObject(r.originalHandler):null,t,null))}return n}retrieveDOMBreakpoints(){this.#Mr.requestDocument()}domBreakpoints(){return this.#Vo.slice()}hasDOMBreakpoint(e,t){return this.#Vo.some((n=>n.node===e&&n.type===t))}setDOMBreakpoint(e,t){for(const n of this.#Vo)if(n.node===e&&n.type===t)return this.toggleDOMBreakpoint(n,!0),n;const n=new zs(this,e,t,!0);return this.#Vo.push(n),this.saveDOMBreakpoints(),this.enableDOMBreakpoint(n),this.dispatchEventToListeners(qs.DOMBreakpointAdded,n),n}removeDOMBreakpoint(e,t){this.removeDOMBreakpoints((n=>n.node===e&&n.type===t))}removeAllDOMBreakpoints(){this.removeDOMBreakpoints((e=>!0))}toggleDOMBreakpoint(e,t){t!==e.enabled&&(e.enabled=t,t?this.enableDOMBreakpoint(e):this.disableDOMBreakpoint(e),this.dispatchEventToListeners(qs.DOMBreakpointToggled,e))}enableDOMBreakpoint(e){e.node.id&&(this.agent.invoke_setDOMBreakpoint({nodeId:e.node.id,type:e.type}),e.node.setMarker(_s,!0))}disableDOMBreakpoint(e){e.node.id&&(this.agent.invoke_removeDOMBreakpoint({nodeId:e.node.id,type:e.type}),e.node.setMarker(_s,!!this.nodeHasBreakpoints(e.node)||null))}nodeHasBreakpoints(e){for(const t of this.#Vo)if(t.node===e&&t.enabled)return!0;return!1}resolveDOMBreakpointData(e){const t=e.type,n=this.#Mr.nodeForId(e.nodeId);if(!t||!n)return null;let r=null,s=!1;return"subtree-modified"===t&&(s=e.insertion||!1,r=this.#Mr.nodeForId(e.targetNodeId)),{type:t,node:n,targetNode:r,insertion:s}}currentURL(){const e=this.#Mr.existingDocument();return e?e.documentURL:t.DevToolsPath.EmptyUrlString}async documentUpdated(){if(this.suspended)return;const e=this.#Vo;this.#Vo=[],this.dispatchEventToListeners(qs.DOMBreakpointsRemoved,e);const n=await this.#Mr.requestDocument(),r=n?n.documentURL:t.DevToolsPath.EmptyUrlString;for(const e of this.#Go.get())e.url===r&&this.#Mr.pushNodeByPathToFrontend(e.path).then(s.bind(this,e));function s(e,t){const n=t?this.#Mr.nodeForId(t):null;if(!n)return;const r=new zs(this,n,e.type,e.enabled);this.#Vo.push(r),e.enabled&&this.enableDOMBreakpoint(r),this.dispatchEventToListeners(qs.DOMBreakpointAdded,r)}}removeDOMBreakpoints(e){const t=[],n=[];for(const r of this.#Vo)e(r)?(t.push(r),r.enabled&&(r.enabled=!1,this.disableDOMBreakpoint(r))):n.push(r);t.length&&(this.#Vo=n,this.saveDOMBreakpoints(),this.dispatchEventToListeners(qs.DOMBreakpointsRemoved,t))}nodeRemoved(e){if(this.suspended)return;const{node:t}=e.data,n=t.children()||[];this.removeDOMBreakpoints((e=>e.node===t||-1!==n.indexOf(e.node)))}saveDOMBreakpoints(){const e=this.currentURL(),t=this.#Go.get().filter((t=>t.url!==e));for(const n of this.#Vo)t.push({url:e,path:n.node.path(),type:n.type,enabled:n.enabled});this.#Go.set(t)}}var qs;!function(e){e.DOMBreakpointAdded="DOMBreakpointAdded",e.DOMBreakpointToggled="DOMBreakpointToggled",e.DOMBreakpointsRemoved="DOMBreakpointsRemoved"}(qs||(qs={}));const _s="breakpoint-marker";class zs{domDebuggerModel;node;type;enabled;constructor(e,t,n,r){this.domDebuggerModel=e,this.node=t,this.type=n,this.enabled=r}}class js{#Ko;#$o;#p;#Qo;#Xo;#Jo;#Yo;#Zo;#na;#el;#tl;#nl;constructor(e,n,r,s,i,a,o,l,d,c,h){this.#Ko=e,this.#$o=n,this.#p=r,this.#Qo=s,this.#Xo=i,this.#Jo=a,this.#Yo=o,this.#Zo=l||o,this.#na=d;const u=d.script();this.#el=u?u.contentURL():t.DevToolsPath.EmptyUrlString,this.#tl=c,this.#nl=h||js.Origin.Raw}domDebuggerModel(){return this.#Ko}type(){return this.#p}useCapture(){return this.#Qo}passive(){return this.#Xo}once(){return this.#Jo}handler(){return this.#Yo}location(){return this.#na}sourceURL(){return this.#el}originalHandler(){return this.#Zo}canRemove(){return Boolean(this.#tl)||this.#nl!==js.Origin.FrameworkUser}remove(){if(!this.canRemove())return Promise.resolve(void 0);if(this.#nl!==js.Origin.FrameworkUser){function e(e,t,n){this.removeEventListener(e,t,n),this["on"+e]&&(this["on"+e]=void 0)}return this.#$o.callFunction(e,[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo)]).then((()=>{}))}if(this.#tl){function e(e,t,n,r){this.call(null,e,t,n,r)}return this.#tl.callFunction(e,[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo),Le.toCallArgument(this.#Xo)]).then((()=>{}))}return Promise.resolve(void 0)}canTogglePassive(){return this.#nl!==js.Origin.FrameworkUser}togglePassive(){return this.#$o.callFunction((function(e,t,n,r){this.removeEventListener(e,t,{capture:n}),this.addEventListener(e,t,{capture:n,passive:!r})}),[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo),Le.toCallArgument(this.#Xo)]).then((()=>{}))}origin(){return this.#nl}markAsFramework(){this.#nl=js.Origin.Framework}isScrollBlockingType(){return"touchstart"===this.#p||"touchmove"===this.#p||"mousewheel"===this.#p||"wheel"===this.#p}}!function(e){let t;!function(e){e.Raw="Raw",e.Framework="Framework",e.FrameworkUser="FrameworkUser"}(t=e.Origin||(e.Origin={}))}(js||(js={}));class Ws extends Fr{#p;constructor(e,t,n){super(e,t),this.#p=n}type(){return this.#p}}class Vs extends Fr{instrumentationName;eventName;eventTargetNames;constructor(e,t,n,r,s){super(r,s),this.instrumentationName=e,this.eventName=t,this.eventTargetNames=n}setEnabled(e){if(this.enabled()!==e){super.setEnabled(e);for(const e of K.instance().models(Hs))this.updateOnModel(e)}}updateOnModel(e){if(this.instrumentationName)this.enabled()?e.agent.invoke_setInstrumentationBreakpoint({eventName:this.instrumentationName}):e.agent.invoke_removeInstrumentationBreakpoint({eventName:this.instrumentationName});else for(const t of this.eventTargetNames)this.enabled()?e.agent.invoke_setEventListenerBreakpoint({eventName:this.eventName,targetName:t}):e.agent.invoke_removeEventListenerBreakpoint({eventName:this.eventName,targetName:t})}static listener="listener:";static instrumentation="instrumentation:"}let Gs;class Ks{#rl;#sl;#il;#al;constructor(){this.#rl=e.Settings.Settings.instance().createLocalSetting("xhrBreakpoints",[]),this.#sl=new Map;for(const e of this.#rl.get())this.#sl.set(e.url,e.enabled);this.#il=[],this.#il.push(new Ws(Us(Bs.trustedTypeViolations),Us(Bs.sinkViolations),"trustedtype-sink-violation")),this.#il.push(new Ws(Us(Bs.trustedTypeViolations),Us(Bs.policyViolations),"trustedtype-policy-violation")),this.#al=[],this.createInstrumentationBreakpoints(Us(Bs.animation),["requestAnimationFrame","cancelAnimationFrame","requestAnimationFrame.callback"]),this.createInstrumentationBreakpoints(Us(Bs.canvas),["canvasContextCreated","webglErrorFired","webglWarningFired"]),this.createInstrumentationBreakpoints(Us(Bs.geolocation),["Geolocation.getCurrentPosition","Geolocation.watchPosition"]),this.createInstrumentationBreakpoints(Us(Bs.notification),["Notification.requestPermission"]),this.createInstrumentationBreakpoints(Us(Bs.parse),["Element.setInnerHTML","Document.write"]),this.createInstrumentationBreakpoints(Us(Bs.script),["scriptFirstStatement","scriptBlockedByCSP"]),this.createInstrumentationBreakpoints(Us(Bs.timer),["setTimeout","clearTimeout","setInterval","clearInterval","setTimeout.callback","setInterval.callback"]),this.createInstrumentationBreakpoints(Us(Bs.window),["DOMWindow.close"]),this.createInstrumentationBreakpoints(Us(Bs.webaudio),["audioContextCreated","audioContextClosed","audioContextResumed","audioContextSuspended"]),this.createEventListenerBreakpoints(Us(Bs.media),["play","pause","playing","canplay","canplaythrough","seeking","seeked","timeupdate","ended","ratechange","durationchange","volumechange","loadstart","progress","suspend","abort","error","emptied","stalled","loadedmetadata","loadeddata","waiting"],["audio","video"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["enterpictureinpicture","leavepictureinpicture"],["video"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["resize"],["PictureInPictureWindow"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["enter"],["documentPictureInPicture"]),this.createEventListenerBreakpoints(Us(Bs.clipboard),["copy","cut","paste","beforecopy","beforecut","beforepaste"],["*"]),this.createEventListenerBreakpoints(Us(Bs.control),["resize","scroll","scrollend","zoom","focus","blur","select","change","submit","reset"],["*"]),this.createEventListenerBreakpoints(Us(Bs.device),["deviceorientation","devicemotion"],["*"]),this.createEventListenerBreakpoints(Us(Bs.domMutation),["DOMActivate","DOMFocusIn","DOMFocusOut","DOMAttrModified","DOMCharacterDataModified","DOMNodeInserted","DOMNodeInsertedIntoDocument","DOMNodeRemoved","DOMNodeRemovedFromDocument","DOMSubtreeModified","DOMContentLoaded"],["*"]),this.createEventListenerBreakpoints(Us(Bs.dragDrop),["drag","dragstart","dragend","dragenter","dragover","dragleave","drop"],["*"]),this.createEventListenerBreakpoints(Us(Bs.keyboard),["keydown","keyup","keypress","input"],["*"]),this.createEventListenerBreakpoints(Us(Bs.load),["load","beforeunload","unload","abort","error","hashchange","popstate","navigate","navigatesuccess","navigateerror","currentchange","navigateto","navigatefrom","finish","dispose"],["*"]),this.createEventListenerBreakpoints(Us(Bs.mouse),["auxclick","click","dblclick","mousedown","mouseup","mouseover","mousemove","mouseout","mouseenter","mouseleave","mousewheel","wheel","contextmenu"],["*"]),this.createEventListenerBreakpoints(Us(Bs.pointer),["pointerover","pointerout","pointerenter","pointerleave","pointerdown","pointerup","pointermove","pointercancel","gotpointercapture","lostpointercapture","pointerrawupdate"],["*"]),this.createEventListenerBreakpoints(Us(Bs.touch),["touchstart","touchmove","touchend","touchcancel"],["*"]),this.createEventListenerBreakpoints(Us(Bs.worker),["message","messageerror"],["*"]),this.createEventListenerBreakpoints(Us(Bs.xhr),["readystatechange","load","loadstart","loadend","abort","error","progress","timeout"],["xmlhttprequest","xmlhttprequestupload"]);for(const[e,t]of[["setTimeout.callback",Us(Bs.setTimeoutOrIntervalFired,{PH1:"setTimeout"})],["setInterval.callback",Us(Bs.setTimeoutOrIntervalFired,{PH1:"setInterval"})],["scriptFirstStatement",Us(Bs.scriptFirstStatement)],["scriptBlockedByCSP",Us(Bs.scriptBlockedByContentSecurity)],["requestAnimationFrame",Us(Bs.requestAnimationFrame)],["cancelAnimationFrame",Us(Bs.cancelAnimationFrame)],["requestAnimationFrame.callback",Us(Bs.animationFrameFired)],["webglErrorFired",Us(Bs.webglErrorFired)],["webglWarningFired",Us(Bs.webglWarningFired)],["Element.setInnerHTML",Us(Bs.setInnerhtml)],["canvasContextCreated",Us(Bs.createCanvasContext)],["Geolocation.getCurrentPosition","getCurrentPosition"],["Geolocation.watchPosition","watchPosition"],["Notification.requestPermission","requestPermission"],["DOMWindow.close","window.close"],["Document.write","document.write"],["audioContextCreated",Us(Bs.createAudiocontext)],["audioContextClosed",Us(Bs.closeAudiocontext)],["audioContextResumed",Us(Bs.resumeAudiocontext)],["audioContextSuspended",Us(Bs.suspendAudiocontext)]]){const n=this.resolveEventListenerBreakpointInternal("instrumentation:"+e);n&&n.setTitle(t)}K.instance().observeModels(Hs,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return Gs&&!t||(Gs=new Ks),Gs}cspViolationBreakpoints(){return this.#il.slice()}createInstrumentationBreakpoints(e,t){for(const n of t)this.#al.push(new Vs(n,"",[],e,n))}createEventListenerBreakpoints(e,t,n){for(const r of t)this.#al.push(new Vs("",r,n,e,r))}resolveEventListenerBreakpointInternal(e,t){const n="instrumentation:",r="listener:";let s="";if(e.startsWith(n))s=e.substring(n.length),e="";else{if(!e.startsWith(r))return null;e=e.substring(r.length)}t=(t||"*").toLowerCase();let i=null;for(const n of this.#al)s&&n.instrumentationName===s&&(i=n),e&&n.eventName===e&&-1!==n.eventTargetNames.indexOf(t)&&(i=n),!i&&e&&n.eventName===e&&-1!==n.eventTargetNames.indexOf("*")&&(i=n);return i}eventListenerBreakpoints(){return this.#al.slice()}resolveEventListenerBreakpointTitle(e){const t=e.eventName;if("instrumentation:webglErrorFired"===t&&e.webglErrorName){let t=e.webglErrorName;return t=t.replace(/^.*(0x[0-9a-f]+).*$/i,"$1"),Us(Bs.webglErrorFiredS,{PH1:t})}if("instrumentation:scriptBlockedByCSP"===t&&e.directiveText)return Us(Bs.scriptBlockedDueToContent,{PH1:e.directiveText});const n=this.resolveEventListenerBreakpointInternal(t,e.targetName);return n?e.targetName?e.targetName+"."+n.title():n.title():""}resolveEventListenerBreakpoint(e){return this.resolveEventListenerBreakpointInternal(e.eventName,e.targetName)}updateCSPViolationBreakpoints(){const e=this.#il.filter((e=>e.enabled())).map((e=>e.type()));for(const t of K.instance().models(Hs))this.updateCSPViolationBreakpointsForModel(t,e)}updateCSPViolationBreakpointsForModel(e,t){e.agent.invoke_setBreakOnCSPViolation({violationTypes:t})}xhrBreakpoints(){return this.#sl}saveXHRBreakpoints(){const e=[];for(const t of this.#sl.keys())e.push({url:t,enabled:this.#sl.get(t)||!1});this.#rl.set(e)}addXHRBreakpoint(e,t){if(this.#sl.set(e,t),t)for(const t of K.instance().models(Hs))t.agent.invoke_setXHRBreakpoint({url:e});this.saveXHRBreakpoints()}removeXHRBreakpoint(e){const t=this.#sl.get(e);if(this.#sl.delete(e),t)for(const t of K.instance().models(Hs))t.agent.invoke_removeXHRBreakpoint({url:e});this.saveXHRBreakpoints()}toggleXHRBreakpoint(e,t){this.#sl.set(e,t);for(const n of K.instance().models(Hs))t?n.agent.invoke_setXHRBreakpoint({url:e}):n.agent.invoke_removeXHRBreakpoint({url:e});this.saveXHRBreakpoints()}modelAdded(e){for(const t of this.#sl.keys())this.#sl.get(t)&&e.agent.invoke_setXHRBreakpoint({url:t});for(const t of this.#al)t.enabled()&&t.updateOnModel(e);const t=this.#il.filter((e=>e.enabled())).map((e=>e.type()));this.updateCSPViolationBreakpointsForModel(e,t)}modelRemoved(e){}}c.register(Hs,{capabilities:z.DOM,autostart:!1});var $s=Object.freeze({__proto__:null,DOMDebuggerModel:Hs,get Events(){return qs},DOMBreakpoint:zs,get EventListener(){return js},CSPViolationBreakpoint:Ws,DOMEventListenerBreakpoint:Vs,DOMDebuggerManager:Ks});const Qs={auctionWorklet:"Ad Auction Worklet",beforeBidderWorkletBiddingStart:"Bidder Bidding Phase Start",beforeBidderWorkletReportingStart:"Bidder Reporting Phase Start",beforeSellerWorkletScoringStart:"Seller Scoring Phase Start",beforeSellerWorkletReportingStart:"Seller Reporting Phase Start"},Xs=s.i18n.registerUIStrings("core/sdk/EventBreakpointsModel.ts",Qs),Js=s.i18n.getLocalizedString.bind(void 0,Xs);class Ys extends c{agent;constructor(e){super(e),this.agent=e.eventBreakpointsAgent()}}class Zs extends Fr{instrumentationName;constructor(e,t){super(t,function(e){switch(e){case"beforeBidderWorkletBiddingStart":return Js(Qs.beforeBidderWorkletBiddingStart);case"beforeBidderWorkletReportingStart":return Js(Qs.beforeBidderWorkletReportingStart);case"beforeSellerWorkletScoringStart":return Js(Qs.beforeSellerWorkletScoringStart);case"beforeSellerWorkletReportingStart":return Js(Qs.beforeSellerWorkletReportingStart)}}(e)),this.instrumentationName=e}setEnabled(e){if(this.enabled()!==e){super.setEnabled(e);for(const e of K.instance().models(Ys))this.updateOnModel(e)}}updateOnModel(e){this.enabled()?e.agent.invoke_setInstrumentationBreakpoint({eventName:this.instrumentationName}):e.agent.invoke_removeInstrumentationBreakpoint({eventName:this.instrumentationName})}static instrumentationPrefix="instrumentation:"}let ei;class ti{#al=[];constructor(){this.createInstrumentationBreakpoints(Js(Qs.auctionWorklet),["beforeBidderWorkletBiddingStart","beforeBidderWorkletReportingStart","beforeSellerWorkletScoringStart","beforeSellerWorkletReportingStart"]),K.instance().observeModels(Ys,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return ei&&!t||(ei=new ti),ei}createInstrumentationBreakpoints(e,t){for(const n of t)this.#al.push(new Zs(n,e))}eventListenerBreakpoints(){return this.#al.slice()}resolveEventListenerBreakpointTitle(e){const t=this.resolveEventListenerBreakpoint(e);return t?t.title():null}resolveEventListenerBreakpoint(e){const t=e.eventName;if(!t.startsWith(Zs.instrumentationPrefix))return null;const n=t.substring(Zs.instrumentationPrefix.length);return this.#al.find((e=>e.instrumentationName===n))||null}modelAdded(e){for(const t of this.#al)t.enabled()&&t.updateOnModel(e)}modelRemoved(e){}}c.register(Ys,{capabilities:z.EventBreakpoints,autostart:!1});var ni=Object.freeze({__proto__:null,EventBreakpointsModel:Ys,EventBreakpointsManager:ti});class ri{#ol;#ll;#dl;#cl;#hl;#ul;#gl;#pl;#ml;#fl;#bl;#yl;#vl=[];constructor(e){this.#ol=e,this.#ll=new Map,this.#dl=new Map,this.#cl=Number(1/0),this.#hl=Number(-1/0),this.#ul=[],this.#gl=[],this.#pl=new Map,this.#ml=new Map,this.#fl=new Map,this.#bl=new Map,this.#yl=new Map}static isTopLevelEvent(e){return vi(e,li)&&"RunTask"===e.name||vi(e,ai)||vi(e,oi)&&"Program"===e.name}static extractId(e){const t=e.scope||"";if(void 0===e.id2)return t&&e.id?`${t}@${e.id}`:e.id;const n=e.id2;if("object"==typeof n&&"global"in n!="local"in n)return void 0!==n.global?`:${t}:${n.global}`:`:${t}:${e.pid}:${n.local}`;console.error(`Unexpected id2 field at ${e.ts/1e3}, one and only one of 'local' and 'global' should be present.`)}static browserMainThread(t){const n=t.sortedProcesses();if(!n.length)return null;const r="CrBrowserMain",s=[],i=[];for(const e of n)e.name().toLowerCase().endsWith("browser")&&s.push(e),i.push(...e.sortedThreads().filter((e=>e.name()===r)));if(1===i.length)return i[0];if(1===s.length)return s[0].threadByName(r);const a=t.devToolsMetadataEvents().filter((e=>"TracingStartedInBrowser"===e.name));return 1===a.length?a[0].thread:(e.Console.Console.instance().error("Failed to find browser main thread in trace, some timeline features may be unavailable"),null)}allRawEvents(){return this.#vl}devToolsMetadataEvents(){return this.#ul}addEvents(e){for(let t=0;te.#kl!==t.#kl?e.#kl-t.#kl:e.name().localeCompare(t.name())))}setName(e){this.#u=e}name(){return this.#u}id(){return this.idInternal}setSortIndex(e){this.#kl=e}getModel(){return this.model}}class fi extends mi{threads;#Sl;constructor(e,t){super(e,t),this.threads=new Map,this.#Sl=new Map}threadById(e){let t=this.threads.get(e);return t||(t=new bi(this,e),this.threads.set(e,t)),t}threadByName(e){return this.#Sl.get(e)||null}setThreadByName(e,t){this.#Sl.set(e,t)}addEvent(e){return this.threadById(e.tid).addEvent(e)}sortedThreads(){return mi.sort([...this.threads.values()])}}class bi extends mi{#wl;#Cl;#Tl;#Rl;constructor(e,t){super(e.getModel(),t),this.#wl=e,this.#Cl=[],this.#Tl=[],this.#Rl=null}#xl(e,t){return e.phase===t}tracingComplete(){this.#Tl.sort(di.compareStartTime),this.#Cl.sort(di.compareStartTime);const e=[],t=new Set;for(let n=0;n!t.has(n)))}addEvent(e){const t="O"===e.ph?ui.fromPayload(e,this):hi.fromPayload(e,this);if(ri.isTopLevelEvent(t)){const e=this.#Rl;if(e&&(e.endTime||0)>t.startTime)return null;this.#Rl=t}return this.#Cl.push(t),t}addAsyncEvent(e){this.#Tl.push(e)}setName(e){super.setName(e),this.#wl.setThreadByName(e,this)}process(){return this.#wl}events(){return this.#Cl}asyncEvents(){return this.#Tl}removeEventsByName(e){const t=[];return this.#Cl=this.#Cl.filter((n=>!!n&&(n.name!==e||(t.push(n),!1)))),t}}const yi=new Map;function vi(e,t){if(e instanceof di)return e.hasCategory(t);let n=yi.get(e.cat);return n||(n=new Set(e.cat.split(",")||[])),n.has(t)}var Ii=Object.freeze({__proto__:null,TracingModel:ri,eventPhasesOfInterestForTraceBounds:si,MetadataEvent:ii,LegacyTopLevelEventCategory:ai,DevToolsMetadataEventCategory:oi,DevToolsTimelineEventCategory:li,eventHasPayload:function(e){return"rawPayload"in e},Event:di,ConstructedEvent:ci,PayloadEvent:hi,ObjectSnapshot:ui,AsyncEvent:gi,Process:fi,Thread:bi,timesForEventInMilliseconds:function(e){if(e instanceof di)return{startTime:l.Types.Timing.MilliSeconds(e.startTime),endTime:e.endTime?l.Types.Timing.MilliSeconds(e.endTime):void 0,duration:l.Types.Timing.MilliSeconds(e.duration||0),selfTime:l.Types.Timing.MilliSeconds(e.selfTime)};const t=e.dur?l.Helpers.Timing.microSecondsToMilliseconds(e.dur):l.Types.Timing.MilliSeconds(0);return{startTime:l.Helpers.Timing.microSecondsToMilliseconds(e.ts),endTime:l.Helpers.Timing.microSecondsToMilliseconds(l.Types.Timing.MicroSeconds(e.ts+(e.dur||0))),duration:e.dur?l.Helpers.Timing.microSecondsToMilliseconds(e.dur):l.Types.Timing.MilliSeconds(0),selfTime:t}},eventHasCategory:vi,phaseForEvent:function(e){return e instanceof di?e.phase:e.ph},threadIDForEvent:function(e){return e instanceof di?e.thread.idInternal:e.tid},eventIsFromNewEngine:function(e){return null!==e&&!(e instanceof di)}});const ki="disabled-by-default-devtools.screenshot",Si={Screenshot:"Screenshot"};class wi{#Ml;timestamp;index;#Pl;#Ll;constructor(e,t,n){this.#Ml=e,this.timestamp=t,this.index=n,this.#Ll=null,this.#Pl=null}static fromSnapshot(e,t,n){const r=new wi(e,t.startTime,n);return r.#Pl=t,r}static fromTraceEvent(e,t,n){const r=l.Helpers.Timing.microSecondsToMilliseconds(t.ts),s=new wi(e,r,n);return s.#Ll=t,s}model(){return this.#Ml}imageDataPromise(){return this.#Ll?Promise.resolve(this.#Ll.args.snapshot):this.#Pl?Promise.resolve(this.#Pl.getSnapshot()):Promise.resolve(null)}}var Ci=Object.freeze({__proto__:null,FilmStripModel:class{#Ve;#El;#Al;constructor(e,t){this.#Ve=[],this.#El=0,this.#Al=0,this.reset(e,t)}hasFrames(){return this.#Ve.length>0}reset(e,t){this.#El=t||e.minimumRecordTime(),this.#Al=e.maximumRecordTime()-this.#El,this.#Ve=[];const n=ri.browserMainThread(e);if(!n)return;const r=n.events();for(let e=0;et.timestampe.update()))),await new Promise((e=>window.setTimeout(e,Pi)))}}var Mi;(Mi||(Mi={})).MemoryChanged="MemoryChanged";const Pi=2e3;class Li{#E;modelsInternal;#Bl;#Dl;constructor(e){this.#E=e,this.modelsInternal=new Set,this.#Bl=0;const t=12e4/Pi;this.#Dl=new Ei(t)}id(){return this.#E}models(){return this.modelsInternal}runtimeModel(){return this.modelsInternal.values().next().value||null}heapProfilerModel(){const e=this.runtimeModel();return e&&e.heapProfilerModel()}async update(){const e=this.runtimeModel(),t=e&&await e.heapUsage();t&&(this.#Bl=t.usedSize,this.#Dl.add(this.#Bl),xi.instance().dispatchEventToListeners(Mi.MemoryChanged,this))}samplesCount(){return this.#Dl.count()}usedHeapSize(){return this.#Bl}usedHeapSizeGrowRate(){return this.#Dl.fitSlope()}isMainThread(){const e=this.runtimeModel();return!!e&&"main"===e.target().id()}}class Ei{#Ul;#Hl;#Kr;#ql;#_l;#zl;#jl;#Wl;#Vl;constructor(e){this.#Ul=0|e,this.reset()}reset(){this.#Hl=Date.now(),this.#Kr=0,this.#ql=[],this.#_l=[],this.#zl=0,this.#jl=0,this.#Wl=0,this.#Vl=0}count(){return this.#ql.length}add(e,t){const n="number"==typeof t?t:Date.now()-this.#Hl,r=e;if(this.#ql.length===this.#Ul){const e=this.#ql[this.#Kr],t=this.#_l[this.#Kr];this.#zl-=e,this.#jl-=t,this.#Wl-=e*e,this.#Vl-=e*t}this.#zl+=n,this.#jl+=r,this.#Wl+=n*n,this.#Vl+=n*r,this.#ql[this.#Kr]=n,this.#_l[this.#Kr]=r,this.#Kr=(this.#Kr+1)%this.#Ul}fitSlope(){const e=this.count();return e<2?0:(this.#Vl-this.#zl*this.#jl/e)/(this.#Wl-this.#zl*this.#zl/e)}}var Ai=Object.freeze({__proto__:null,IsolateManager:xi,get Events(){return Mi},MemoryTrendWindowMs:12e4,Isolate:Li,MemoryTrend:Ei});class Oi extends c{#Gl=!1;#ma=!1;constructor(e){super(e),this.ensureEnabled()}async ensureEnabled(){if(this.#ma)return;this.#ma=!0,this.target().registerAuditsDispatcher(this);const e=this.target().auditsAgent();await e.invoke_enable()}issueAdded(e){this.dispatchEventToListeners("IssueAdded",{issuesModel:this,inspectorIssue:e.issue})}dispose(){super.dispose(),this.#Gl=!0}getTargetIfNotDisposed(){return this.#Gl?null:this.target()}}c.register(Oi,{capabilities:z.Audits,autostart:!0});var Ni,Fi=Object.freeze({__proto__:null,IssuesModel:Oi});!function(e){let t;!function(e){e.NonFastScrollable="NonFastScrollable",e.TouchEventHandler="TouchEventHandler",e.WheelEventHandler="WheelEventHandler",e.RepaintsOnScroll="RepaintsOnScroll",e.MainThreadScrollingReason="MainThreadScrollingReason"}(t=e.ScrollRectType||(e.ScrollRectType={}))}(Ni||(Ni={}));var Bi=Object.freeze({__proto__:null,get Layer(){return Ni},StickyPositionConstraint:class{#Kl;#$l;#Ql;#Xl;constructor(e,t){this.#Kl=t.stickyBoxRect,this.#$l=t.containingBlockRect,this.#Ql=null,e&&t.nearestLayerShiftingStickyBox&&(this.#Ql=e.layerById(t.nearestLayerShiftingStickyBox)),this.#Xl=null,e&&t.nearestLayerShiftingContainingBlock&&(this.#Xl=e.layerById(t.nearestLayerShiftingContainingBlock))}stickyBoxRect(){return this.#Kl}containingBlockRect(){return this.#$l}nearestLayerShiftingStickyBox(){return this.#Ql}nearestLayerShiftingContainingBlock(){return this.#Xl}},LayerTreeBase:class{#e;#Mr;layersById;#Jl;#Yl;#Zl;#ed;constructor(e){this.#e=e,this.#Mr=e?e.model(Pn):null,this.layersById=new Map,this.#Jl=null,this.#Yl=null,this.#Zl=new Map}target(){return this.#e}root(){return this.#Jl}setRoot(e){this.#Jl=e}contentRoot(){return this.#Yl}setContentRoot(e){this.#Yl=e}forEachLayer(e,t){return!(!t&&!(t=this.root()))&&(e(t)||t.children().some(this.forEachLayer.bind(this,e)))}layerById(e){return this.layersById.get(e)||null}async resolveBackendNodeIds(e){if(!e.size||!this.#Mr)return;const t=await this.#Mr.pushNodesByBackendIdsToFrontend(e);if(t)for(const e of t.keys())this.#Zl.set(e,t.get(e)||null)}backendNodeIdToNode(){return this.#Zl}setViewportSize(e){this.#ed=e}viewportSize(){return this.#ed}nodeForId(e){return this.#Mr?this.#Mr.nodeForId(e):null}}});class Di{id;url;startTime;loadTime;contentLoadTime;mainRequest;constructor(e){this.id=++Di.lastIdentifier,this.url=e.url(),this.startTime=e.startTime,this.mainRequest=e}static forRequest(e){return Ui.get(e)||null}bindRequest(e){Ui.set(e,this)}static lastIdentifier=0}const Ui=new WeakMap;var Hi=Object.freeze({__proto__:null,PageLoad:Di});class qi extends c{layerTreeAgent;constructor(e){super(e),this.layerTreeAgent=e.layerTreeAgent()}async loadSnapshotFromFragments(e){const{snapshotId:t}=await this.layerTreeAgent.invoke_loadSnapshot({tiles:e});return t?new _i(this,t):null}loadSnapshot(e){const t={x:0,y:0,picture:e};return this.loadSnapshotFromFragments([t])}async makeSnapshot(e){const{snapshotId:t}=await this.layerTreeAgent.invoke_makeSnapshot({layerId:e});return t?new _i(this,t):null}}class _i{#td;#nd;#rd;constructor(e,t){this.#td=e,this.#nd=t,this.#rd=1}release(){console.assert(this.#rd>0,"release is already called on the object"),--this.#rd||this.#td.layerTreeAgent.invoke_releaseSnapshot({snapshotId:this.#nd})}addReference(){++this.#rd,console.assert(this.#rd>0,"Referencing a dead object")}async replay(e,t,n){return(await this.#td.layerTreeAgent.invoke_replaySnapshot({snapshotId:this.#nd,fromStep:t,toStep:n,scale:e||1})).dataURL}async profile(e){return(await this.#td.layerTreeAgent.invoke_profileSnapshot({snapshotId:this.#nd,minRepeatCount:5,minDuration:1,clipRect:e||void 0})).timings}async commandLog(){const e=await this.#td.layerTreeAgent.invoke_snapshotCommandLog({snapshotId:this.#nd});return e.commandLog?e.commandLog.map(((e,t)=>new zi(e,t))):null}}class zi{method;params;commandIndex;constructor(e,t){this.method=e.method,this.params=e.params,this.commandIndex=t}}c.register(qi,{capabilities:z.DOM,autostart:!1});var ji=Object.freeze({__proto__:null,PaintProfilerModel:qi,PaintProfilerSnapshot:_i,PaintProfilerLogItem:zi});class Wi extends c{#Ts;#sd;#id;constructor(e){super(e),this.#Ts=e.performanceAgent(),this.#sd=new Map([["TaskDuration","CumulativeTime"],["ScriptDuration","CumulativeTime"],["LayoutDuration","CumulativeTime"],["RecalcStyleDuration","CumulativeTime"],["LayoutCount","CumulativeCount"],["RecalcStyleCount","CumulativeCount"]]),this.#id=new Map}enable(){return this.#Ts.invoke_enable({})}disable(){return this.#Ts.invoke_disable()}async requestMetrics(){const e=await this.#Ts.invoke_getMetrics()||[],n=new Map,r=performance.now();for(const s of e.metrics){let e,i=this.#id.get(s.name);switch(i||(i={lastValue:void 0,lastTimestamp:void 0},this.#id.set(s.name,i)),this.#sd.get(s.name)){case"CumulativeTime":e=i.lastTimestamp&&i.lastValue?t.NumberUtilities.clamp(1e3*(s.value-i.lastValue)/(r-i.lastTimestamp),0,1):0,i.lastValue=s.value,i.lastTimestamp=r;break;case"CumulativeCount":e=i.lastTimestamp&&i.lastValue?Math.max(0,1e3*(s.value-i.lastValue)/(r-i.lastTimestamp)):0,i.lastValue=s.value,i.lastTimestamp=r;break;default:e=s.value}n.set(s.name,e)}return{metrics:n,timestamp:r}}}c.register(Wi,{capabilities:z.DOM,autostart:!1});var Vi,Gi=Object.freeze({__proto__:null,PerformanceMetricsModel:Wi});class Ki extends c{agent;loaderIds=[];targetJustAttached=!0;lastPrimaryPageModel=null;documents=new Map;getFeatureFlagsPromise;constructor(e){super(e),e.registerPreloadDispatcher(new $i(this)),this.agent=e.preloadAgent(),this.agent.invoke_enable(),this.getFeatureFlagsPromise=this.getFeatureFlags();const t=e.targetInfo();void 0!==t&&"prerender"===t.subtype&&(this.lastPrimaryPageModel=K.instance().primaryPageTarget()?.model(Ki)||null),K.instance().addModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this)}dispose(){super.dispose(),K.instance().removeModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),this.agent.invoke_disable()}ensureDocumentPreloadingData(e){void 0===this.documents.get(e)&&this.documents.set(e,new Qi)}currentLoaderId(){if(this.targetJustAttached)return null;if(0===this.loaderIds.length)throw new Error("unreachable");return this.loaderIds[this.loaderIds.length-1]}currentDocument(){const e=this.currentLoaderId();return null===e?null:this.documents.get(e)||null}getRuleSetById(e){return this.currentDocument()?.ruleSets.getById(e)||null}getAllRuleSets(){return this.currentDocument()?.ruleSets.getAll()||[]}getPreloadingAttemptById(e){const t=this.currentDocument();return null===t?null:t.preloadingAttempts.getById(e,t.sources)||null}getPreloadingAttempts(e){const t=this.currentDocument();return null===t?[]:t.preloadingAttempts.getAll(e,t.sources)}getPreloadingAttemptsOfPreviousPage(){if(this.loaderIds.length<=1)return[];const e=this.documents.get(this.loaderIds[this.loaderIds.length-2]);return void 0===e?[]:e.preloadingAttempts.getAll(null,e.sources)}onPrimaryPageChanged(e){const{frame:t,type:n}=e.data;if(null===this.lastPrimaryPageModel&&"Activation"===n)return;if(null!==this.lastPrimaryPageModel&&"Activation"!==n)return;if(null!==this.lastPrimaryPageModel&&"Activation"===n){this.loaderIds=this.lastPrimaryPageModel.loaderIds;for(const[e,t]of this.lastPrimaryPageModel.documents.entries())this.ensureDocumentPreloadingData(e),this.documents.get(e)?.mergePrevious(t)}this.lastPrimaryPageModel=null;const r=t.loaderId;this.loaderIds.push(r),this.loaderIds=this.loaderIds.slice(-2),this.ensureDocumentPreloadingData(r);for(const e of this.documents.keys())this.loaderIds.includes(e)||this.documents.delete(e);this.dispatchEventToListeners(Vi.ModelUpdated)}onRuleSetUpdated(e){const t=e.ruleSet,n=t.loaderId;null===this.currentLoaderId()&&(this.loaderIds=[n],this.targetJustAttached=!1),this.ensureDocumentPreloadingData(n),this.documents.get(n)?.ruleSets.upsert(t),this.dispatchEventToListeners(Vi.ModelUpdated)}onRuleSetRemoved(e){const t=e.id;for(const e of this.documents.values())e.ruleSets.delete(t);this.dispatchEventToListeners(Vi.ModelUpdated)}onPreloadingAttemptSourcesUpdated(e){const t=e.loaderId;this.ensureDocumentPreloadingData(t);const n=this.documents.get(t);void 0!==n&&(n.sources.update(e.preloadingAttemptSources),n.preloadingAttempts.maybeRegisterNotTriggered(n.sources),this.dispatchEventToListeners(Vi.ModelUpdated))}onPrefetchStatusUpdated(e){const t=e.key.loaderId;this.ensureDocumentPreloadingData(t);const n={action:"Prefetch",key:e.key,status:Ji(e.status),prefetchStatus:e.prefetchStatus||null};this.documents.get(t)?.preloadingAttempts.upsert(n),this.dispatchEventToListeners(Vi.ModelUpdated)}onPrerenderStatusUpdated(e){const t=e.key.loaderId;this.ensureDocumentPreloadingData(t);const n={action:"Prerender",key:e.key,status:Ji(e.status),prerenderStatus:e.prerenderStatus||null};this.documents.get(t)?.preloadingAttempts.upsert(n),this.dispatchEventToListeners(Vi.ModelUpdated)}async getFeatureFlags(){const e=this.target().systemInfo().invoke_getFeatureState({featureState:"PreloadingHoldback"}),t=this.target().systemInfo().invoke_getFeatureState({featureState:"PrerenderHoldback"});return{preloadingHoldback:(await e).featureEnabled,prerender2Holdback:(await t).featureEnabled}}async onPreloadEnabledStateUpdated(e){const t=await this.getFeatureFlagsPromise,n={featureFlagPreloadingHoldback:t.preloadingHoldback,featureFlagPrerender2Holdback:t.prerender2Holdback,...e};this.dispatchEventToListeners(Vi.WarningsUpdated,n)}}c.register(Ki,{capabilities:z.DOM,autostart:!1}),function(e){e.ModelUpdated="ModelUpdated",e.WarningsUpdated="WarningsUpdated"}(Vi||(Vi={}));class $i{model;constructor(e){this.model=e}ruleSetUpdated(e){this.model.onRuleSetUpdated(e)}ruleSetRemoved(e){this.model.onRuleSetRemoved(e)}preloadingAttemptSourcesUpdated(e){this.model.onPreloadingAttemptSourcesUpdated(e)}prefetchStatusUpdated(e){this.model.onPrefetchStatusUpdated(e)}prerenderAttemptCompleted(e){}prerenderStatusUpdated(e){this.model.onPrerenderStatusUpdated(e)}preloadEnabledStateUpdated(e){this.model.onPreloadEnabledStateUpdated(e)}}class Qi{ruleSets=new Xi;preloadingAttempts=new Zi;sources=new ea;mergePrevious(e){if(!this.ruleSets.isEmpty()||!this.sources.isEmpty())throw new Error("unreachable");this.ruleSets=e.ruleSets,this.preloadingAttempts.mergePrevious(e.preloadingAttempts),this.sources=e.sources}}class Xi{map=new Map;isEmpty(){return 0===this.map.size}getById(e){return this.map.get(e)||null}getAll(){return Array.from(this.map.entries()).map((([e,t])=>({id:e,value:t})))}upsert(e){this.map.set(e.id,e)}delete(e){this.map.delete(e)}}function Ji(e){switch(e){case"Pending":return"Pending";case"Running":return"Running";case"Ready":return"Ready";case"Success":return"Success";case"Failure":return"Failure";case"NotSupported":return"NotSupported"}throw new Error("unreachable")}function Yi(e){let t,n;switch(e.action){case"Prefetch":t="Prefetch";break;case"Prerender":t="Prerender"}switch(e.targetHint){case void 0:n="undefined";break;case"Blank":n="Blank";break;case"Self":n="Self"}return`${e.loaderId}:${t}:${e.url}:${n}`}class Zi{map=new Map;enrich(e,t){let n=[],r=[];return null!==t&&(n=t.ruleSetIds,r=t.nodeIds),{...e,ruleSetIds:n,nodeIds:r}}getById(e,t){const n=this.map.get(e)||null;return null===n?null:this.enrich(n,t.getById(e))}getAll(e,t){return[...this.map.entries()].map((([e,n])=>({id:e,value:this.enrich(n,t.getById(e))}))).filter((({value:t})=>!e||t.ruleSetIds.includes(e)))}upsert(e){const t=Yi(e.key);this.map.set(t,e)}maybeRegisterNotTriggered(e){for(const[t,{key:n}]of e.entries()){if(void 0!==this.map.get(t))continue;let e;switch(n.action){case"Prefetch":e={action:"Prefetch",key:n,status:"NotTriggered",prefetchStatus:null};break;case"Prerender":e={action:"Prerender",key:n,status:"NotTriggered",prerenderStatus:null}}this.map.set(t,e)}}mergePrevious(e){for(const[t,n]of this.map.entries())e.map.set(t,n);this.map=e.map}}class ea{map=new Map;entries(){return this.map.entries()}isEmpty(){return 0===this.map.size}getById(e){return this.map.get(e)||null}update(e){this.map=new Map(e.map((e=>[Yi(e.key),e])))}}var ta=Object.freeze({__proto__:null,PreloadingModel:Ki,get Events(){return Vi}});class na extends c{#Ts;#ad;#od;constructor(e){super(e),this.#Ts=e.pageAgent(),this.#ad=null,this.#od=null,e.registerPageDispatcher(this)}startScreencast(e,t,n,r,s,i,a){this.#ad=i,this.#od=a,this.#Ts.invoke_startScreencast({format:e,quality:t,maxWidth:n,maxHeight:r,everyNthFrame:s})}stopScreencast(){this.#ad=null,this.#od=null,this.#Ts.invoke_stopScreencast()}async captureScreenshot(e,t,n,r){const s={format:e,quality:t,fromSurface:!0};switch(n){case"fromClip":s.captureBeyondViewport=!0,s.clip=r;break;case"fullpage":s.captureBeyondViewport=!0;break;case"fromViewport":s.captureBeyondViewport=!1;break;default:throw new Error("Unexpected or unspecified screnshotMode")}await vn.muteHighlight();const i=await this.#Ts.invoke_captureScreenshot(s);return await vn.unmuteHighlight(),i.data}async fetchLayoutMetrics(){const e=await this.#Ts.invoke_getLayoutMetrics();return e.getError()?null:{viewportX:e.cssVisualViewport.pageX,viewportY:e.cssVisualViewport.pageY,viewportScale:e.cssVisualViewport.scale,contentWidth:e.cssContentSize.width,contentHeight:e.cssContentSize.height}}screencastFrame({data:e,metadata:t,sessionId:n}){this.#Ts.invoke_screencastFrameAck({sessionId:n}),this.#ad&&this.#ad.call(null,e,t)}screencastVisibilityChanged({visible:e}){this.#od&&this.#od.call(null,e)}backForwardCacheNotUsed(e){}domContentEventFired(e){}loadEventFired(e){}lifecycleEvent(e){}navigatedWithinDocument(e){}frameAttached(e){}frameNavigated(e){}documentOpened(e){}frameDetached(e){}frameStartedLoading(e){}frameStoppedLoading(e){}frameRequestedNavigation(e){}frameScheduledNavigation(e){}frameClearedScheduledNavigation(e){}frameResized(){}javascriptDialogOpening(e){}javascriptDialogClosed(e){}interstitialShown(){}interstitialHidden(){}windowOpen(e){}fileChooserOpened(e){}compilationCacheProduced(e){}downloadWillBegin(e){}downloadProgress(){}prerenderAttemptCompleted(e){}prefetchStatusUpdated(e){}prerenderStatusUpdated(e){}}c.register(na,{capabilities:z.ScreenCapture,autostart:!1});var ra=Object.freeze({__proto__:null,ScreenCaptureModel:na});class sa extends c{enabled=!1;storageAgent;storageKeyManager;bucketsById=new Map;trackedStorageKeys=new Set;constructor(e){super(e),e.registerStorageDispatcher(this),this.storageAgent=e.storageAgent(),this.storageKeyManager=e.model(qn)}getBuckets(){return new Set(this.bucketsById.values())}getBucketsForStorageKey(e){const t=[...this.bucketsById.values()];return new Set(t.filter((({bucket:t})=>t.storageKey===e)))}getDefaultBucketForStorageKey(e){return[...this.bucketsById.values()].find((({bucket:t})=>t.storageKey===e&&void 0===t.name))??null}getBucketById(e){return this.bucketsById.get(e)??null}getBucketByName(e,t){if(!t)return this.getDefaultBucketForStorageKey(e);return[...this.bucketsById.values()].find((({bucket:n})=>n.storageKey===e&&n.name===t))??null}deleteBucket(e){this.storageAgent.invoke_deleteStorageBucket({bucket:e})}enable(){if(!this.enabled){if(this.storageKeyManager){this.storageKeyManager.addEventListener(Un.StorageKeyAdded,this.storageKeyAdded,this),this.storageKeyManager.addEventListener(Un.StorageKeyRemoved,this.storageKeyRemoved,this);for(const e of this.storageKeyManager.storageKeys())this.addStorageKey(e)}this.enabled=!0}}storageKeyAdded(e){this.addStorageKey(e.data)}storageKeyRemoved(e){this.removeStorageKey(e.data)}addStorageKey(e){if(this.trackedStorageKeys.has(e))throw new Error("Can't call addStorageKey for a storage key if it has already been added.");this.trackedStorageKeys.add(e),this.storageAgent.invoke_setStorageBucketTracking({storageKey:e,enable:!0})}removeStorageKey(e){if(!this.trackedStorageKeys.has(e))throw new Error("Can't call removeStorageKey for a storage key if it hasn't already been added.");const t=this.getBucketsForStorageKey(e);for(const e of t)this.bucketRemoved(e);this.trackedStorageKeys.delete(e),this.storageAgent.invoke_setStorageBucketTracking({storageKey:e,enable:!1})}bucketAdded(e){this.bucketsById.set(e.id,e),this.dispatchEventToListeners("BucketAdded",{model:this,bucketInfo:e})}bucketRemoved(e){this.bucketsById.delete(e.id),this.dispatchEventToListeners("BucketRemoved",{model:this,bucketInfo:e})}bucketChanged(e){this.dispatchEventToListeners("BucketChanged",{model:this,bucketInfo:e})}bucketInfosAreEqual(e,t){return e.bucket.storageKey===t.bucket.storageKey&&e.id===t.id&&e.bucket.name===t.bucket.name&&e.expiration===t.expiration&&e.quota===t.quota&&e.persistent===t.persistent&&e.durability===t.durability}storageBucketCreatedOrUpdated({bucketInfo:e}){const t=this.getBucketById(e.id);t?this.bucketInfosAreEqual(t,e)||this.bucketChanged(e):this.bucketAdded(e)}storageBucketDeleted({bucketId:e}){const t=this.getBucketById(e);if(!t)throw new Error(`Received an event that Storage Bucket '${e}' was deleted, but it wasn't in the StorageBucketsModel.`);this.bucketRemoved(t)}interestGroupAccessed(e){}indexedDBListUpdated(e){}indexedDBContentUpdated(e){}cacheStorageListUpdated(e){}cacheStorageContentUpdated(e){}sharedStorageAccessed(e){}}c.register(sa,{capabilities:z.Storage,autostart:!1});var ia=Object.freeze({__proto__:null,StorageBucketsModel:sa});const aa={serviceworkercacheagentError:"`ServiceWorkerCacheAgent` error deleting cache entry {PH1} in cache: {PH2}"},oa=s.i18n.registerUIStrings("core/sdk/ServiceWorkerCacheModel.ts",aa),la=s.i18n.getLocalizedString.bind(void 0,oa);class da extends c{cacheAgent;#ld;#dd;#cd=new Map;#hd=new Set;#ud=new Set;#gd=new e.Throttler.Throttler(2e3);#ma=!1;#pd=!1;constructor(e){super(e),e.registerStorageDispatcher(this),this.cacheAgent=e.cacheStorageAgent(),this.#ld=e.storageAgent(),this.#dd=e.model(sa)}enable(){if(!this.#ma){this.#dd.addEventListener("BucketAdded",this.storageBucketAdded,this),this.#dd.addEventListener("BucketRemoved",this.storageBucketRemoved,this);for(const e of this.#dd.getBuckets())this.addStorageBucket(e.bucket);this.#ma=!0}}clearForStorageKey(e){for(const[t,n]of this.#cd.entries())n.storageKey===e&&(this.#cd.delete(t),this.cacheRemoved(n));for(const t of this.#dd.getBucketsForStorageKey(e))this.loadCacheNames(t.bucket)}refreshCacheNames(){for(const e of this.#cd.values())this.cacheRemoved(e);this.#cd.clear();const e=this.#dd.getBuckets();for(const t of e)this.loadCacheNames(t.bucket)}async deleteCache(e){const t=await this.cacheAgent.invoke_deleteCache({cacheId:e.cacheId});t.getError()?console.error(`ServiceWorkerCacheAgent error deleting cache ${e.toString()}: ${t.getError()}`):(this.#cd.delete(e.cacheId),this.cacheRemoved(e))}async deleteCacheEntry(t,n){const r=await this.cacheAgent.invoke_deleteEntry({cacheId:t.cacheId,request:n});r.getError()&&e.Console.Console.instance().error(la(aa.serviceworkercacheagentError,{PH1:t.toString(),PH2:String(r.getError())}))}loadCacheData(e,t,n,r,s){this.requestEntries(e,t,n,r,s)}loadAllCacheData(e,t,n){this.requestAllEntries(e,t,n)}caches(){const e=new Array;for(const t of this.#cd.values())e.push(t);return e}dispose(){for(const e of this.#cd.values())this.cacheRemoved(e);this.#cd.clear(),this.#ma&&(this.#dd.removeEventListener("BucketAdded",this.storageBucketAdded,this),this.#dd.removeEventListener("BucketRemoved",this.storageBucketRemoved,this))}addStorageBucket(e){this.loadCacheNames(e),this.#hd.has(e.storageKey)||(this.#hd.add(e.storageKey),this.#ld.invoke_trackCacheStorageForStorageKey({storageKey:e.storageKey}))}removeStorageBucket(e){let t=0;for(const[n,r]of this.#cd.entries())e.storageKey===r.storageKey&&t++,r.inBucket(e)&&(t--,this.#cd.delete(n),this.cacheRemoved(r));0===t&&(this.#hd.delete(e.storageKey),this.#ld.invoke_untrackCacheStorageForStorageKey({storageKey:e.storageKey}))}async loadCacheNames(e){const t=await this.cacheAgent.invoke_requestCacheNames({storageBucket:e});t.getError()||this.updateCacheNames(e,t.caches)}updateCacheNames(e,t){const n=new Set,r=new Map,s=new Map;for(const e of t){const t=e.storageBucket??this.#dd.getDefaultBucketForStorageKey(e.storageKey)?.bucket;if(!t)continue;const s=new ha(this,t,e.cacheName,e.cacheId);n.add(s.cacheId),this.#cd.has(s.cacheId)||(r.set(s.cacheId,s),this.#cd.set(s.cacheId,s))}this.#cd.forEach((function(t){t.inBucket(e)&&!n.has(t.cacheId)&&(s.set(t.cacheId,t),this.#cd.delete(t.cacheId))}),this),r.forEach(this.cacheAdded,this),s.forEach(this.cacheRemoved,this)}storageBucketAdded({data:{bucketInfo:{bucket:e}}}){this.addStorageBucket(e)}storageBucketRemoved({data:{bucketInfo:{bucket:e}}}){this.removeStorageBucket(e)}cacheAdded(e){this.dispatchEventToListeners(ca.CacheAdded,{model:this,cache:e})}cacheRemoved(e){this.dispatchEventToListeners(ca.CacheRemoved,{model:this,cache:e})}async requestEntries(e,t,n,r,s){const i=await this.cacheAgent.invoke_requestEntries({cacheId:e.cacheId,skipCount:t,pageSize:n,pathFilter:r});i.getError()?console.error("ServiceWorkerCacheAgent error while requesting entries: ",i.getError()):s(i.cacheDataEntries,i.returnCount)}async requestAllEntries(e,t,n){const r=await this.cacheAgent.invoke_requestEntries({cacheId:e.cacheId,pathFilter:t});r.getError()?console.error("ServiceWorkerCacheAgent error while requesting entries: ",r.getError()):n(r.cacheDataEntries,r.returnCount)}cacheStorageListUpdated({bucketId:e}){const t=this.#dd.getBucketById(e)?.bucket;t&&(this.#ud.add(t),this.#gd.schedule((()=>{const e=Array.from(this.#ud,(e=>this.loadCacheNames(e)));return this.#ud.clear(),Promise.all(e)}),this.#pd))}cacheStorageContentUpdated({bucketId:e,cacheName:t}){const n=this.#dd.getBucketById(e)?.bucket;n&&this.dispatchEventToListeners(ca.CacheStorageContentUpdated,{storageBucket:n,cacheName:t})}indexedDBListUpdated(e){}indexedDBContentUpdated(e){}interestGroupAccessed(e){}sharedStorageAccessed(e){}storageBucketCreatedOrUpdated(e){}storageBucketDeleted(e){}setThrottlerSchedulesAsSoonAsPossibleForTest(){this.#pd=!0}}var ca;!function(e){e.CacheAdded="CacheAdded",e.CacheRemoved="CacheRemoved",e.CacheStorageContentUpdated="CacheStorageContentUpdated"}(ca||(ca={}));class ha{#$r;storageKey;storageBucket;cacheName;cacheId;constructor(e,t,n,r){this.#$r=e,this.storageBucket=t,this.storageKey=t.storageKey,this.cacheName=n,this.cacheId=r}inBucket(e){return this.storageKey===e.storageKey&&this.storageBucket.name===e.name}equals(e){return this.cacheId===e.cacheId}toString(){return this.storageKey+this.cacheName}async requestCachedResponse(e,t){const n=await this.#$r.cacheAgent.invoke_requestCachedResponse({cacheId:this.cacheId,requestURL:e,requestHeaders:t});return n.getError()?null:n.response}}c.register(da,{capabilities:z.Storage,autostart:!1});var ua=Object.freeze({__proto__:null,ServiceWorkerCacheModel:da,get Events(){return ca},Cache:ha});const ga={running:"running",starting:"starting",stopped:"stopped",stopping:"stopping",activated:"activated",activating:"activating",installed:"installed",installing:"installing",new:"new",redundant:"redundant",sSS:"{PH1} #{PH2} ({PH3})"},pa=s.i18n.registerUIStrings("core/sdk/ServiceWorkerManager.ts",ga),ma=s.i18n.getLocalizedString.bind(void 0,pa),fa=s.i18n.getLazilyComputedLocalizedString.bind(void 0,pa);class ba extends c{#Ts;#md;#ma;#fd;serviceWorkerNetworkRequestsPanelStatus;constructor(t){super(t),t.registerServiceWorkerDispatcher(new va(this)),this.#Ts=t.serviceWorkerAgent(),this.#md=new Map,this.#ma=!1,this.enable(),this.#fd=e.Settings.Settings.instance().createSetting("serviceWorkerUpdateOnReload",!1),this.#fd.get()&&this.forceUpdateSettingChanged(),this.#fd.addChangeListener(this.forceUpdateSettingChanged,this),new wa(t,this),this.serviceWorkerNetworkRequestsPanelStatus={isOpen:!1,openedAt:0}}async enable(){this.#ma||(this.#ma=!0,await this.#Ts.invoke_enable())}async disable(){this.#ma&&(this.#ma=!1,this.#md.clear(),await this.#Ts.invoke_enable())}registrations(){return this.#md}hasRegistrationForURLs(e){for(const t of this.#md.values())if(e.filter((e=>e&&e.startsWith(t.scopeURL))).length===e.length)return!0;return!1}findVersion(e){for(const t of this.registrations().values()){const n=t.versions.get(e);if(n)return n}return null}deleteRegistration(e){const t=this.#md.get(e);if(t){if(t.isRedundant())return this.#md.delete(e),void this.dispatchEventToListeners(ya.RegistrationDeleted,t);t.deleting=!0;for(const e of t.versions.values())this.stopWorker(e.id);this.unregister(t.scopeURL)}}async updateRegistration(e){const t=this.#md.get(e);t&&await this.#Ts.invoke_updateRegistration({scopeURL:t.scopeURL})}async deliverPushMessage(t,n){const r=this.#md.get(t);if(!r)return;const s=e.ParsedURL.ParsedURL.extractOrigin(r.scopeURL);await this.#Ts.invoke_deliverPushMessage({origin:s,registrationId:t,data:n})}async dispatchSyncEvent(t,n,r){const s=this.#md.get(t);if(!s)return;const i=e.ParsedURL.ParsedURL.extractOrigin(s.scopeURL);await this.#Ts.invoke_dispatchSyncEvent({origin:i,registrationId:t,tag:n,lastChance:r})}async dispatchPeriodicSyncEvent(t,n){const r=this.#md.get(t);if(!r)return;const s=e.ParsedURL.ParsedURL.extractOrigin(r.scopeURL);await this.#Ts.invoke_dispatchPeriodicSyncEvent({origin:s,registrationId:t,tag:n})}async unregister(e){await this.#Ts.invoke_unregister({scopeURL:e})}async startWorker(e){await this.#Ts.invoke_startWorker({scopeURL:e})}async skipWaiting(e){await this.#Ts.invoke_skipWaiting({scopeURL:e})}async stopWorker(e){await this.#Ts.invoke_stopWorker({versionId:e})}async inspectWorker(e){await this.#Ts.invoke_inspectWorker({versionId:e})}workerRegistrationUpdated(e){for(const t of e){let e=this.#md.get(t.registrationId);e?(e.update(t),e.shouldBeRemoved()?(this.#md.delete(e.id),this.dispatchEventToListeners(ya.RegistrationDeleted,e)):this.dispatchEventToListeners(ya.RegistrationUpdated,e)):(e=new Sa(t),this.#md.set(t.registrationId,e),this.dispatchEventToListeners(ya.RegistrationUpdated,e))}}workerVersionUpdated(e){const t=new Set;for(const n of e){const e=this.#md.get(n.registrationId);e&&(e.updateVersion(n),t.add(e))}for(const e of t)e.shouldBeRemoved()?(this.#md.delete(e.id),this.dispatchEventToListeners(ya.RegistrationDeleted,e)):this.dispatchEventToListeners(ya.RegistrationUpdated,e)}workerErrorReported(e){const t=this.#md.get(e.registrationId);t&&(t.errors.push(e),this.dispatchEventToListeners(ya.RegistrationErrorAdded,{registration:t,error:e}))}forceUpdateOnReloadSetting(){return this.#fd}forceUpdateSettingChanged(){const e=this.#fd.get();this.#Ts.invoke_setForceUpdateOnPageLoad({forceUpdateOnPageLoad:e})}}var ya;!function(e){e.RegistrationUpdated="RegistrationUpdated",e.RegistrationErrorAdded="RegistrationErrorAdded",e.RegistrationDeleted="RegistrationDeleted"}(ya||(ya={}));class va{#$;constructor(e){this.#$=e}workerRegistrationUpdated({registrations:e}){this.#$.workerRegistrationUpdated(e)}workerVersionUpdated({versions:e}){this.#$.workerVersionUpdated(e)}workerErrorReported({errorMessage:e}){this.#$.workerErrorReported(e)}}class Ia{runningStatus;status;last_updated_timestamp;previousState;constructor(e,t,n,r){this.runningStatus=e,this.status=t,this.last_updated_timestamp=r,this.previousState=n}}class ka{id;scriptURL;parsedURL;securityOrigin;scriptLastModified;scriptResponseTime;controlledClients;targetId;currentState;registration;constructor(e,t){this.registration=e,this.update(t)}update(t){this.id=t.versionId,this.scriptURL=t.scriptURL;const n=new e.ParsedURL.ParsedURL(t.scriptURL);this.securityOrigin=n.securityOrigin(),this.currentState=new Ia(t.runningStatus,t.status,this.currentState,Date.now()),this.scriptLastModified=t.scriptLastModified,this.scriptResponseTime=t.scriptResponseTime,t.controlledClients?this.controlledClients=t.controlledClients.slice():this.controlledClients=[],this.targetId=t.targetId||null}isStartable(){return!this.registration.isDeleted&&this.isActivated()&&this.isStopped()}isStoppedAndRedundant(){return"stopped"===this.runningStatus&&"redundant"===this.status}isStopped(){return"stopped"===this.runningStatus}isStarting(){return"starting"===this.runningStatus}isRunning(){return"running"===this.runningStatus}isStopping(){return"stopping"===this.runningStatus}isNew(){return"new"===this.status}isInstalling(){return"installing"===this.status}isInstalled(){return"installed"===this.status}isActivating(){return"activating"===this.status}isActivated(){return"activated"===this.status}isRedundant(){return"redundant"===this.status}get status(){return this.currentState.status}get runningStatus(){return this.currentState.runningStatus}mode(){return this.isNew()||this.isInstalling()?ka.Modes.Installing:this.isInstalled()?ka.Modes.Waiting:this.isActivating()||this.isActivated()?ka.Modes.Active:ka.Modes.Redundant}}!function(e){let t;e.RunningStatus={running:fa(ga.running),starting:fa(ga.starting),stopped:fa(ga.stopped),stopping:fa(ga.stopping)},e.Status={activated:fa(ga.activated),activating:fa(ga.activating),installed:fa(ga.installed),installing:fa(ga.installing),new:fa(ga.new),redundant:fa(ga.redundant)},function(e){e.Installing="installing",e.Waiting="waiting",e.Active="active",e.Redundant="redundant"}(t=e.Modes||(e.Modes={}))}(ka||(ka={}));class Sa{#bd;id;scopeURL;securityOrigin;isDeleted;versions;deleting;errors;constructor(e){this.update(e),this.versions=new Map,this.deleting=!1,this.errors=[]}update(t){this.#bd=Symbol("fingerprint"),this.id=t.registrationId,this.scopeURL=t.scopeURL;const n=new e.ParsedURL.ParsedURL(t.scopeURL);this.securityOrigin=n.securityOrigin(),this.isDeleted=t.isDeleted}fingerprint(){return this.#bd}versionsByMode(){const e=new Map;for(const t of this.versions.values())e.set(t.mode(),t);return e}updateVersion(e){this.#bd=Symbol("fingerprint");let t=this.versions.get(e.versionId);return t?(t.update(e),t):(t=new ka(this,e),this.versions.set(e.versionId,t),t)}isRedundant(){for(const e of this.versions.values())if(!e.isStoppedAndRedundant())return!1;return!0}shouldBeRemoved(){return this.isRedundant()&&(!this.errors.length||this.deleting)}canBeRemoved(){return this.isDeleted||this.deleting}clearErrors(){this.#bd=Symbol("fingerprint"),this.errors=[]}}class wa{#h;#yd;#vd;constructor(e,t){this.#h=e,this.#yd=t,this.#vd=new Map,t.addEventListener(ya.RegistrationUpdated,this.registrationsUpdated,this),t.addEventListener(ya.RegistrationDeleted,this.registrationsUpdated,this),K.instance().addModelListener(Cr,Rr.ExecutionContextCreated,this.executionContextCreated,this)}registrationsUpdated(){this.#vd.clear();const e=this.#yd.registrations().values();for(const t of e)for(const e of t.versions.values())e.targetId&&this.#vd.set(e.targetId,e);this.updateAllContextLabels()}executionContextCreated(e){const t=e.data,n=this.serviceWorkerTargetId(t.target());n&&this.updateContextLabel(t,this.#vd.get(n)||null)}serviceWorkerTargetId(e){return e.parentTarget()!==this.#h||e.type()!==_.ServiceWorker?null:e.id()}updateAllContextLabels(){for(const e of K.instance().targets()){const t=this.serviceWorkerTargetId(e);if(!t)continue;const n=this.#vd.get(t)||null,r=e.model(Cr),s=r?r.executionContexts():[];for(const e of s)this.updateContextLabel(e,n)}}updateContextLabel(t,n){if(!n)return void t.setLabel("");const r=e.ParsedURL.ParsedURL.fromString(t.origin),s=r?r.lastPathComponentWithFragment():t.name,i=ka.Status[n.status];t.setLabel(ma(ga.sSS,{PH1:s,PH2:n.id,PH3:i()}))}}c.register(ba,{capabilities:z.ServiceWorker,autostart:!0});var Ca=Object.freeze({__proto__:null,ServiceWorkerManager:ba,get Events(){return ya},ServiceWorkerVersionState:Ia,get ServiceWorkerVersion(){return ka},ServiceWorkerRegistration:Sa});const Ta=new Map,Ra=new Map;async function xa(e,t){const n=Ta.get(e)?.get(t);if(void 0!==n)return n;const r=K.instance().primaryPageTarget()?.model(Pn);if(!r)return null;const s=(await r.pushNodesByBackendIdsToFrontend(new Set([t])))?.get(t)||null,i=Ta.get(e)||new Map;return i.set(t,s),Ta.set(e,i),s}const Ma=new Map,Pa=new Map;var La=Object.freeze({__proto__:null,_TEST_clearCache:function(){Ta.clear(),Ra.clear(),Ma.clear(),Pa.clear()},domNodeForBackendNodeID:xa,domNodesForMultipleBackendNodeIds:async function(e,t){const n=Ra.get(e)?.get(t);if(n)return n;const r=K.instance().primaryPageTarget()?.model(Pn);if(!r)return new Map;const s=await r.pushNodesByBackendIdsToFrontend(t)||new Map,i=Ra.get(e)||new Map;return i.set(t,s),Ra.set(e,i),s},sourcesForLayoutShift:async function(e,t){const n=Ma.get(e)?.get(t);if(n)return n;const r=t.args.data?.impacted_nodes;if(!r)return[];const s=[];await Promise.all(r.map((async t=>{const n=await xa(e,t.node_id);n&&s.push({previousRect:new DOMRect(t.old_rect[0],t.old_rect[1],t.old_rect[2],t.old_rect[3]),currentRect:new DOMRect(t.new_rect[0],t.new_rect[1],t.new_rect[2],t.new_rect[3]),node:n})})));const i=Ma.get(e)||new Map;return i.set(t,s),Ma.set(e,i),s},normalizedImpactedNodesForLayoutShift:async function(e,t){const n=Pa.get(e)?.get(t);if(n)return n;const r=t.args?.data?.impacted_nodes;if(!r)return[];let s=null;const i=K.instance().primaryPageTarget(),a=await(i?.runtimeAgent().invoke_evaluate({expression:"window.devicePixelRatio"}));if("number"===a?.result.type&&(s=a?.result.value??null),!s)return r;const o=[];for(const e of r){const t={...e};for(let n=0;n{setTimeout((()=>e(void 0)),1e3)}))]):void 0,n=Ts.instance().cpuThrottlingRate(),r=ue.instance().networkConditions(),s="function"==typeof r.title?r.title():r.title;return{source:"DevTools",startTime:e?new Date(e).toJSON():void 0,cpuThrottling:n,networkThrottling:s,hardwareConcurrency:t}}catch{return}}});class Ea extends c{#Id;#kd;#Sd;#wd;#Cd;constructor(e){super(e),this.#Id=e.tracingAgent(),e.registerTracingDispatcher(new Aa(this)),this.#kd=null,this.#Sd=0,this.#wd=0}bufferUsage(e,t,n){this.#Sd=void 0===t?null:t,this.#kd&&this.#kd.tracingBufferUsage(e||n||0)}eventsCollected(e){this.#kd&&(this.#kd.traceEventsCollected(e),this.#wd+=e.length,this.#Sd?(this.#wd>this.#Sd&&(this.#wd=this.#Sd),this.#kd.eventsRetrievalProgress(this.#wd/this.#Sd)):this.#kd.eventsRetrievalProgress(0))}tracingComplete(){this.#Sd=0,this.#wd=0,this.#kd&&(this.#kd.tracingComplete(),this.#kd=null),this.#Cd=!1}async start(e,t,n){if(this.#kd)throw new Error("Tracing is already started");this.#kd=e;const r={bufferUsageReportingInterval:500,categories:t,options:n,transferMode:"ReportEvents"},s=await this.#Id.invoke_start(r);return s.getError()&&(this.#kd=null),s}stop(){if(!this.#kd)throw new Error("Tracing is not started");if(this.#Cd)throw new Error("Tracing is already being stopped");this.#Cd=!0,this.#Id.invoke_end()}}class Aa{#Td;constructor(e){this.#Td=e}bufferUsage({value:e,eventCount:t,percentFull:n}){this.#Td.bufferUsage(e,t,n)}dataCollected({value:e}){this.#Td.eventsCollected(e)}tracingComplete(){this.#Td.tracingComplete()}}c.register(Ea,{capabilities:z.Tracing,autostart:!1});var Oa=Object.freeze({__proto__:null,TracingManager:Ea});class Na extends c{#Ts;constructor(e){super(e),this.#Ts=e.webAuthnAgent(),e.registerWebAuthnDispatcher(new Fa(this))}setVirtualAuthEnvEnabled(e){return e?this.#Ts.invoke_enable({enableUI:!0}):this.#Ts.invoke_disable()}async addAuthenticator(e){return(await this.#Ts.invoke_addVirtualAuthenticator({options:e})).authenticatorId}async removeAuthenticator(e){await this.#Ts.invoke_removeVirtualAuthenticator({authenticatorId:e})}async setAutomaticPresenceSimulation(e,t){await this.#Ts.invoke_setAutomaticPresenceSimulation({authenticatorId:e,enabled:t})}async getCredentials(e){return(await this.#Ts.invoke_getCredentials({authenticatorId:e})).credentials}async removeCredential(e,t){await this.#Ts.invoke_removeCredential({authenticatorId:e,credentialId:t})}credentialAdded(e){this.dispatchEventToListeners("CredentialAdded",e)}credentialAsserted(e){this.dispatchEventToListeners("CredentialAsserted",e)}}class Fa{#$r;constructor(e){this.#$r=e}credentialAdded(e){this.#$r.credentialAdded(e)}credentialAsserted(e){this.#$r.credentialAsserted(e)}}c.register(Na,{capabilities:z.WebAuthn,autostart:!1});var Ba=Object.freeze({__proto__:null,WebAuthnModel:Na});export{Nr as AccessibilityModel,vs as CPUProfileDataModel,ss as CPUProfilerModel,Ms as CPUThrottlingManager,Qe as CSSContainerQuery,ze as CSSFontFace,Je as CSSLayer,wt as CSSMatchedStyles,tt as CSSMedia,E as CSSMetadata,hn as CSSModel,lt as CSSProperty,Fs as CSSPropertyParser,We as CSSQuery,yt as CSSRule,rt as CSSScope,ct as CSSStyleDeclaration,Mt as CSSStyleSheetHeader,it as CSSSupports,Br as CategorizedBreakpoint,Vr as ChildTargetManager,Jr as CompilerSourceMappingContentProvider,jr as Connections,ms as ConsoleModel,U as Cookie,bs as CookieModel,j as CookieParser,$s as DOMDebuggerModel,On as DOMModel,Ir as DebuggerModel,ws as EmulationModel,ni as EventBreakpointsModel,Ci as FilmStripModel,Ti as FrameAssociated,At as FrameManager,wr as HeapProfilerModel,Nt as IOModel,Ai as IsolateManager,Fi as IssuesModel,Bi as LayerTreeBase,as as LogModel,me as NetworkManager,Pe as NetworkRequest,gn as OverlayColorGenerator,Cn as OverlayModel,mn as OverlayPersistentHighlighter,Hi as PageLoad,zt as PageResourceLoader,ji as PaintProfiler,Gi as PerformanceMetricsModel,ta as PreloadingModel,N as ProfileTreeModel,qe as RemoteObject,Bn as Resource,Kn as ResourceTreeModel,Er as RuntimeModel,h as SDKModel,ra as ScreenCaptureModel,tr as Script,Hn as SecurityOriginManager,Ie as ServerTiming,ua as ServiceWorkerCacheModel,Ca as ServiceWorkerManager,Xt as SourceMap,Zt as SourceMapManager,ia as StorageBucketsModel,zn as StorageKeyManager,V as Target,Q as TargetManager,La as TraceSDKServices,Oa as TracingManager,Ii as TracingModel,Ba as WebAuthnModel}; +import*as e from"../common/common.js";import*as t from"../platform/platform.js";import{assertNotNullOrUndefined as n}from"../platform/platform.js";import*as r from"../../models/text_utils/text_utils.js";import*as s from"../i18n/i18n.js";import*as i from"../host/host.js";import*as a from"../protocol_client/protocol_client.js";import*as o from"../root/root.js";import*as l from"../../models/trace/trace.js";const d=new Map;class c extends e.ObjectWrapper.ObjectWrapper{#e;constructor(e){super(),this.#e=e}target(){return this.#e}async preSuspendModel(e){}async suspendModel(e){}async resumeModel(){}async postResumeModel(){}dispose(){}static register(e,t){if(t.early&&!t.autostart)throw new Error(`Error registering model ${e.name}: early models must be autostarted.`);d.set(e,t)}static get registeredModels(){return d}}var h=Object.freeze({__proto__:null,SDKModel:c});const u=[{longhands:["animation-delay-start","animation-delay-end"],name:"-alternative-animation-delay"},{longhands:["animation-duration","animation-timing-function","animation-delay-start","animation-delay-end","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name","animation-timeline","animation-range-start","animation-range-end"],name:"-alternative-animation-with-delay-start-end"},{longhands:["animation-duration","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name","animation-timeline","animation-range-start","animation-range-end"],name:"-alternative-animation-with-timeline"},{inherited:!0,longhands:["white-space-collapse","text-wrap"],name:"-alternative-white-space"},{inherited:!0,name:"-webkit-border-horizontal-spacing"},{name:"-webkit-border-image"},{inherited:!0,name:"-webkit-border-vertical-spacing"},{keywords:["stretch","start","center","end","baseline"],name:"-webkit-box-align"},{keywords:["slice","clone"],name:"-webkit-box-decoration-break"},{inherited:!0,keywords:["normal","reverse"],name:"-webkit-box-direction"},{name:"-webkit-box-flex"},{name:"-webkit-box-ordinal-group"},{keywords:["horizontal","vertical"],name:"-webkit-box-orient"},{keywords:["start","center","end","justify"],name:"-webkit-box-pack"},{name:"-webkit-box-reflect"},{longhands:["break-after"],name:"-webkit-column-break-after"},{longhands:["break-before"],name:"-webkit-column-break-before"},{longhands:["break-inside"],name:"-webkit-column-break-inside"},{inherited:!0,name:"-webkit-font-smoothing"},{inherited:!0,name:"-webkit-highlight"},{inherited:!0,keywords:["auto","loose","normal","strict","after-white-space","anywhere"],name:"-webkit-line-break"},{name:"-webkit-line-clamp"},{inherited:!0,name:"-webkit-locale"},{longhands:["-webkit-mask-image","-webkit-mask-position-x","-webkit-mask-position-y","-webkit-mask-size","-webkit-mask-repeat-x","-webkit-mask-repeat-y","-webkit-mask-origin","-webkit-mask-clip"],name:"-webkit-mask"},{longhands:["-webkit-mask-box-image-source","-webkit-mask-box-image-slice","-webkit-mask-box-image-width","-webkit-mask-box-image-outset","-webkit-mask-box-image-repeat"],name:"-webkit-mask-box-image"},{name:"-webkit-mask-box-image-outset"},{name:"-webkit-mask-box-image-repeat"},{name:"-webkit-mask-box-image-slice"},{name:"-webkit-mask-box-image-source"},{name:"-webkit-mask-box-image-width"},{name:"-webkit-mask-clip"},{name:"-webkit-mask-composite"},{name:"-webkit-mask-image"},{name:"-webkit-mask-origin"},{longhands:["-webkit-mask-position-x","-webkit-mask-position-y"],name:"-webkit-mask-position"},{name:"-webkit-mask-position-x"},{name:"-webkit-mask-position-y"},{longhands:["-webkit-mask-repeat-x","-webkit-mask-repeat-y"],name:"-webkit-mask-repeat"},{name:"-webkit-mask-repeat-x"},{name:"-webkit-mask-repeat-y"},{name:"-webkit-mask-size"},{name:"-webkit-perspective-origin-x"},{name:"-webkit-perspective-origin-y"},{inherited:!0,keywords:["economy","exact"],name:"-webkit-print-color-adjust"},{inherited:!0,keywords:["logical","visual"],name:"-webkit-rtl-ordering"},{inherited:!0,keywords:["before","after"],name:"-webkit-ruby-position"},{inherited:!0,name:"-webkit-tap-highlight-color"},{inherited:!0,name:"-webkit-text-combine"},{inherited:!0,name:"-webkit-text-decorations-in-effect"},{inherited:!0,name:"-webkit-text-fill-color"},{inherited:!0,name:"-webkit-text-orientation"},{inherited:!0,keywords:["none","disc","circle","square"],name:"-webkit-text-security"},{inherited:!0,longhands:["-webkit-text-stroke-width","-webkit-text-stroke-color"],name:"-webkit-text-stroke"},{inherited:!0,name:"-webkit-text-stroke-color"},{inherited:!0,name:"-webkit-text-stroke-width"},{name:"-webkit-transform-origin-x"},{name:"-webkit-transform-origin-y"},{name:"-webkit-transform-origin-z"},{keywords:["auto","none","element"],name:"-webkit-user-drag"},{inherited:!0,keywords:["read-only","read-write","read-write-plaintext-only"],name:"-webkit-user-modify"},{inherited:!0,name:"-webkit-writing-mode"},{inherited:!0,keywords:["auto","currentcolor"],name:"accent-color"},{name:"additive-symbols"},{name:"align-content"},{name:"align-items"},{name:"align-self"},{keywords:["auto","baseline","alphabetic","ideographic","middle","central","mathematical","before-edge","text-before-edge","after-edge","text-after-edge","hanging"],name:"alignment-baseline"},{name:"all"},{keywords:["none"],name:"anchor-default"},{keywords:["none"],name:"anchor-name"},{keywords:["none"],name:"anchor-scroll"},{longhands:["animation-duration","animation-timing-function","animation-delay","animation-iteration-count","animation-direction","animation-fill-mode","animation-play-state","animation-name"],name:"animation"},{keywords:["replace","add","accumulate"],name:"animation-composition"},{name:"animation-delay"},{name:"animation-delay-end"},{name:"animation-delay-start"},{keywords:["normal","reverse","alternate","alternate-reverse"],name:"animation-direction"},{name:"animation-duration"},{keywords:["none","forwards","backwards","both"],name:"animation-fill-mode"},{keywords:["infinite"],name:"animation-iteration-count"},{keywords:["none"],name:"animation-name"},{keywords:["running","paused"],name:"animation-play-state"},{longhands:["animation-range-start","animation-range-end"],name:"animation-range"},{name:"animation-range-end"},{name:"animation-range-start"},{keywords:["none","auto"],name:"animation-timeline"},{keywords:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"],name:"animation-timing-function"},{keywords:["none","drag","no-drag"],name:"app-region"},{name:"appearance"},{name:"ascent-override"},{keywords:["auto"],name:"aspect-ratio"},{keywords:["none"],name:"backdrop-filter"},{keywords:["visible","hidden"],name:"backface-visibility"},{longhands:["background-image","background-position-x","background-position-y","background-size","background-repeat-x","background-repeat-y","background-attachment","background-origin","background-clip","background-color"],name:"background"},{keywords:["scroll","fixed","local"],name:"background-attachment"},{keywords:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],name:"background-blend-mode"},{keywords:["border-box","padding-box","content-box"],name:"background-clip"},{keywords:["currentcolor"],name:"background-color"},{keywords:["auto","none"],name:"background-image"},{keywords:["border-box","padding-box","content-box"],name:"background-origin"},{longhands:["background-position-x","background-position-y"],name:"background-position"},{name:"background-position-x"},{name:"background-position-y"},{longhands:["background-repeat-x","background-repeat-y"],name:"background-repeat"},{name:"background-repeat-x"},{name:"background-repeat-y"},{keywords:["auto","cover","contain"],name:"background-size"},{name:"base-palette"},{keywords:["baseline","sub","super"],name:"baseline-shift"},{keywords:["auto","first","last"],name:"baseline-source"},{keywords:["auto"],name:"block-size"},{longhands:["border-top-color","border-top-style","border-top-width","border-right-color","border-right-style","border-right-width","border-bottom-color","border-bottom-style","border-bottom-width","border-left-color","border-left-style","border-left-width","border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],name:"border"},{longhands:["border-block-start-color","border-block-start-style","border-block-start-width","border-block-end-color","border-block-end-style","border-block-end-width"],name:"border-block"},{longhands:["border-block-start-color","border-block-end-color"],name:"border-block-color"},{longhands:["border-block-end-width","border-block-end-style","border-block-end-color"],name:"border-block-end"},{name:"border-block-end-color"},{name:"border-block-end-style"},{name:"border-block-end-width"},{longhands:["border-block-start-width","border-block-start-style","border-block-start-color"],name:"border-block-start"},{name:"border-block-start-color"},{name:"border-block-start-style"},{name:"border-block-start-width"},{longhands:["border-block-start-style","border-block-end-style"],name:"border-block-style"},{longhands:["border-block-start-width","border-block-end-width"],name:"border-block-width"},{longhands:["border-bottom-width","border-bottom-style","border-bottom-color"],name:"border-bottom"},{keywords:["currentcolor"],name:"border-bottom-color"},{name:"border-bottom-left-radius"},{name:"border-bottom-right-radius"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-bottom-style"},{keywords:["thin","medium","thick"],name:"border-bottom-width"},{inherited:!0,keywords:["separate","collapse"],name:"border-collapse"},{longhands:["border-top-color","border-right-color","border-bottom-color","border-left-color"],name:"border-color"},{name:"border-end-end-radius"},{name:"border-end-start-radius"},{longhands:["border-image-source","border-image-slice","border-image-width","border-image-outset","border-image-repeat"],name:"border-image"},{name:"border-image-outset"},{keywords:["stretch","repeat","round","space"],name:"border-image-repeat"},{name:"border-image-slice"},{keywords:["none"],name:"border-image-source"},{keywords:["auto"],name:"border-image-width"},{longhands:["border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-end-color","border-inline-end-style","border-inline-end-width"],name:"border-inline"},{longhands:["border-inline-start-color","border-inline-end-color"],name:"border-inline-color"},{longhands:["border-inline-end-width","border-inline-end-style","border-inline-end-color"],name:"border-inline-end"},{name:"border-inline-end-color"},{name:"border-inline-end-style"},{name:"border-inline-end-width"},{longhands:["border-inline-start-width","border-inline-start-style","border-inline-start-color"],name:"border-inline-start"},{name:"border-inline-start-color"},{name:"border-inline-start-style"},{name:"border-inline-start-width"},{longhands:["border-inline-start-style","border-inline-end-style"],name:"border-inline-style"},{longhands:["border-inline-start-width","border-inline-end-width"],name:"border-inline-width"},{longhands:["border-left-width","border-left-style","border-left-color"],name:"border-left"},{keywords:["currentcolor"],name:"border-left-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-left-style"},{keywords:["thin","medium","thick"],name:"border-left-width"},{longhands:["border-top-left-radius","border-top-right-radius","border-bottom-right-radius","border-bottom-left-radius"],name:"border-radius"},{longhands:["border-right-width","border-right-style","border-right-color"],name:"border-right"},{keywords:["currentcolor"],name:"border-right-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-right-style"},{keywords:["thin","medium","thick"],name:"border-right-width"},{inherited:!0,longhands:["-webkit-border-horizontal-spacing","-webkit-border-vertical-spacing"],name:"border-spacing"},{name:"border-start-end-radius"},{name:"border-start-start-radius"},{keywords:["none"],longhands:["border-top-style","border-right-style","border-bottom-style","border-left-style"],name:"border-style"},{longhands:["border-top-width","border-top-style","border-top-color"],name:"border-top"},{keywords:["currentcolor"],name:"border-top-color"},{name:"border-top-left-radius"},{name:"border-top-right-radius"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"border-top-style"},{keywords:["thin","medium","thick"],name:"border-top-width"},{longhands:["border-top-width","border-right-width","border-bottom-width","border-left-width"],name:"border-width"},{keywords:["auto"],name:"bottom"},{keywords:["none"],name:"box-shadow"},{keywords:["content-box","border-box"],name:"box-sizing"},{keywords:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"],name:"break-after"},{keywords:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"],name:"break-before"},{keywords:["auto","avoid","avoid-column","avoid-page"],name:"break-inside"},{keywords:["auto","dynamic","static"],name:"buffered-rendering"},{inherited:!0,keywords:["top","bottom"],name:"caption-side"},{inherited:!0,keywords:["auto","currentcolor"],name:"caret-color"},{keywords:["none","left","right","both","inline-start","inline-end"],name:"clear"},{keywords:["auto"],name:"clip"},{keywords:["none"],name:"clip-path"},{inherited:!0,keywords:["nonzero","evenodd"],name:"clip-rule"},{inherited:!0,keywords:["currentcolor"],name:"color"},{inherited:!0,keywords:["auto","srgb","linearrgb"],name:"color-interpolation"},{inherited:!0,keywords:["auto","srgb","linearrgb"],name:"color-interpolation-filters"},{inherited:!0,keywords:["auto","optimizespeed","optimizequality"],name:"color-rendering"},{inherited:!0,name:"color-scheme"},{keywords:["auto"],name:"column-count"},{keywords:["balance","auto"],name:"column-fill"},{keywords:["normal"],name:"column-gap"},{longhands:["column-rule-width","column-rule-style","column-rule-color"],name:"column-rule"},{keywords:["currentcolor"],name:"column-rule-color"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"column-rule-style"},{keywords:["thin","medium","thick"],name:"column-rule-width"},{keywords:["none","all"],name:"column-span"},{keywords:["auto"],name:"column-width"},{longhands:["column-width","column-count"],name:"columns"},{keywords:["none","strict","content","size","layout","style","paint","inline-size","block-size"],name:"contain"},{name:"contain-intrinsic-block-size"},{keywords:["auto","none"],name:"contain-intrinsic-height"},{name:"contain-intrinsic-inline-size"},{longhands:["contain-intrinsic-width","contain-intrinsic-height"],name:"contain-intrinsic-size"},{keywords:["auto","none"],name:"contain-intrinsic-width"},{longhands:["container-name","container-type"],name:"container"},{keywords:["none"],name:"container-name"},{keywords:["normal","inline-size","size","sticky"],name:"container-type"},{name:"content"},{keywords:["visible","auto","hidden"],name:"content-visibility"},{keywords:["none"],name:"counter-increment"},{keywords:["none"],name:"counter-reset"},{keywords:["none"],name:"counter-set"},{inherited:!0,keywords:["auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize","s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","col-resize","row-resize","all-scroll","zoom-in","zoom-out","grab","grabbing"],name:"cursor"},{name:"cx"},{name:"cy"},{keywords:["none"],name:"d"},{name:"descent-override"},{inherited:!0,keywords:["ltr","rtl"],name:"direction"},{keywords:["inline","block","list-item","inline-block","table","inline-table","table-row-group","table-header-group","table-footer-group","table-row","table-column-group","table-column","table-cell","table-caption","-webkit-box","-webkit-inline-box","flex","inline-flex","grid","inline-grid","contents","flow-root","none","flow","math"],name:"display"},{inherited:!0,keywords:["auto","alphabetic","ideographic","middle","central","mathematical","hanging","use-script","no-change","reset-size","text-after-edge","text-before-edge"],name:"dominant-baseline"},{inherited:!0,keywords:["show","hide"],name:"empty-cells"},{name:"fallback"},{inherited:!0,name:"fill"},{inherited:!0,name:"fill-opacity"},{inherited:!0,keywords:["nonzero","evenodd"],name:"fill-rule"},{keywords:["none"],name:"filter"},{longhands:["flex-grow","flex-shrink","flex-basis"],name:"flex"},{keywords:["auto","fit-content","min-content","max-content","content"],name:"flex-basis"},{keywords:["row","row-reverse","column","column-reverse"],name:"flex-direction"},{longhands:["flex-direction","flex-wrap"],name:"flex-flow"},{name:"flex-grow"},{name:"flex-shrink"},{keywords:["nowrap","wrap","wrap-reverse"],name:"flex-wrap"},{keywords:["none","left","right","inline-start","inline-end"],name:"float"},{keywords:["currentcolor"],name:"flood-color"},{name:"flood-opacity"},{inherited:!0,longhands:["font-style","font-variant-ligatures","font-variant-caps","font-variant-numeric","font-variant-east-asian","font-variant-alternates","font-variant-position","font-weight","font-stretch","font-size","line-height","font-family","font-optical-sizing","font-size-adjust","font-kerning","font-feature-settings","font-variation-settings"],name:"font"},{name:"font-display"},{inherited:!0,name:"font-family"},{inherited:!0,keywords:["normal"],name:"font-feature-settings"},{inherited:!0,keywords:["auto","normal","none"],name:"font-kerning"},{inherited:!0,keywords:["auto","none"],name:"font-optical-sizing"},{inherited:!0,keywords:["normal","light","dark"],name:"font-palette"},{inherited:!0,keywords:["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large","larger","smaller","-webkit-xxx-large"],name:"font-size"},{inherited:!0,keywords:["none","ex-height","cap-height","ch-width","ic-width"],name:"font-size-adjust"},{inherited:!0,keywords:["normal","ultra-condensed","extra-condensed","condensed","semi-condensed","semi-expanded","expanded","extra-expanded","ultra-expanded"],name:"font-stretch"},{inherited:!0,keywords:["normal","italic","oblique"],name:"font-style"},{inherited:!0,longhands:["font-synthesis-weight","font-synthesis-style","font-synthesis-small-caps"],name:"font-synthesis"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-small-caps"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-style"},{inherited:!0,keywords:["auto","none"],name:"font-synthesis-weight"},{inherited:!0,longhands:["font-variant-ligatures","font-variant-caps","font-variant-alternates","font-variant-numeric","font-variant-east-asian","font-variant-position"],name:"font-variant"},{inherited:!0,keywords:["normal"],name:"font-variant-alternates"},{inherited:!0,keywords:["normal","small-caps","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps"],name:"font-variant-caps"},{inherited:!0,keywords:["normal","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"],name:"font-variant-east-asian"},{inherited:!0,keywords:["normal","none","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual"],name:"font-variant-ligatures"},{inherited:!0,keywords:["normal","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero"],name:"font-variant-numeric"},{inherited:!0,keywords:["normal","sub","super"],name:"font-variant-position"},{inherited:!0,keywords:["normal"],name:"font-variation-settings"},{inherited:!0,keywords:["normal","bold","bolder","lighter"],name:"font-weight"},{inherited:!0,keywords:["auto","none","preserve-parent-color"],name:"forced-color-adjust"},{longhands:["row-gap","column-gap"],name:"gap"},{longhands:["grid-template-rows","grid-template-columns","grid-template-areas","grid-auto-flow","grid-auto-rows","grid-auto-columns"],name:"grid"},{longhands:["grid-row-start","grid-column-start","grid-row-end","grid-column-end"],name:"grid-area"},{keywords:["auto","min-content","max-content"],name:"grid-auto-columns"},{keywords:["row","column"],name:"grid-auto-flow"},{keywords:["auto","min-content","max-content"],name:"grid-auto-rows"},{longhands:["grid-column-start","grid-column-end"],name:"grid-column"},{keywords:["auto"],name:"grid-column-end"},{longhands:["column-gap"],name:"grid-column-gap"},{keywords:["auto"],name:"grid-column-start"},{longhands:["row-gap","column-gap"],name:"grid-gap"},{longhands:["grid-row-start","grid-row-end"],name:"grid-row"},{keywords:["auto"],name:"grid-row-end"},{longhands:["row-gap"],name:"grid-row-gap"},{keywords:["auto"],name:"grid-row-start"},{longhands:["grid-template-rows","grid-template-columns","grid-template-areas"],name:"grid-template"},{keywords:["none"],name:"grid-template-areas"},{keywords:["none"],name:"grid-template-columns"},{keywords:["none"],name:"grid-template-rows"},{keywords:["auto","fit-content","min-content","max-content"],name:"height"},{inherited:!0,name:"hyphenate-character"},{inherited:!0,keywords:["auto"],name:"hyphenate-limit-chars"},{inherited:!0,keywords:["none","manual","auto"],name:"hyphens"},{inherited:!0,name:"image-orientation"},{inherited:!0,keywords:["auto","optimizespeed","optimizequality","-webkit-optimize-contrast","pixelated"],name:"image-rendering"},{name:"inherits"},{inherited:!1,keywords:["drop","normal","raise"],name:"initial-letter"},{name:"initial-value"},{keywords:["auto"],name:"inline-size"},{longhands:["top","right","bottom","left"],name:"inset"},{longhands:["inset-block-start","inset-block-end"],name:"inset-block"},{name:"inset-block-end"},{name:"inset-block-start"},{longhands:["inset-inline-start","inset-inline-end"],name:"inset-inline"},{name:"inset-inline-end"},{name:"inset-inline-start"},{keywords:["auto","isolate"],name:"isolation"},{name:"justify-content"},{name:"justify-items"},{name:"justify-self"},{keywords:["auto"],name:"left"},{inherited:!0,keywords:["normal"],name:"letter-spacing"},{keywords:["currentcolor"],name:"lighting-color"},{inherited:!0,keywords:["auto","loose","normal","strict","anywhere"],name:"line-break"},{name:"line-gap-override"},{inherited:!0,keywords:["normal"],name:"line-height"},{inherited:!0,longhands:["list-style-position","list-style-image","list-style-type"],name:"list-style"},{inherited:!0,keywords:["none"],name:"list-style-image"},{inherited:!0,keywords:["outside","inside"],name:"list-style-position"},{inherited:!0,keywords:["disc","circle","square","disclosure-open","disclosure-closed","decimal","none"],name:"list-style-type"},{longhands:["margin-top","margin-right","margin-bottom","margin-left"],name:"margin"},{longhands:["margin-block-start","margin-block-end"],name:"margin-block"},{keywords:["auto"],name:"margin-block-end"},{keywords:["auto"],name:"margin-block-start"},{keywords:["auto"],name:"margin-bottom"},{longhands:["margin-inline-start","margin-inline-end"],name:"margin-inline"},{keywords:["auto"],name:"margin-inline-end"},{keywords:["auto"],name:"margin-inline-start"},{keywords:["auto"],name:"margin-left"},{keywords:["auto"],name:"margin-right"},{keywords:["auto"],name:"margin-top"},{inherited:!0,longhands:["marker-start","marker-mid","marker-end"],name:"marker"},{inherited:!0,keywords:["none"],name:"marker-end"},{inherited:!0,keywords:["none"],name:"marker-mid"},{inherited:!0,keywords:["none"],name:"marker-start"},{name:"mask"},{keywords:["luminance","alpha"],name:"mask-type"},{inherited:!0,name:"math-depth"},{inherited:!0,keywords:["normal","compact"],name:"math-shift"},{inherited:!0,keywords:["normal","compact"],name:"math-style"},{keywords:["none"],name:"max-block-size"},{keywords:["none"],name:"max-height"},{keywords:["none"],name:"max-inline-size"},{keywords:["none"],name:"max-width"},{name:"min-block-size"},{name:"min-height"},{name:"min-inline-size"},{name:"min-width"},{keywords:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter"],name:"mix-blend-mode"},{name:"negative"},{keywords:["fill","contain","cover","none","scale-down"],name:"object-fit"},{name:"object-position"},{keywords:["none"],name:"object-view-box"},{longhands:["offset-position","offset-path","offset-distance","offset-rotate","offset-anchor"],name:"offset"},{keywords:["auto"],name:"offset-anchor"},{name:"offset-distance"},{keywords:["none"],name:"offset-path"},{keywords:["auto","normal"],name:"offset-position"},{keywords:["auto","reverse"],name:"offset-rotate"},{name:"opacity"},{name:"order"},{keywords:["normal","none"],name:"origin-trial-test-property"},{inherited:!0,name:"orphans"},{longhands:["outline-color","outline-style","outline-width"],name:"outline"},{keywords:["currentcolor"],name:"outline-color"},{name:"outline-offset"},{keywords:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"],name:"outline-style"},{keywords:["thin","medium","thick"],name:"outline-width"},{longhands:["overflow-x","overflow-y"],name:"overflow"},{inherited:!1,keywords:["visible","none","auto"],name:"overflow-anchor"},{name:"overflow-block"},{keywords:["border-box","content-box","padding-box"],name:"overflow-clip-margin"},{name:"overflow-inline"},{inherited:!0,keywords:["normal","break-word","anywhere"],name:"overflow-wrap"},{keywords:["visible","hidden","scroll","auto","overlay","clip"],name:"overflow-x"},{keywords:["visible","hidden","scroll","auto","overlay","clip"],name:"overflow-y"},{keywords:["none","auto"],name:"overlay"},{name:"override-colors"},{longhands:["overscroll-behavior-x","overscroll-behavior-y"],name:"overscroll-behavior"},{name:"overscroll-behavior-block"},{name:"overscroll-behavior-inline"},{keywords:["auto","contain","none"],name:"overscroll-behavior-x"},{keywords:["auto","contain","none"],name:"overscroll-behavior-y"},{name:"pad"},{longhands:["padding-top","padding-right","padding-bottom","padding-left"],name:"padding"},{longhands:["padding-block-start","padding-block-end"],name:"padding-block"},{name:"padding-block-end"},{name:"padding-block-start"},{name:"padding-bottom"},{longhands:["padding-inline-start","padding-inline-end"],name:"padding-inline"},{name:"padding-inline-end"},{name:"padding-inline-start"},{name:"padding-left"},{name:"padding-right"},{name:"padding-top"},{keywords:["auto"],name:"page"},{longhands:["break-after"],name:"page-break-after"},{longhands:["break-before"],name:"page-break-before"},{longhands:["break-inside"],name:"page-break-inside"},{name:"page-orientation"},{inherited:!0,keywords:["normal","fill","stroke","markers"],name:"paint-order"},{keywords:["none"],name:"perspective"},{name:"perspective-origin"},{longhands:["align-content","justify-content"],name:"place-content"},{longhands:["align-items","justify-items"],name:"place-items"},{longhands:["align-self","justify-self"],name:"place-self"},{inherited:!0,keywords:["none","auto","stroke","fill","painted","visible","visiblestroke","visiblefill","visiblepainted","bounding-box","all"],name:"pointer-events"},{name:"popover-hide-delay"},{name:"popover-show-delay"},{keywords:["static","relative","absolute","fixed","sticky"],name:"position"},{keywords:["none"],name:"position-fallback"},{name:"prefix"},{inherited:!0,keywords:["auto","none"],name:"quotes"},{name:"r"},{name:"range"},{keywords:["none","both","horizontal","vertical","block","inline"],name:"resize"},{keywords:["auto"],name:"right"},{name:"rotate"},{keywords:["normal"],name:"row-gap"},{inherited:!0,name:"ruby-position"},{keywords:["auto"],name:"rx"},{keywords:["auto"],name:"ry"},{name:"scale"},{keywords:["auto","smooth"],name:"scroll-behavior"},{name:"scroll-customization"},{longhands:["scroll-margin-top","scroll-margin-right","scroll-margin-bottom","scroll-margin-left"],name:"scroll-margin"},{longhands:["scroll-margin-block-start","scroll-margin-block-end"],name:"scroll-margin-block"},{name:"scroll-margin-block-end"},{name:"scroll-margin-block-start"},{name:"scroll-margin-bottom"},{longhands:["scroll-margin-inline-start","scroll-margin-inline-end"],name:"scroll-margin-inline"},{name:"scroll-margin-inline-end"},{name:"scroll-margin-inline-start"},{name:"scroll-margin-left"},{name:"scroll-margin-right"},{name:"scroll-margin-top"},{longhands:["scroll-padding-top","scroll-padding-right","scroll-padding-bottom","scroll-padding-left"],name:"scroll-padding"},{longhands:["scroll-padding-block-start","scroll-padding-block-end"],name:"scroll-padding-block"},{keywords:["auto"],name:"scroll-padding-block-end"},{keywords:["auto"],name:"scroll-padding-block-start"},{keywords:["auto"],name:"scroll-padding-bottom"},{longhands:["scroll-padding-inline-start","scroll-padding-inline-end"],name:"scroll-padding-inline"},{keywords:["auto"],name:"scroll-padding-inline-end"},{keywords:["auto"],name:"scroll-padding-inline-start"},{keywords:["auto"],name:"scroll-padding-left"},{keywords:["auto"],name:"scroll-padding-right"},{keywords:["auto"],name:"scroll-padding-top"},{keywords:["none","start","end","center"],name:"scroll-snap-align"},{keywords:["normal","always"],name:"scroll-snap-stop"},{keywords:["none","x","y","block","inline","both","mandatory","proximity"],name:"scroll-snap-type"},{longhands:["scroll-start-block","scroll-start-inline"],name:"scroll-start"},{keywords:["auto","start","end","center","top","bottom","left","right"],name:"scroll-start-block"},{keywords:["auto","start","end","center","top","bottom","left","right"],name:"scroll-start-inline"},{longhands:["scroll-start-target-block","scroll-start-target-inline"],name:"scroll-start-target"},{keywords:["none","auto"],name:"scroll-start-target-block"},{keywords:["none","auto"],name:"scroll-start-target-inline"},{keywords:["none","auto"],name:"scroll-start-target-x"},{keywords:["none","auto"],name:"scroll-start-target-y"},{name:"scroll-start-x"},{name:"scroll-start-y"},{longhands:["scroll-timeline-name","scroll-timeline-axis","scroll-timeline-attachment"],name:"scroll-timeline"},{name:"scroll-timeline-attachment"},{name:"scroll-timeline-axis"},{name:"scroll-timeline-name"},{inherited:!0,keywords:["auto"],name:"scrollbar-color"},{inherited:!1,keywords:["auto","stable","both-edges"],name:"scrollbar-gutter"},{inherited:!1,keywords:["auto","thin","none"],name:"scrollbar-width"},{name:"shape-image-threshold"},{keywords:["none"],name:"shape-margin"},{keywords:["none"],name:"shape-outside"},{inherited:!0,keywords:["auto","optimizespeed","crispedges","geometricprecision"],name:"shape-rendering"},{name:"size"},{name:"size-adjust"},{inherited:!0,keywords:["none","normal","spell-out","digits","literal-punctuation","no-punctuation"],name:"speak"},{name:"speak-as"},{name:"src"},{keywords:["currentcolor"],name:"stop-color"},{name:"stop-opacity"},{inherited:!0,name:"stroke"},{inherited:!0,keywords:["none"],name:"stroke-dasharray"},{inherited:!0,name:"stroke-dashoffset"},{inherited:!0,keywords:["butt","round","square"],name:"stroke-linecap"},{inherited:!0,keywords:["miter","bevel","round"],name:"stroke-linejoin"},{inherited:!0,name:"stroke-miterlimit"},{inherited:!0,name:"stroke-opacity"},{inherited:!0,name:"stroke-width"},{name:"suffix"},{name:"symbols"},{name:"syntax"},{name:"system"},{inherited:!0,name:"tab-size"},{keywords:["auto","fixed"],name:"table-layout"},{inherited:!0,keywords:["left","right","center","justify","-webkit-left","-webkit-right","-webkit-center","start","end"],name:"text-align"},{inherited:!0,keywords:["auto","start","end","left","right","center","justify"],name:"text-align-last"},{inherited:!0,keywords:["start","middle","end"],name:"text-anchor"},{keywords:["none","start","end","both"],name:"text-box-trim"},{inherited:!0,keywords:["none","all"],name:"text-combine-upright"},{longhands:["text-decoration-line","text-decoration-thickness","text-decoration-style","text-decoration-color"],name:"text-decoration"},{keywords:["currentcolor"],name:"text-decoration-color"},{keywords:["none","underline","overline","line-through","blink","spelling-error","grammar-error"],name:"text-decoration-line"},{inherited:!0,keywords:["none","auto"],name:"text-decoration-skip-ink"},{keywords:["solid","double","dotted","dashed","wavy"],name:"text-decoration-style"},{inherited:!0,keywords:["auto","from-font"],name:"text-decoration-thickness"},{inherited:!0,longhands:["text-emphasis-style","text-emphasis-color"],name:"text-emphasis"},{inherited:!0,keywords:["currentcolor"],name:"text-emphasis-color"},{inherited:!0,name:"text-emphasis-position"},{inherited:!0,name:"text-emphasis-style"},{inherited:!0,name:"text-indent"},{inherited:!0,keywords:["sideways","mixed","upright"],name:"text-orientation"},{keywords:["clip","ellipsis"],name:"text-overflow"},{inherited:!0,keywords:["auto","optimizespeed","optimizelegibility","geometricprecision"],name:"text-rendering"},{inherited:!0,keywords:["none"],name:"text-shadow"},{inherited:!0,keywords:["none","auto"],name:"text-size-adjust"},{inherited:!0,keywords:["capitalize","uppercase","lowercase","none","math-auto"],name:"text-transform"},{inherited:!0,keywords:["auto"],name:"text-underline-offset"},{inherited:!0,keywords:["auto","from-font","under","left","right"],name:"text-underline-position"},{inherited:!0,keywords:["wrap","nowrap","balance","pretty"],name:"text-wrap"},{name:"timeline-scope"},{longhands:["toggle-root","toggle-trigger"],name:"toggle"},{keywords:["none"],name:"toggle-group"},{keywords:["none"],name:"toggle-root"},{keywords:["none"],name:"toggle-trigger"},{keywords:["normal"],name:"toggle-visibility"},{keywords:["auto"],name:"top"},{keywords:["auto","none","pan-x","pan-left","pan-right","pan-y","pan-up","pan-down","pinch-zoom","manipulation"],name:"touch-action"},{keywords:["none"],name:"transform"},{keywords:["fill-box","view-box"],name:"transform-box"},{name:"transform-origin"},{keywords:["flat","preserve-3d"],name:"transform-style"},{longhands:["transition-property","transition-duration","transition-timing-function","transition-delay"],name:"transition"},{name:"transition-delay"},{name:"transition-duration"},{keywords:["none"],name:"transition-property"},{keywords:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"],name:"transition-timing-function"},{name:"translate"},{keywords:["normal","embed","bidi-override","isolate","plaintext","isolate-override"],name:"unicode-bidi"},{name:"unicode-range"},{inherited:!0,keywords:["auto","none","text","all","contain"],name:"user-select"},{keywords:["none","non-scaling-stroke"],name:"vector-effect"},{keywords:["baseline","sub","super","text-top","text-bottom","middle"],name:"vertical-align"},{longhands:["view-timeline-name","view-timeline-axis","view-timeline-attachment"],name:"view-timeline"},{name:"view-timeline-attachment"},{name:"view-timeline-axis"},{name:"view-timeline-inset"},{name:"view-timeline-name"},{keywords:["none"],name:"view-transition-name"},{inherited:!0,keywords:["visible","hidden","collapse"],name:"visibility"},{inherited:!0,keywords:["normal","pre","pre-wrap","pre-line","nowrap","break-spaces"],name:"white-space"},{inherited:!0,keywords:["collapse","preserve","preserve-breaks","break-spaces"],name:"white-space-collapse"},{inherited:!0,name:"widows"},{keywords:["auto","fit-content","min-content","max-content"],name:"width"},{keywords:["auto"],name:"will-change"},{inherited:!0,keywords:["normal"],name:"word-boundary-detection"},{inherited:!0,keywords:["normal","break-all","keep-all","break-word"],name:"word-break"},{inherited:!0,keywords:["normal"],name:"word-spacing"},{inherited:!0,keywords:["horizontal-tb","vertical-rl","vertical-lr"],name:"writing-mode"},{name:"x"},{name:"y"},{keywords:["auto"],name:"z-index"},{name:"zoom"}],g={"-webkit-box-align":{values:["stretch","start","center","end","baseline"]},"-webkit-box-decoration-break":{values:["slice","clone"]},"-webkit-box-direction":{values:["normal","reverse"]},"-webkit-box-orient":{values:["horizontal","vertical"]},"-webkit-box-pack":{values:["start","center","end","justify"]},"-webkit-line-break":{values:["auto","loose","normal","strict","after-white-space","anywhere"]},"-webkit-print-color-adjust":{values:["economy","exact"]},"-webkit-rtl-ordering":{values:["logical","visual"]},"-webkit-ruby-position":{values:["before","after"]},"-webkit-text-security":{values:["none","disc","circle","square"]},"-webkit-user-drag":{values:["auto","none","element"]},"-webkit-user-modify":{values:["read-only","read-write","read-write-plaintext-only"]},"accent-color":{values:["auto","currentcolor"]},"alignment-baseline":{values:["auto","baseline","alphabetic","ideographic","middle","central","mathematical","before-edge","text-before-edge","after-edge","text-after-edge","hanging"]},"anchor-default":{values:["none"]},"anchor-name":{values:["none"]},"anchor-scroll":{values:["none"]},"animation-composition":{values:["replace","add","accumulate"]},"animation-direction":{values:["normal","reverse","alternate","alternate-reverse"]},"animation-fill-mode":{values:["none","forwards","backwards","both"]},"animation-iteration-count":{values:["infinite"]},"animation-name":{values:["none"]},"animation-play-state":{values:["running","paused"]},"animation-timeline":{values:["none","auto"]},"animation-timing-function":{values:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"]},"app-region":{values:["none","drag","no-drag"]},"aspect-ratio":{values:["auto"]},"backdrop-filter":{values:["none"]},"backface-visibility":{values:["visible","hidden"]},"background-attachment":{values:["scroll","fixed","local"]},"background-blend-mode":{values:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"]},"background-clip":{values:["border-box","padding-box","content-box"]},"background-color":{values:["currentcolor"]},"background-image":{values:["auto","none"]},"background-origin":{values:["border-box","padding-box","content-box"]},"background-size":{values:["auto","cover","contain"]},"baseline-shift":{values:["baseline","sub","super"]},"baseline-source":{values:["auto","first","last"]},"block-size":{values:["auto"]},"border-bottom-color":{values:["currentcolor"]},"border-bottom-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-bottom-width":{values:["thin","medium","thick"]},"border-collapse":{values:["separate","collapse"]},"border-image-repeat":{values:["stretch","repeat","round","space"]},"border-image-source":{values:["none"]},"border-image-width":{values:["auto"]},"border-left-color":{values:["currentcolor"]},"border-left-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-left-width":{values:["thin","medium","thick"]},"border-right-color":{values:["currentcolor"]},"border-right-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-right-width":{values:["thin","medium","thick"]},"border-style":{values:["none"]},"border-top-color":{values:["currentcolor"]},"border-top-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"border-top-width":{values:["thin","medium","thick"]},bottom:{values:["auto"]},"box-shadow":{values:["none"]},"box-sizing":{values:["content-box","border-box"]},"break-after":{values:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"]},"break-before":{values:["auto","avoid","avoid-column","avoid-page","column","left","page","recto","right","verso"]},"break-inside":{values:["auto","avoid","avoid-column","avoid-page"]},"buffered-rendering":{values:["auto","dynamic","static"]},"caption-side":{values:["top","bottom"]},"caret-color":{values:["auto","currentcolor"]},clear:{values:["none","left","right","both","inline-start","inline-end"]},clip:{values:["auto"]},"clip-path":{values:["none"]},"clip-rule":{values:["nonzero","evenodd"]},color:{values:["currentcolor"]},"color-interpolation":{values:["auto","srgb","linearrgb"]},"color-interpolation-filters":{values:["auto","srgb","linearrgb"]},"color-rendering":{values:["auto","optimizespeed","optimizequality"]},"column-count":{values:["auto"]},"column-fill":{values:["balance","auto"]},"column-gap":{values:["normal"]},"column-rule-color":{values:["currentcolor"]},"column-rule-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"column-rule-width":{values:["thin","medium","thick"]},"column-span":{values:["none","all"]},"column-width":{values:["auto"]},contain:{values:["none","strict","content","size","layout","style","paint","inline-size","block-size"]},"contain-intrinsic-height":{values:["auto","none"]},"contain-intrinsic-width":{values:["auto","none"]},"container-name":{values:["none"]},"container-type":{values:["normal","inline-size","size","sticky"]},"content-visibility":{values:["visible","auto","hidden"]},"counter-increment":{values:["none"]},"counter-reset":{values:["none"]},"counter-set":{values:["none"]},cursor:{values:["auto","default","none","context-menu","help","pointer","progress","wait","cell","crosshair","text","vertical-text","alias","copy","move","no-drop","not-allowed","e-resize","n-resize","ne-resize","nw-resize","s-resize","se-resize","sw-resize","w-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","col-resize","row-resize","all-scroll","zoom-in","zoom-out","grab","grabbing"]},d:{values:["none"]},direction:{values:["ltr","rtl"]},display:{values:["inline","block","list-item","inline-block","table","inline-table","table-row-group","table-header-group","table-footer-group","table-row","table-column-group","table-column","table-cell","table-caption","-webkit-box","-webkit-inline-box","flex","inline-flex","grid","inline-grid","contents","flow-root","none","flow","math"]},"dominant-baseline":{values:["auto","alphabetic","ideographic","middle","central","mathematical","hanging","use-script","no-change","reset-size","text-after-edge","text-before-edge"]},"empty-cells":{values:["show","hide"]},"fill-rule":{values:["nonzero","evenodd"]},filter:{values:["none"]},"flex-basis":{values:["auto","fit-content","min-content","max-content","content"]},"flex-direction":{values:["row","row-reverse","column","column-reverse"]},"flex-wrap":{values:["nowrap","wrap","wrap-reverse"]},float:{values:["none","left","right","inline-start","inline-end"]},"flood-color":{values:["currentcolor"]},"font-feature-settings":{values:["normal"]},"font-kerning":{values:["auto","normal","none"]},"font-optical-sizing":{values:["auto","none"]},"font-palette":{values:["normal","light","dark"]},"font-size":{values:["xx-small","x-small","small","medium","large","x-large","xx-large","xxx-large","larger","smaller","-webkit-xxx-large"]},"font-size-adjust":{values:["none","ex-height","cap-height","ch-width","ic-width"]},"font-stretch":{values:["normal","ultra-condensed","extra-condensed","condensed","semi-condensed","semi-expanded","expanded","extra-expanded","ultra-expanded"]},"font-style":{values:["normal","italic","oblique"]},"font-synthesis-small-caps":{values:["auto","none"]},"font-synthesis-style":{values:["auto","none"]},"font-synthesis-weight":{values:["auto","none"]},"font-variant-alternates":{values:["normal"]},"font-variant-caps":{values:["normal","small-caps","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps"]},"font-variant-east-asian":{values:["normal","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"]},"font-variant-ligatures":{values:["normal","none","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual"]},"font-variant-numeric":{values:["normal","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero"]},"font-variant-position":{values:["normal","sub","super"]},"font-variation-settings":{values:["normal"]},"font-weight":{values:["normal","bold","bolder","lighter"]},"forced-color-adjust":{values:["auto","none","preserve-parent-color"]},"grid-auto-columns":{values:["auto","min-content","max-content"]},"grid-auto-flow":{values:["row","column"]},"grid-auto-rows":{values:["auto","min-content","max-content"]},"grid-column-end":{values:["auto"]},"grid-column-start":{values:["auto"]},"grid-row-end":{values:["auto"]},"grid-row-start":{values:["auto"]},"grid-template-areas":{values:["none"]},"grid-template-columns":{values:["none"]},"grid-template-rows":{values:["none"]},height:{values:["auto","fit-content","min-content","max-content"]},"hyphenate-limit-chars":{values:["auto"]},hyphens:{values:["none","manual","auto"]},"image-rendering":{values:["auto","optimizespeed","optimizequality","-webkit-optimize-contrast","pixelated"]},"initial-letter":{values:["drop","normal","raise"]},"inline-size":{values:["auto"]},isolation:{values:["auto","isolate"]},left:{values:["auto"]},"letter-spacing":{values:["normal"]},"lighting-color":{values:["currentcolor"]},"line-break":{values:["auto","loose","normal","strict","anywhere"]},"line-height":{values:["normal"]},"list-style-image":{values:["none"]},"list-style-position":{values:["outside","inside"]},"list-style-type":{values:["disc","circle","square","disclosure-open","disclosure-closed","decimal","none"]},"margin-block-end":{values:["auto"]},"margin-block-start":{values:["auto"]},"margin-bottom":{values:["auto"]},"margin-inline-end":{values:["auto"]},"margin-inline-start":{values:["auto"]},"margin-left":{values:["auto"]},"margin-right":{values:["auto"]},"margin-top":{values:["auto"]},"marker-end":{values:["none"]},"marker-mid":{values:["none"]},"marker-start":{values:["none"]},"mask-type":{values:["luminance","alpha"]},"math-shift":{values:["normal","compact"]},"math-style":{values:["normal","compact"]},"max-block-size":{values:["none"]},"max-height":{values:["none"]},"max-inline-size":{values:["none"]},"max-width":{values:["none"]},"mix-blend-mode":{values:["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity","plus-lighter"]},"object-fit":{values:["fill","contain","cover","none","scale-down"]},"object-view-box":{values:["none"]},"offset-anchor":{values:["auto"]},"offset-path":{values:["none"]},"offset-position":{values:["auto","normal"]},"offset-rotate":{values:["auto","reverse"]},"origin-trial-test-property":{values:["normal","none"]},"outline-color":{values:["currentcolor"]},"outline-style":{values:["none","hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"outline-width":{values:["thin","medium","thick"]},"overflow-anchor":{values:["visible","none","auto"]},"overflow-clip-margin":{values:["border-box","content-box","padding-box"]},"overflow-wrap":{values:["normal","break-word","anywhere"]},"overflow-x":{values:["visible","hidden","scroll","auto","overlay","clip"]},"overflow-y":{values:["visible","hidden","scroll","auto","overlay","clip"]},overlay:{values:["none","auto"]},"overscroll-behavior-x":{values:["auto","contain","none"]},"overscroll-behavior-y":{values:["auto","contain","none"]},page:{values:["auto"]},"paint-order":{values:["normal","fill","stroke","markers"]},perspective:{values:["none"]},"pointer-events":{values:["none","auto","stroke","fill","painted","visible","visiblestroke","visiblefill","visiblepainted","bounding-box","all"]},position:{values:["static","relative","absolute","fixed","sticky"]},"position-fallback":{values:["none"]},quotes:{values:["auto","none"]},resize:{values:["none","both","horizontal","vertical","block","inline"]},right:{values:["auto"]},"row-gap":{values:["normal"]},rx:{values:["auto"]},ry:{values:["auto"]},"scroll-behavior":{values:["auto","smooth"]},"scroll-padding-block-end":{values:["auto"]},"scroll-padding-block-start":{values:["auto"]},"scroll-padding-bottom":{values:["auto"]},"scroll-padding-inline-end":{values:["auto"]},"scroll-padding-inline-start":{values:["auto"]},"scroll-padding-left":{values:["auto"]},"scroll-padding-right":{values:["auto"]},"scroll-padding-top":{values:["auto"]},"scroll-snap-align":{values:["none","start","end","center"]},"scroll-snap-stop":{values:["normal","always"]},"scroll-snap-type":{values:["none","x","y","block","inline","both","mandatory","proximity"]},"scroll-start-block":{values:["auto","start","end","center","top","bottom","left","right"]},"scroll-start-inline":{values:["auto","start","end","center","top","bottom","left","right"]},"scroll-start-target-block":{values:["none","auto"]},"scroll-start-target-inline":{values:["none","auto"]},"scroll-start-target-x":{values:["none","auto"]},"scroll-start-target-y":{values:["none","auto"]},"scrollbar-color":{values:["auto"]},"scrollbar-gutter":{values:["auto","stable","both-edges"]},"scrollbar-width":{values:["auto","thin","none"]},"shape-margin":{values:["none"]},"shape-outside":{values:["none"]},"shape-rendering":{values:["auto","optimizespeed","crispedges","geometricprecision"]},speak:{values:["none","normal","spell-out","digits","literal-punctuation","no-punctuation"]},"stop-color":{values:["currentcolor"]},"stroke-dasharray":{values:["none"]},"stroke-linecap":{values:["butt","round","square"]},"stroke-linejoin":{values:["miter","bevel","round"]},"table-layout":{values:["auto","fixed"]},"text-align":{values:["left","right","center","justify","-webkit-left","-webkit-right","-webkit-center","start","end"]},"text-align-last":{values:["auto","start","end","left","right","center","justify"]},"text-anchor":{values:["start","middle","end"]},"text-box-trim":{values:["none","start","end","both"]},"text-combine-upright":{values:["none","all"]},"text-decoration-color":{values:["currentcolor"]},"text-decoration-line":{values:["none","underline","overline","line-through","blink","spelling-error","grammar-error"]},"text-decoration-skip-ink":{values:["none","auto"]},"text-decoration-style":{values:["solid","double","dotted","dashed","wavy"]},"text-decoration-thickness":{values:["auto","from-font"]},"text-emphasis-color":{values:["currentcolor"]},"text-orientation":{values:["sideways","mixed","upright"]},"text-overflow":{values:["clip","ellipsis"]},"text-rendering":{values:["auto","optimizespeed","optimizelegibility","geometricprecision"]},"text-shadow":{values:["none"]},"text-size-adjust":{values:["none","auto"]},"text-transform":{values:["capitalize","uppercase","lowercase","none","math-auto"]},"text-underline-offset":{values:["auto"]},"text-underline-position":{values:["auto","from-font","under","left","right"]},"text-wrap":{values:["wrap","nowrap","balance","pretty"]},"toggle-group":{values:["none"]},"toggle-root":{values:["none"]},"toggle-trigger":{values:["none"]},"toggle-visibility":{values:["normal"]},top:{values:["auto"]},"touch-action":{values:["auto","none","pan-x","pan-left","pan-right","pan-y","pan-up","pan-down","pinch-zoom","manipulation"]},transform:{values:["none"]},"transform-box":{values:["fill-box","view-box"]},"transform-style":{values:["flat","preserve-3d"]},"transition-property":{values:["none"]},"transition-timing-function":{values:["linear","ease","ease-in","ease-out","ease-in-out","jump-both","jump-end","jump-none","jump-start","step-start","step-end"]},"unicode-bidi":{values:["normal","embed","bidi-override","isolate","plaintext","isolate-override"]},"user-select":{values:["auto","none","text","all","contain"]},"vector-effect":{values:["none","non-scaling-stroke"]},"vertical-align":{values:["baseline","sub","super","text-top","text-bottom","middle"]},"view-transition-name":{values:["none"]},visibility:{values:["visible","hidden","collapse"]},"white-space":{values:["normal","pre","pre-wrap","pre-line","nowrap","break-spaces"]},"white-space-collapse":{values:["collapse","preserve","preserve-breaks","break-spaces"]},width:{values:["auto","fit-content","min-content","max-content"]},"will-change":{values:["auto"]},"word-boundary-detection":{values:["normal"]},"word-break":{values:["normal","break-all","keep-all","break-word"]},"word-spacing":{values:["normal"]},"writing-mode":{values:["horizontal-tb","vertical-rl","vertical-lr"]},"z-index":{values:["auto"]}},p=new Map([["-epub-caption-side","caption-side"],["-epub-text-combine","-webkit-text-combine"],["-epub-text-emphasis","text-emphasis"],["-epub-text-emphasis-color","text-emphasis-color"],["-epub-text-emphasis-style","text-emphasis-style"],["-epub-text-orientation","-webkit-text-orientation"],["-epub-text-transform","text-transform"],["-epub-word-break","word-break"],["-epub-writing-mode","-webkit-writing-mode"],["-webkit-align-content","align-content"],["-webkit-align-items","align-items"],["-webkit-align-self","align-self"],["-webkit-alternative-animation-delay","-alternative-animation-delay"],["-webkit-alternative-animation-with-delay-start-end","-alternative-animation-with-delay-start-end"],["-webkit-alternative-animation-with-timeline","-alternative-animation-with-timeline"],["-webkit-animation","animation"],["-webkit-animation-delay","animation-delay"],["-webkit-animation-direction","animation-direction"],["-webkit-animation-duration","animation-duration"],["-webkit-animation-fill-mode","animation-fill-mode"],["-webkit-animation-iteration-count","animation-iteration-count"],["-webkit-animation-name","animation-name"],["-webkit-animation-play-state","animation-play-state"],["-webkit-animation-timing-function","animation-timing-function"],["-webkit-app-region","app-region"],["-webkit-appearance","appearance"],["-webkit-backface-visibility","backface-visibility"],["-webkit-background-clip","background-clip"],["-webkit-background-origin","background-origin"],["-webkit-background-size","background-size"],["-webkit-border-after","border-block-end"],["-webkit-border-after-color","border-block-end-color"],["-webkit-border-after-style","border-block-end-style"],["-webkit-border-after-width","border-block-end-width"],["-webkit-border-before","border-block-start"],["-webkit-border-before-color","border-block-start-color"],["-webkit-border-before-style","border-block-start-style"],["-webkit-border-before-width","border-block-start-width"],["-webkit-border-bottom-left-radius","border-bottom-left-radius"],["-webkit-border-bottom-right-radius","border-bottom-right-radius"],["-webkit-border-end","border-inline-end"],["-webkit-border-end-color","border-inline-end-color"],["-webkit-border-end-style","border-inline-end-style"],["-webkit-border-end-width","border-inline-end-width"],["-webkit-border-radius","border-radius"],["-webkit-border-start","border-inline-start"],["-webkit-border-start-color","border-inline-start-color"],["-webkit-border-start-style","border-inline-start-style"],["-webkit-border-start-width","border-inline-start-width"],["-webkit-border-top-left-radius","border-top-left-radius"],["-webkit-border-top-right-radius","border-top-right-radius"],["-webkit-box-shadow","box-shadow"],["-webkit-box-sizing","box-sizing"],["-webkit-clip-path","clip-path"],["-webkit-column-count","column-count"],["-webkit-column-gap","column-gap"],["-webkit-column-rule","column-rule"],["-webkit-column-rule-color","column-rule-color"],["-webkit-column-rule-style","column-rule-style"],["-webkit-column-rule-width","column-rule-width"],["-webkit-column-span","column-span"],["-webkit-column-width","column-width"],["-webkit-columns","columns"],["-webkit-filter","filter"],["-webkit-flex","flex"],["-webkit-flex-basis","flex-basis"],["-webkit-flex-direction","flex-direction"],["-webkit-flex-flow","flex-flow"],["-webkit-flex-grow","flex-grow"],["-webkit-flex-shrink","flex-shrink"],["-webkit-flex-wrap","flex-wrap"],["-webkit-font-feature-settings","font-feature-settings"],["-webkit-hyphenate-character","hyphenate-character"],["-webkit-justify-content","justify-content"],["-webkit-logical-height","block-size"],["-webkit-logical-width","inline-size"],["-webkit-margin-after","margin-block-end"],["-webkit-margin-before","margin-block-start"],["-webkit-margin-end","margin-inline-end"],["-webkit-margin-start","margin-inline-start"],["-webkit-max-logical-height","max-block-size"],["-webkit-max-logical-width","max-inline-size"],["-webkit-min-logical-height","min-block-size"],["-webkit-min-logical-width","min-inline-size"],["-webkit-opacity","opacity"],["-webkit-order","order"],["-webkit-padding-after","padding-block-end"],["-webkit-padding-before","padding-block-start"],["-webkit-padding-end","padding-inline-end"],["-webkit-padding-start","padding-inline-start"],["-webkit-perspective","perspective"],["-webkit-perspective-origin","perspective-origin"],["-webkit-shape-image-threshold","shape-image-threshold"],["-webkit-shape-margin","shape-margin"],["-webkit-shape-outside","shape-outside"],["-webkit-text-emphasis","text-emphasis"],["-webkit-text-emphasis-color","text-emphasis-color"],["-webkit-text-emphasis-position","text-emphasis-position"],["-webkit-text-emphasis-style","text-emphasis-style"],["-webkit-text-size-adjust","text-size-adjust"],["-webkit-transform","transform"],["-webkit-transform-origin","transform-origin"],["-webkit-transform-style","transform-style"],["-webkit-transition","transition"],["-webkit-transition-delay","transition-delay"],["-webkit-transition-duration","transition-duration"],["-webkit-transition-property","transition-property"],["-webkit-transition-timing-function","transition-timing-function"],["-webkit-user-select","user-select"],["word-wrap","overflow-wrap"]]);class m{#t;#n;#r;#s;#i;#a;#o;#l;#d;#c;constructor(e,n){this.#t=[],this.#n=new Map,this.#r=new Map,this.#s=new Set,this.#i=new Set,this.#a=new Map,this.#o=n;for(let t=0;tCSS.supports(e,t))).sort(m.sortPrefixesToEnd).map((t=>`${e}: ${t}`));this.isSVGProperty(e)||this.#d.push(...t),this.#c.push(...t)}}static sortPrefixesToEnd(e,t){const n=e.startsWith("-webkit-"),r=t.startsWith("-webkit-");return n&&!r?1:!n&&r||et?1:0}allProperties(){return this.#t}aliasesFor(){return this.#o}nameValuePresets(e){return e?this.#c:this.#d}isSVGProperty(e){return e=e.toLowerCase(),this.#i.has(e)}getLonghands(e){return this.#n.get(e)||null}getShorthands(e){return this.#r.get(e)||null}isColorAwareProperty(e){return R.has(e.toLowerCase())||this.isCustomProperty(e.toLowerCase())}isFontFamilyProperty(e){return"font-family"===e.toLowerCase()}isAngleAwareProperty(e){const t=e.toLowerCase();return R.has(t)||x.has(t)}isGridAreaDefiningProperty(e){return"grid"===(e=e.toLowerCase())||"grid-template"===e||"grid-template-areas"===e}isLengthProperty(e){return"line-height"!==(e=e.toLowerCase())&&(w.has(e)||e.startsWith("margin")||e.startsWith("padding")||-1!==e.indexOf("width")||-1!==e.indexOf("height"))}isBezierAwareProperty(e){return e=e.toLowerCase(),C.has(e)||this.isCustomProperty(e)}isFontAwareProperty(e){return e=e.toLowerCase(),T.has(e)||this.isCustomProperty(e)}isCustomProperty(e){return e.startsWith("--")}isShadowProperty(e){return"box-shadow"===(e=e.toLowerCase())||"text-shadow"===e||"-webkit-box-shadow"===e}isStringProperty(e){return"content"===(e=e.toLowerCase())}canonicalPropertyName(e){if(this.isCustomProperty(e))return e;e=e.toLowerCase();const t=this.#o.get(e);if(t)return t;if(!e||e.length<9||"-"!==e.charAt(0))return e;const n=e.match(/(?:-webkit-)(.+)/);return n&&this.#l.has(n[1])?n[1]:e}isCSSPropertyName(e){return!!((e=e.toLowerCase()).startsWith("--")&&e.length>2||e.startsWith("-moz-")||e.startsWith("-ms-")||e.startsWith("-o-")||e.startsWith("-webkit-"))||this.#l.has(e)}isPropertyInherited(e){return(e=e.toLowerCase()).startsWith("--")||this.#s.has(this.canonicalPropertyName(e))||this.#s.has(e)}specificPropertyValues(e){const t=e.replace(/^-webkit-/,""),n=this.#a;let r=n.get(e)||n.get(t);if(!r){r=[];for(const t of L)CSS.supports(e,t)&&r.push(t);n.set(e,r)}return r}getPropertyValues(t){const n=["inherit","initial","revert","unset"];if(t=t.toLowerCase(),n.push(...this.specificPropertyValues(t)),this.isColorAwareProperty(t)){n.push("currentColor");for(const t of e.Color.Nicknames.keys())n.push(t)}return n.sort(m.sortPrefixesToEnd)}propertyUsageWeight(e){return P.get(e)||P.get(this.canonicalPropertyName(e))||0}getValuePreset(e,t){const n=S.get(e);let r=n?n.get(t):null;if(!r)return null;let s=r.length,i=r.length;return r&&(s=r.indexOf("|"),i=r.lastIndexOf("|"),i=s===i?i:i-1,r=r.replace(/\|/g,"")),{text:r,startColumn:s,endColumn:i}}isHighlightPseudoType(e){return"highlight"===e||"selection"===e||"target-text"===e||"grammar-error"===e||"spelling-error"===e}}const f=/(var\(\s*--.*?\))/g,b=/((?:\[[\w\- ]+\]\s*)*(?:"[^"]+"|'[^']+'))[^'"\[]*\[?[^'"\[]*/;let y=null;function v(){if(!y){y=new m(u,p)}return y}const I=new Map([["linear-gradient","linear-gradient(|45deg, black, transparent|)"],["radial-gradient","radial-gradient(|black, transparent|)"],["repeating-linear-gradient","repeating-linear-gradient(|45deg, black, transparent 100px|)"],["repeating-radial-gradient","repeating-radial-gradient(|black, transparent 100px|)"],["url","url(||)"]]),k=new Map([["blur","blur(|1px|)"],["brightness","brightness(|0.5|)"],["contrast","contrast(|0.5|)"],["drop-shadow","drop-shadow(|2px 4px 6px black|)"],["grayscale","grayscale(|1|)"],["hue-rotate","hue-rotate(|45deg|)"],["invert","invert(|1|)"],["opacity","opacity(|0.5|)"],["saturate","saturate(|0.5|)"],["sepia","sepia(|1|)"],["url","url(||)"]]),S=new Map([["filter",k],["backdrop-filter",k],["background",I],["background-image",I],["-webkit-mask-image",I],["transform",new Map([["scale","scale(|1.5|)"],["scaleX","scaleX(|1.5|)"],["scaleY","scaleY(|1.5|)"],["scale3d","scale3d(|1.5, 1.5, 1.5|)"],["rotate","rotate(|45deg|)"],["rotateX","rotateX(|45deg|)"],["rotateY","rotateY(|45deg|)"],["rotateZ","rotateZ(|45deg|)"],["rotate3d","rotate3d(|1, 1, 1, 45deg|)"],["skew","skew(|10deg, 10deg|)"],["skewX","skewX(|10deg|)"],["skewY","skewY(|10deg|)"],["translate","translate(|10px, 10px|)"],["translateX","translateX(|10px|)"],["translateY","translateY(|10px|)"],["translateZ","translateZ(|10px|)"],["translate3d","translate3d(|10px, 10px, 10px|)"],["matrix","matrix(|1, 0, 0, 1, 0, 0|)"],["matrix3d","matrix3d(|1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1|)"],["perspective","perspective(|10px|)"]])]]),w=new Set(["background-position","border-spacing","bottom","font-size","height","left","letter-spacing","max-height","max-width","min-height","min-width","right","text-indent","top","width","word-spacing","grid-row-gap","grid-column-gap","row-gap"]),C=new Set(["animation","animation-timing-function","transition","transition-timing-function","-webkit-animation","-webkit-animation-timing-function","-webkit-transition","-webkit-transition-timing-function"]),T=new Set(["font-size","line-height","font-weight","font-family","letter-spacing"]),R=new Set(["accent-color","background","background-color","background-image","border","border-color","border-image","border-image-source","border-bottom","border-bottom-color","border-left","border-left-color","border-right","border-right-color","border-top","border-top-color","box-shadow","caret-color","color","column-rule","column-rule-color","content","fill","list-style-image","outline","outline-color","stop-color","stroke","text-decoration-color","text-shadow","-webkit-border-after","-webkit-border-after-color","-webkit-border-before","-webkit-border-before-color","-webkit-border-end","-webkit-border-end-color","-webkit-border-start","-webkit-border-start-color","-webkit-box-reflect","-webkit-box-shadow","-webkit-column-rule-color","-webkit-mask","-webkit-mask-box-image","-webkit-mask-box-image-source","-webkit-mask-image","-webkit-tap-highlight-color","-webkit-text-decoration-color","-webkit-text-emphasis","-webkit-text-emphasis-color","-webkit-text-fill-color","-webkit-text-stroke","-webkit-text-stroke-color"]),x=new Set(["-webkit-border-image","transform","-webkit-transform","rotate","filter","-webkit-filter","backdrop-filter","offset","offset-rotate","font-style"]),M={"background-repeat":{values:["repeat","repeat-x","repeat-y","no-repeat","space","round"]},content:{values:["normal","close-quote","no-close-quote","no-open-quote","open-quote"]},"baseline-shift":{values:["baseline"]},"max-height":{values:["min-content","max-content","-webkit-fill-available","fit-content"]},color:{values:["black"]},"background-color":{values:["white"]},"box-shadow":{values:["inset"]},"text-shadow":{values:["0 0 black"]},"-webkit-writing-mode":{values:["horizontal-tb","vertical-rl","vertical-lr"]},"writing-mode":{values:["lr","rl","tb","lr-tb","rl-tb","tb-rl"]},"page-break-inside":{values:["avoid"]},cursor:{values:["-webkit-zoom-in","-webkit-zoom-out","-webkit-grab","-webkit-grabbing"]},"border-width":{values:["medium","thick","thin"]},"border-style":{values:["hidden","inset","groove","ridge","outset","dotted","dashed","solid","double"]},size:{values:["a3","a4","a5","b4","b5","landscape","ledger","legal","letter","portrait"]},overflow:{values:["hidden","visible","overlay","scroll"]},"overscroll-behavior":{values:["contain"]},"text-rendering":{values:["optimizeSpeed","optimizeLegibility","geometricPrecision"]},"text-align":{values:["-webkit-auto","-webkit-match-parent"]},"clip-path":{values:["circle","ellipse","inset","polygon","url"]},"color-interpolation":{values:["sRGB","linearRGB"]},"word-wrap":{values:["normal","break-word"]},"font-weight":{values:["100","200","300","400","500","600","700","800","900"]},"-webkit-text-emphasis":{values:["circle","filled","open","dot","double-circle","triangle","sesame"]},"color-rendering":{values:["optimizeSpeed","optimizeQuality"]},"-webkit-text-combine":{values:["horizontal"]},"text-orientation":{values:["sideways-right"]},outline:{values:["inset","groove","ridge","outset","dotted","dashed","solid","double","medium","thick","thin"]},font:{values:["caption","icon","menu","message-box","small-caption","-webkit-mini-control","-webkit-small-control","-webkit-control","status-bar"]},"dominant-baseline":{values:["text-before-edge","text-after-edge","use-script","no-change","reset-size"]},"-webkit-text-emphasis-position":{values:["over","under"]},"alignment-baseline":{values:["before-edge","after-edge","text-before-edge","text-after-edge","hanging"]},"page-break-before":{values:["left","right","always","avoid"]},"border-image":{values:["repeat","stretch","space","round"]},"text-decoration":{values:["blink","line-through","overline","underline","wavy","double","solid","dashed","dotted"]},"font-family":{values:["serif","sans-serif","cursive","fantasy","monospace","system-ui","emoji","math","fangsong","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","-webkit-body"]},zoom:{values:["normal"]},"max-width":{values:["min-content","max-content","-webkit-fill-available","fit-content"]},"-webkit-font-smoothing":{values:["antialiased","subpixel-antialiased"]},border:{values:["hidden","inset","groove","ridge","outset","dotted","dashed","solid","double","medium","thick","thin"]},"font-variant":{values:["small-caps","normal","common-ligatures","no-common-ligatures","discretionary-ligatures","no-discretionary-ligatures","historical-ligatures","no-historical-ligatures","contextual","no-contextual","all-small-caps","petite-caps","all-petite-caps","unicase","titling-caps","lining-nums","oldstyle-nums","proportional-nums","tabular-nums","diagonal-fractions","stacked-fractions","ordinal","slashed-zero","jis78","jis83","jis90","jis04","simplified","traditional","full-width","proportional-width","ruby"]},"vertical-align":{values:["top","bottom","-webkit-baseline-middle"]},"page-break-after":{values:["left","right","always","avoid"]},"-webkit-text-emphasis-style":{values:["circle","filled","open","dot","double-circle","triangle","sesame"]},transform:{values:["scale","scaleX","scaleY","scale3d","rotate","rotateX","rotateY","rotateZ","rotate3d","skew","skewX","skewY","translate","translateX","translateY","translateZ","translate3d","matrix","matrix3d","perspective"]},"align-content":{values:["normal","baseline","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end"]},"justify-content":{values:["normal","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end","left","right"]},"place-content":{values:["normal","space-between","space-around","space-evenly","stretch","center","start","end","flex-start","flex-end","baseline"]},"align-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"justify-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end","left","right","legacy"]},"place-items":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"align-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"justify-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end","left","right"]},"place-self":{values:["normal","stretch","baseline","center","start","end","self-start","self-end","flex-start","flex-end"]},"perspective-origin":{values:["left","center","right","top","bottom"]},"transform-origin":{values:["left","center","right","top","bottom"]},"transition-timing-function":{values:["cubic-bezier","steps"]},"animation-timing-function":{values:["cubic-bezier","steps"]},"-webkit-backface-visibility":{values:["visible","hidden"]},"-webkit-column-break-after":{values:["always","avoid"]},"-webkit-column-break-before":{values:["always","avoid"]},"-webkit-column-break-inside":{values:["avoid"]},"-webkit-column-span":{values:["all"]},"-webkit-column-gap":{values:["normal"]},filter:{values:["url","blur","brightness","contrast","drop-shadow","grayscale","hue-rotate","invert","opacity","saturate","sepia"]},"backdrop-filter":{values:["url","blur","brightness","contrast","drop-shadow","grayscale","hue-rotate","invert","opacity","saturate","sepia"]},"mix-blend-mode":{values:["unset"]},"background-blend-mode":{values:["unset"]},"grid-template-columns":{values:["min-content","max-content"]},"grid-template-rows":{values:["min-content","max-content"]},"grid-auto-flow":{values:["dense"]},background:{values:["repeat","repeat-x","repeat-y","no-repeat","top","bottom","left","right","center","fixed","local","scroll","space","round","border-box","content-box","padding-box","linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"background-image":{values:["linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"background-position":{values:["top","bottom","left","right","center"]},"background-position-x":{values:["left","right","center"]},"background-position-y":{values:["top","bottom","center"]},"background-repeat-x":{values:["repeat","no-repeat"]},"background-repeat-y":{values:["repeat","no-repeat"]},"border-bottom":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-left":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-right":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"border-top":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"buffered-rendering":{values:["static","dynamic"]},"color-interpolation-filters":{values:["srgb","linearrgb"]},"column-rule":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"flex-flow":{values:["nowrap","row","row-reverse","column","column-reverse","wrap","wrap-reverse"]},height:{values:["-webkit-fill-available"]},"inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"list-style":{values:["outside","inside","disc","circle","square","decimal","decimal-leading-zero","arabic-indic","bengali","cambodian","khmer","devanagari","gujarati","gurmukhi","kannada","lao","malayalam","mongolian","myanmar","oriya","persian","urdu","telugu","tibetan","thai","lower-roman","upper-roman","lower-greek","lower-alpha","lower-latin","upper-alpha","upper-latin","cjk-earthly-branch","cjk-heavenly-stem","ethiopic-halehame","ethiopic-halehame-am","ethiopic-halehame-ti-er","ethiopic-halehame-ti-et","hangul","hangul-consonant","korean-hangul-formal","korean-hanja-formal","korean-hanja-informal","hebrew","armenian","lower-armenian","upper-armenian","georgian","cjk-ideographic","simp-chinese-formal","simp-chinese-informal","trad-chinese-formal","trad-chinese-informal","hiragana","katakana","hiragana-iroha","katakana-iroha"]},"max-block-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"max-inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-block-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-inline-size":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"min-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"object-position":{values:["top","bottom","left","right","center"]},"shape-outside":{values:["border-box","content-box","padding-box","margin-box"]},"-webkit-appearance":{values:["checkbox","radio","push-button","square-button","button","inner-spin-button","listbox","media-slider","media-sliderthumb","media-volume-slider","media-volume-sliderthumb","menulist","menulist-button","meter","progress-bar","slider-horizontal","slider-vertical","sliderthumb-horizontal","sliderthumb-vertical","searchfield","searchfield-cancel-button","textfield","textarea"]},"-webkit-border-after":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-after-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-after-width":{values:["medium","thick","thin"]},"-webkit-border-before":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-before-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-before-width":{values:["medium","thick","thin"]},"-webkit-border-end":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-end-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-end-width":{values:["medium","thick","thin"]},"-webkit-border-start":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double","medium","thick","thin"]},"-webkit-border-start-style":{values:["hidden","inset","groove","outset","ridge","dotted","dashed","solid","double"]},"-webkit-border-start-width":{values:["medium","thick","thin"]},"-webkit-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-margin-collapse":{values:["collapse","separate","discard"]},"-webkit-mask-box-image":{values:["repeat","stretch","space","round"]},"-webkit-mask-box-image-repeat":{values:["repeat","stretch","space","round"]},"-webkit-mask-clip":{values:["text","border","border-box","content","content-box","padding","padding-box"]},"-webkit-mask-composite":{values:["clear","copy","source-over","source-in","source-out","source-atop","destination-over","destination-in","destination-out","destination-atop","xor","plus-lighter"]},"-webkit-mask-image":{values:["linear-gradient","radial-gradient","repeating-linear-gradient","repeating-radial-gradient","url"]},"-webkit-mask-origin":{values:["border","border-box","content","content-box","padding","padding-box"]},"-webkit-mask-position":{values:["top","bottom","left","right","center"]},"-webkit-mask-position-x":{values:["left","right","center"]},"-webkit-mask-position-y":{values:["top","bottom","center"]},"-webkit-mask-repeat":{values:["repeat","repeat-x","repeat-y","no-repeat","space","round"]},"-webkit-mask-size":{values:["contain","cover"]},"-webkit-max-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-max-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-min-logical-height":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-min-logical-width":{values:["-webkit-fill-available","min-content","max-content","fit-content"]},"-webkit-perspective-origin-x":{values:["left","right","center"]},"-webkit-perspective-origin-y":{values:["top","bottom","center"]},"-webkit-text-decorations-in-effect":{values:["blink","line-through","overline","underline"]},"-webkit-text-stroke":{values:["medium","thick","thin"]},"-webkit-text-stroke-width":{values:["medium","thick","thin"]},"-webkit-transform-origin-x":{values:["left","right","center"]},"-webkit-transform-origin-y":{values:["top","bottom","center"]},width:{values:["-webkit-fill-available"]}},P=new Map([["align-content",57],["align-items",129],["align-self",55],["animation",175],["animation-delay",114],["animation-direction",113],["animation-duration",137],["animation-fill-mode",132],["animation-iteration-count",124],["animation-name",139],["animation-play-state",104],["animation-timing-function",141],["backface-visibility",123],["background",260],["background-attachment",119],["background-clip",165],["background-color",259],["background-image",246],["background-origin",107],["background-position",237],["background-position-x",108],["background-position-y",93],["background-repeat",234],["background-size",203],["border",263],["border-bottom",233],["border-bottom-color",190],["border-bottom-left-radius",186],["border-bottom-right-radius",185],["border-bottom-style",150],["border-bottom-width",179],["border-collapse",209],["border-color",226],["border-image",89],["border-image-outset",50],["border-image-repeat",49],["border-image-slice",58],["border-image-source",32],["border-image-width",52],["border-left",221],["border-left-color",174],["border-left-style",142],["border-left-width",172],["border-radius",224],["border-right",223],["border-right-color",182],["border-right-style",130],["border-right-width",178],["border-spacing",198],["border-style",206],["border-top",231],["border-top-color",192],["border-top-left-radius",187],["border-top-right-radius",189],["border-top-style",152],["border-top-width",180],["border-width",214],["bottom",227],["box-shadow",213],["box-sizing",216],["caption-side",96],["clear",229],["clip",173],["clip-rule",5],["color",256],["content",219],["counter-increment",111],["counter-reset",110],["cursor",250],["direction",176],["display",262],["empty-cells",99],["fill",140],["fill-opacity",82],["fill-rule",22],["filter",160],["flex",133],["flex-basis",66],["flex-direction",85],["flex-flow",94],["flex-grow",112],["flex-shrink",61],["flex-wrap",68],["float",252],["font",211],["font-family",254],["font-kerning",18],["font-size",264],["font-stretch",77],["font-style",220],["font-variant",161],["font-weight",257],["height",266],["image-rendering",90],["justify-content",127],["left",248],["letter-spacing",188],["line-height",244],["list-style",215],["list-style-image",145],["list-style-position",149],["list-style-type",199],["margin",267],["margin-bottom",241],["margin-left",243],["margin-right",238],["margin-top",253],["mask",20],["max-height",205],["max-width",225],["min-height",217],["min-width",218],["object-fit",33],["opacity",251],["order",117],["orphans",146],["outline",222],["outline-color",153],["outline-offset",147],["outline-style",151],["outline-width",148],["overflow",255],["overflow-wrap",105],["overflow-x",184],["overflow-y",196],["padding",265],["padding-bottom",230],["padding-left",235],["padding-right",232],["padding-top",240],["page",8],["page-break-after",120],["page-break-before",69],["page-break-inside",121],["perspective",92],["perspective-origin",103],["pointer-events",183],["position",261],["quotes",158],["resize",168],["right",245],["shape-rendering",38],["size",64],["speak",118],["src",170],["stop-color",42],["stop-opacity",31],["stroke",98],["stroke-dasharray",36],["stroke-dashoffset",3],["stroke-linecap",30],["stroke-linejoin",21],["stroke-miterlimit",12],["stroke-opacity",34],["stroke-width",87],["table-layout",171],["tab-size",46],["text-align",260],["text-anchor",35],["text-decoration",247],["text-indent",207],["text-overflow",204],["text-rendering",155],["text-shadow",208],["text-transform",202],["top",258],["touch-action",80],["transform",181],["transform-origin",162],["transform-style",86],["transition",193],["transition-delay",134],["transition-duration",135],["transition-property",131],["transition-timing-function",122],["unicode-bidi",156],["unicode-range",136],["vertical-align",236],["visibility",242],["-webkit-appearance",191],["-webkit-backface-visibility",154],["-webkit-background-clip",164],["-webkit-background-origin",40],["-webkit-background-size",163],["-webkit-border-end",9],["-webkit-border-horizontal-spacing",81],["-webkit-border-image",75],["-webkit-border-radius",212],["-webkit-border-start",10],["-webkit-border-start-color",16],["-webkit-border-start-width",13],["-webkit-border-vertical-spacing",43],["-webkit-box-align",101],["-webkit-box-direction",51],["-webkit-box-flex",128],["-webkit-box-ordinal-group",91],["-webkit-box-orient",144],["-webkit-box-pack",106],["-webkit-box-reflect",39],["-webkit-box-shadow",210],["-webkit-column-break-inside",60],["-webkit-column-count",84],["-webkit-column-gap",76],["-webkit-column-rule",25],["-webkit-column-rule-color",23],["-webkit-columns",44],["-webkit-column-span",29],["-webkit-column-width",47],["-webkit-filter",159],["-webkit-font-feature-settings",59],["-webkit-font-smoothing",177],["-webkit-highlight",1],["-webkit-line-break",45],["-webkit-line-clamp",126],["-webkit-margin-after",67],["-webkit-margin-before",70],["-webkit-margin-collapse",14],["-webkit-margin-end",65],["-webkit-margin-start",100],["-webkit-margin-top-collapse",78],["-webkit-mask",19],["-webkit-mask-box-image",72],["-webkit-mask-image",88],["-webkit-mask-position",54],["-webkit-mask-repeat",63],["-webkit-mask-size",79],["-webkit-padding-after",15],["-webkit-padding-before",28],["-webkit-padding-end",48],["-webkit-padding-start",73],["-webkit-print-color-adjust",83],["-webkit-rtl-ordering",7],["-webkit-tap-highlight-color",169],["-webkit-text-emphasis-color",11],["-webkit-text-fill-color",71],["-webkit-text-security",17],["-webkit-text-stroke",56],["-webkit-text-stroke-color",37],["-webkit-text-stroke-width",53],["-webkit-user-drag",95],["-webkit-user-modify",62],["-webkit-user-select",194],["-webkit-writing-mode",4],["white-space",228],["widows",115],["width",268],["will-change",74],["word-break",166],["word-spacing",157],["word-wrap",197],["writing-mode",41],["z-index",239],["zoom",200]]),L=["auto","none"];var E=Object.freeze({__proto__:null,CSSMetadata:m,VariableRegex:f,CustomVariableRegex:/(var\(*--[\w\d]+-([\w]+-[\w]+)\))/g,URLRegex:/url\(\s*('.+?'|".+?"|[^)]+)\s*\)/g,GridAreaRowRegex:b,cssMetadata:v});class A{callFrame;callUID;self;total;id;parent;children;functionName;depth;deoptReason;#h;constructor(e,t){this.callFrame=e,this.callUID=`${e.functionName}@${e.scriptId}:${e.lineNumber}:${e.columnNumber}`,this.self=0,this.total=0,this.id=0,this.functionName=e.functionName,this.parent=null,this.children=[],this.#h=t}get scriptId(){return String(this.callFrame.scriptId)}get url(){return this.callFrame.url}get lineNumber(){return this.callFrame.lineNumber}get columnNumber(){return this.callFrame.columnNumber}setFunctionName(e){null!==e&&(this.functionName=e)}target(){return this.#h}}class O{#e;root;total;maxDepth;constructor(e){this.#e=e||null}initialize(e){this.root=e,this.assignDepthsAndParents(),this.total=this.calculateTotals(this.root)}assignDepthsAndParents(){const e=this.root;e.depth=-1,e.parent=null,this.maxDepth=0;const t=[e];for(;t.length;){const e=t.pop(),n=e.depth+1;n>this.maxDepth&&(this.maxDepth=n);const r=e.children;for(const s of r)s.depth=n,s.parent=e,s.children.length&&t.push(s)}}calculateTotals(e){const t=[e],n=[];for(;t.length;){const e=t.pop();e.total=e.self,n.push(e),t.push(...e.children)}for(;n.length>1;){const e=n.pop();e.parent&&(e.parent.total+=e.total)}return e.total}target(){return this.#e}}var N=Object.freeze({__proto__:null,ProfileNode:A,ProfileTreeModel:O});class F{#u;#g;#p;#m;#f;#b;#y;constructor(e,t,n,r){this.#u=e,this.#g=t,this.#p=n,this.#m={},this.#f=0,this.#b=r||"Medium",this.#y=null}static fromProtocolCookie(e){const t=new F(e.name,e.value,null,e.priority);return t.addAttribute("domain",e.domain),t.addAttribute("path",e.path),e.expires&&t.addAttribute("expires",1e3*e.expires),e.httpOnly&&t.addAttribute("httpOnly"),e.secure&&t.addAttribute("secure"),e.sameSite&&t.addAttribute("sameSite",e.sameSite),"sourcePort"in e&&t.addAttribute("sourcePort",e.sourcePort),"sourceScheme"in e&&t.addAttribute("sourceScheme",e.sourceScheme),"partitionKey"in e&&t.addAttribute("partitionKey",e.partitionKey),"partitionKeyOpaque"in e&&t.addAttribute("partitionKey",""),t.setSize(e.size),t}key(){return(this.domain()||"-")+" "+this.name()+" "+(this.path()||"-")}name(){return this.#u}value(){return this.#g}type(){return this.#p}httpOnly(){return"httponly"in this.#m}secure(){return"secure"in this.#m}sameSite(){return this.#m.samesite}partitionKey(){return this.#m.partitionkey}setPartitionKey(e){this.addAttribute("partitionKey",e)}partitionKeyOpaque(){return""===this.#m.partitionkey}setPartitionKeyOpaque(){this.addAttribute("partitionKey","")}priority(){return this.#b}session(){return!("expires"in this.#m||"max-age"in this.#m)}path(){return this.#m.path}domain(){return this.#m.domain}expires(){return this.#m.expires}maxAge(){return this.#m["max-age"]}sourcePort(){return this.#m.sourceport}sourceScheme(){return this.#m.sourcescheme}size(){return this.#f}url(){if(!this.domain()||!this.path())return null;let e="";const t=this.sourcePort();return t&&80!==t&&443!==t&&(e=`:${this.sourcePort()}`),(this.secure()?"https://":"http://")+this.domain()+e+this.path()}setSize(e){this.#f=e}expiresDate(e){return this.maxAge()?new Date(e.getTime()+1e3*this.maxAge()):this.expires()?new Date(this.expires()):null}addAttribute(e,t){const n=e.toLowerCase();if("priority"===n)this.#b=t;else this.#m[n]=t}setCookieLine(e){this.#y=e}getCookieLine(){return this.#y}matchesSecurityOrigin(e){const t=new URL(e).hostname;return F.isDomainMatch(this.domain(),t)}static isDomainMatch(e,t){return t===e||!(!e||"."!==e[0])&&(e.substr(1)===t||t.length>e.length&&t.endsWith(e))}}var B,D;!function(e){e[e.Request=0]="Request",e[e.Response=1]="Response"}(B||(B={})),function(e){e.Name="name",e.Value="value",e.Size="size",e.Domain="domain",e.Path="path",e.Expires="expires",e.HttpOnly="httpOnly",e.Secure="secure",e.SameSite="sameSite",e.SourceScheme="sourceScheme",e.SourcePort="sourcePort",e.Priority="priority",e.PartitionKey="partitionKey"}(D||(D={}));var U=Object.freeze({__proto__:null,Cookie:F,get Type(){return B},get Attributes(){return D}});class H{#v;#I;#k;#S;#w;#C;#T;constructor(e){e&&(this.#v=e.toLowerCase().replace(/^\./,"")),this.#I=[],this.#S=0}static parseSetCookie(e,t){return new H(t).parseSetCookie(e)}cookies(){return this.#I}parseSetCookie(e){if(!this.initialize(e))return null;for(let e=this.extractKeyValue();e;e=this.extractKeyValue())this.#w?this.#w.addAttribute(e.key,e.value):this.addCookie(e,B.Response),this.advanceAndCheckCookieDelimiter()&&this.flushCookie();return this.flushCookie(),this.#I}initialize(e){return this.#k=e,"string"==typeof e&&(this.#I=[],this.#w=null,this.#C="",this.#S=this.#k.length,!0)}flushCookie(){this.#w&&(this.#w.setSize(this.#S-this.#k.length-this.#T),this.#w.setCookieLine(this.#C.replace("\n",""))),this.#w=null,this.#C=""}extractKeyValue(){if(!this.#k||!this.#k.length)return null;const e=/^[ \t]*([^=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this.#k);if(!e)return console.error("Failed parsing cookie header before: "+this.#k),null;const t=new q(e[1]&&e[1].trim(),e[2]&&e[2].trim(),this.#S-this.#k.length);return this.#C+=e[0],this.#k=this.#k.slice(e[0].length),t}advanceAndCheckCookieDelimiter(){if(!this.#k)return!1;const e=/^\s*[\n;]\s*/.exec(this.#k);return!!e&&(this.#C+=e[0],this.#k=this.#k.slice(e[0].length),null!==e[0].match("\n"))}addCookie(e,t){this.#w&&this.#w.setSize(e.position-this.#T),this.#w="string"==typeof e.value?new F(e.key,e.value,t):new F("",e.key,t),this.#v&&this.#w.addAttribute("domain",this.#v),this.#T=e.position,this.#I.push(this.#w)}}class q{key;value;position;constructor(e,t,n){this.key=e,this.value=t,this.position=n}}var _,z,j=Object.freeze({__proto__:null,CookieParser:H});class W extends a.InspectorBackend.TargetBase{#R;#u;#x;#M;#P;#p;#L;#E;#A;#O;#N;#F;constructor(e,n,r,s,i,a,o,l,d){switch(super(s===_.Node,i,a,l),this.#R=e,this.#u=r,this.#x=t.DevToolsPath.EmptyUrlString,this.#M="",this.#P=0,s){case _.Frame:this.#P=z.Browser|z.Storage|z.DOM|z.JS|z.Log|z.Network|z.Target|z.Tracing|z.Emulation|z.Input|z.Inspector|z.Audits|z.WebAuthn|z.IO|z.Media,i?.type()!==_.Frame&&(this.#P|=z.DeviceEmulation|z.ScreenCapture|z.Security|z.ServiceWorker,d?.url.startsWith("chrome-extension://")&&(this.#P&=~z.Security));break;case _.ServiceWorker:this.#P=z.JS|z.Log|z.Network|z.Target|z.Inspector|z.IO,i?.type()!==_.Frame&&(this.#P|=z.Browser);break;case _.SharedWorker:this.#P=z.JS|z.Log|z.Network|z.Target|z.IO|z.Media|z.Inspector;break;case _.Worker:this.#P=z.JS|z.Log|z.Network|z.Target|z.IO|z.Media|z.Emulation;break;case _.Node:this.#P=z.JS;break;case _.AuctionWorklet:this.#P=z.JS|z.EventBreakpoints;break;case _.Browser:this.#P=z.Target|z.IO;break;case _.Tab:this.#P=z.Target}this.#p=s,this.#L=i,this.#E=n,this.#A=new Map,this.#O=o,this.#N=d}createModels(e){this.#F=!0;const t=Array.from(c.registeredModels.entries());for(const[e,n]of t)n.early&&this.model(e);for(const[n,r]of t)(r.autostart||e.has(n))&&this.model(n);this.#F=!1}id(){return this.#E}name(){return this.#u||this.#M}setName(e){this.#u!==e&&(this.#u=e,this.#R.onNameChange(this))}type(){return this.#p}markAsNodeJSForTest(){super.markAsNodeJSForTest(),this.#p=_.Node}targetManager(){return this.#R}hasAllCapabilities(e){return(this.#P&e)===e}decorateLabel(e){return this.#p===_.Worker||this.#p===_.ServiceWorker?"⚙ "+e:e}parentTarget(){return this.#L}outermostTarget(){let e=null,t=this;do{t.type()!==_.Tab&&t.type()!==_.Browser&&(e=t),t=t.parentTarget()}while(t);return e}dispose(e){super.dispose(e),this.#R.removeTarget(this);for(const e of this.#A.values())e.dispose()}model(e){if(!this.#A.get(e)){const t=c.registeredModels.get(e);if(void 0===t)throw"Model class is not registered @"+(new Error).stack;if((this.#P&t.capabilities)===t.capabilities){const t=new e(this);this.#A.set(e,t),this.#F||this.#R.modelAdded(this,e,t,this.#R.isInScope(this))}}return this.#A.get(e)||null}models(){return this.#A}inspectedURL(){return this.#x}setInspectedURL(n){this.#x=n;const r=e.ParsedURL.ParsedURL.fromString(n);this.#M=r?r.lastPathComponentWithFragment():"#"+this.#E,this.parentTarget()?.type()!==_.Frame&&i.InspectorFrontendHost.InspectorFrontendHostInstance.inspectedURLChanged(n||t.DevToolsPath.EmptyUrlString),this.#R.onInspectedURLChange(this),this.#u||this.#R.onNameChange(this)}async suspend(e){this.#O||(this.#O=!0,await Promise.all(Array.from(this.models().values(),(t=>t.preSuspendModel(e)))),await Promise.all(Array.from(this.models().values(),(t=>t.suspendModel(e)))))}async resume(){this.#O&&(this.#O=!1,await Promise.all(Array.from(this.models().values(),(e=>e.resumeModel()))),await Promise.all(Array.from(this.models().values(),(e=>e.postResumeModel()))))}suspended(){return this.#O}updateTargetInfo(e){this.#N=e}targetInfo(){return this.#N}}!function(e){e.Frame="frame",e.ServiceWorker="service-worker",e.Worker="worker",e.SharedWorker="shared-worker",e.Node="node",e.Browser="browser",e.AuctionWorklet="auction-worklet",e.Tab="tab"}(_||(_={})),function(e){e[e.Browser=1]="Browser",e[e.DOM=2]="DOM",e[e.JS=4]="JS",e[e.Log=8]="Log",e[e.Network=16]="Network",e[e.Target=32]="Target",e[e.ScreenCapture=64]="ScreenCapture",e[e.Tracing=128]="Tracing",e[e.Emulation=256]="Emulation",e[e.Security=512]="Security",e[e.Input=1024]="Input",e[e.Inspector=2048]="Inspector",e[e.DeviceEmulation=4096]="DeviceEmulation",e[e.Storage=8192]="Storage",e[e.ServiceWorker=16384]="ServiceWorker",e[e.Audits=32768]="Audits",e[e.WebAuthn=65536]="WebAuthn",e[e.IO=131072]="IO",e[e.Media=262144]="Media",e[e.EventBreakpoints=524288]="EventBreakpoints",e[e.None=0]="None"}(z||(z={}));var V=Object.freeze({__proto__:null,Target:W,get Type(){return _},get Capability(){return z}});let G;class K extends e.ObjectWrapper.ObjectWrapper{#B;#D;#U;#H;#q;#O;#_;#z;#j;#W;constructor(){super(),this.#B=new Set,this.#D=new Set,this.#U=new t.MapUtilities.Multimap,this.#H=new t.MapUtilities.Multimap,this.#O=!1,this.#_=null,this.#z=null,this.#q=new WeakSet,this.#j=!1,this.#W=new Set}static instance({forceNew:e}={forceNew:!1}){return G&&!e||(G=new K),G}static removeInstance(){G=void 0}onInspectedURLChange(e){this.dispatchEventToListeners($.InspectedURLChanged,e)}onNameChange(e){this.dispatchEventToListeners($.NameChanged,e)}async suspendAllTargets(e){if(this.#O)return;this.#O=!0,this.dispatchEventToListeners($.SuspendStateChanged);const t=Array.from(this.#B.values(),(t=>t.suspend(e)));await Promise.all(t)}async resumeAllTargets(){if(!this.#O)return;this.#O=!1,this.dispatchEventToListeners($.SuspendStateChanged);const e=Array.from(this.#B.values(),(e=>e.resume()));await Promise.all(e)}allTargetsSuspended(){return this.#O}models(e,t){const n=[];for(const r of this.#B){if(t?.scoped&&!this.isInScope(r))continue;const s=r.model(e);s&&n.push(s)}return n}inspectedURL(){const e=this.primaryPageTarget();return e?e.inspectedURL():""}observeModels(e,t,n){const r=this.models(e,n);this.#H.set(e,t),n?.scoped&&this.#q.add(t);for(const e of r)t.modelAdded(e)}unobserveModels(e,t){this.#H.delete(e,t),this.#q.delete(t)}modelAdded(e,t,n,r){for(const e of this.#H.get(t).values())this.#q.has(e)&&!r||e.modelAdded(n)}modelRemoved(e,t,n,r){for(const e of this.#H.get(t).values())this.#q.has(e)&&!r||e.modelRemoved(n)}addModelListener(e,t,n,r,s){const i=e=>{s?.scoped&&!this.isInScope(e)||n.call(r,e)};for(const n of this.models(e))n.addEventListener(t,i);this.#U.set(t,{modelClass:e,thisObject:r,listener:n,wrappedListener:i})}removeModelListener(e,t,n,r){if(!this.#U.has(t))return;let s=null;for(const i of this.#U.get(t))i.modelClass===e&&i.listener===n&&i.thisObject===r&&(s=i.wrappedListener,this.#U.delete(t,i));if(s)for(const n of this.models(e))n.removeEventListener(t,s)}observeTargets(e,t){if(this.#D.has(e))throw new Error("Observer can only be registered once");t?.scoped&&this.#q.add(e);for(const n of this.#B)t?.scoped&&!this.isInScope(n)||e.targetAdded(n);this.#D.add(e)}unobserveTargets(e){this.#D.delete(e),this.#q.delete(e)}createTarget(e,t,n,r,s,i,a,o){const l=new W(this,e,t,n,r,s||"",this.#O,a||null,o);i&&l.pageAgent().invoke_waitForDebugger(),l.createModels(new Set(this.#H.keysArray())),this.#B.add(l);const d=this.isInScope(l);for(const e of[...this.#D])this.#q.has(e)&&!d||e.targetAdded(l);for(const[e,t]of l.models().entries())this.modelAdded(l,e,t,d);for(const e of this.#U.keysArray())for(const t of this.#U.get(e)){const n=l.model(t.modelClass);n&&n.addEventListener(e,t.wrappedListener)}return l!==l.outermostTarget()||l.type()===_.Frame&&l!==this.primaryPageTarget()||this.#j||this.setScopeTarget(l),l}removeTarget(e){if(!this.#B.has(e))return;const t=this.isInScope(e);this.#B.delete(e);for(const r of e.models().keys()){const s=e.models().get(r);n(s),this.modelRemoved(e,r,s,t)}for(const n of[...this.#D])this.#q.has(n)&&!t||n.targetRemoved(e);for(const t of this.#U.keysArray())for(const n of this.#U.get(t)){const r=e.model(n.modelClass);r&&r.removeEventListener(t,n.wrappedListener)}}targets(){return[...this.#B]}targetById(e){return this.targets().find((t=>t.id()===e))||null}rootTarget(){return this.#B.size?this.#B.values().next().value:null}primaryPageTarget(){let e=this.rootTarget();return e?.type()===_.Tab&&(e=this.targets().find((t=>t.parentTarget()===e&&t.type()===_.Frame&&!t.targetInfo()?.subtype?.length))||null),e}browserTarget(){return this.#_}async maybeAttachInitialTarget(){if(!Boolean(o.Runtime.Runtime.queryParam("browserConnection")))return!1;this.#_||(this.#_=new W(this,"main","browser",_.Browser,null,"",!1,null,void 0),this.#_.createModels(new Set(this.#H.keysArray())));const e=await i.InspectorFrontendHost.InspectorFrontendHostInstance.initialTargetId();return this.#_.targetAgent().invoke_autoAttachRelated({targetId:e,waitForDebuggerOnStart:!0}),!0}clearAllTargetsForTest(){this.#B.clear()}isInScope(e){if(!e)return!1;for(function(e){return"source"in e&&e.source instanceof c}(e)&&(e=e.source),e instanceof c&&(e=e.target());e&&e!==this.#z;)e=e.parentTarget();return Boolean(e)&&e===this.#z}setScopeTarget(e){if(e!==this.#z){for(const e of this.targets())if(this.isInScope(e)){for(const t of this.#H.keysArray()){const n=e.models().get(t);if(n)for(const e of[...this.#H.get(t)].filter((e=>this.#q.has(e))))e.modelRemoved(n)}for(const t of[...this.#D].filter((e=>this.#q.has(e))))t.targetRemoved(e)}this.#z=e;for(const e of this.targets())if(this.isInScope(e)){for(const t of[...this.#D].filter((e=>this.#q.has(e))))t.targetAdded(e);for(const[t,n]of e.models().entries())for(const e of[...this.#H.get(t)].filter((e=>this.#q.has(e))))e.modelAdded(n)}for(const e of this.#W)e()}}addScopeChangeListener(e){this.#W.add(e)}removeScopeChangeListener(e){this.#W.delete(e)}scopeTarget(){return this.#z}}var $;!function(e){e.AvailableTargetsChanged="AvailableTargetsChanged",e.InspectedURLChanged="InspectedURLChanged",e.NameChanged="NameChanged",e.SuspendStateChanged="SuspendStateChanged"}($||($={}));var Q=Object.freeze({__proto__:null,TargetManager:K,get Events(){return $},Observer:class{targetAdded(e){}targetRemoved(e){}},SDKModelObserver:class{modelAdded(e){}modelRemoved(e){}}});const X={noContentForWebSocket:"Content for WebSockets is currently not supported",noContentForRedirect:"No content available because this request was redirected",noContentForPreflight:"No content available for preflight request",noThrottling:"No throttling",offline:"Offline",slowG:"Slow 3G",fastG:"Fast 3G",requestWasBlockedByDevtoolsS:'Request was blocked by DevTools: "{PH1}"',crossoriginReadBlockingCorb:"Cross-Origin Read Blocking (CORB) blocked cross-origin response {PH1} with MIME type {PH2}. See https://www.chromestatus.com/feature/5629709824032768 for more details.",sFailedLoadingSS:'{PH1} failed loading: {PH2} "{PH3}".',sFinishedLoadingSS:'{PH1} finished loading: {PH2} "{PH3}".'},J=s.i18n.registerUIStrings("core/sdk/NetworkManager.ts",X),Y=s.i18n.getLocalizedString.bind(void 0,J),Z=s.i18n.getLazilyComputedLocalizedString.bind(void 0,J),ee=new WeakMap,te=new Map([["2g","cellular2g"],["3g","cellular3g"],["4g","cellular4g"],["bluetooth","bluetooth"],["wifi","wifi"],["wimax","wimax"]]);class ne extends c{dispatcher;fetchDispatcher;#V;#G;constructor(t){super(t),this.dispatcher=new ce(this),this.fetchDispatcher=new de(t.fetchAgent(),this),this.#V=t.networkAgent(),t.registerNetworkDispatcher(this.dispatcher),t.registerFetchDispatcher(this.fetchDispatcher),e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()&&this.#V.invoke_setCacheDisabled({cacheDisabled:!0}),this.#V.invoke_enable({maxPostDataSize:le}),this.#V.invoke_setAttachDebugStack({enabled:!0}),this.#G=e.Settings.Settings.instance().createSetting("bypassServiceWorker",!1),this.#G.get()&&this.bypassServiceWorkerChanged(),this.#G.addChangeListener(this.bypassServiceWorkerChanged,this),e.Settings.Settings.instance().moduleSetting("cacheDisabled").addChangeListener(this.cacheDisabledSettingChanged,this)}static forRequest(e){return ee.get(e)||null}static canReplayRequest(t){return Boolean(ee.get(t))&&Boolean(t.backendRequestId())&&!t.isRedirect()&&t.resourceType()===e.ResourceType.resourceTypes.XHR}static replayRequest(e){const t=ee.get(e),n=e.backendRequestId();t&&n&&!e.isRedirect()&&t.#V.invoke_replayXHR({requestId:n})}static async searchInRequest(e,t,n,r){const s=ne.forRequest(e),i=e.backendRequestId();if(!s||!i||e.isRedirect())return[];return(await s.#V.invoke_searchInResponseBody({requestId:i,query:t,caseSensitive:n,isRegex:r})).result||[]}static async requestContentData(t){if(t.resourceType()===e.ResourceType.resourceTypes.WebSocket)return{error:Y(X.noContentForWebSocket),content:null,encoded:!1};if(t.finished||await t.once(Te.FinishedLoading),t.isRedirect())return{error:Y(X.noContentForRedirect),content:null,encoded:!1};if(t.isPreflightRequest())return{error:Y(X.noContentForPreflight),content:null,encoded:!1};const n=ne.forRequest(t);if(!n)return{error:"No network manager for request",content:null,encoded:!1};const r=t.backendRequestId();if(!r)return{error:"No backend request id for request",content:null,encoded:!1};const s=await n.#V.invoke_getResponseBody({requestId:r}),i=s.getError()||null;return{error:i,content:i?null:s.body,encoded:s.base64Encoded}}static async requestPostData(e){const t=ne.forRequest(e);if(!t)return console.error("No network manager for request"),null;const n=e.backendRequestId();if(!n)return console.error("No backend request id for request"),null;try{const{postData:e}=await t.#V.invoke_getRequestPostData({requestId:n});return e}catch(e){return e.message}}static connectionType(e){if(!e.download&&!e.upload)return"none";const t="function"==typeof e.title?e.title().toLowerCase():e.title.toLowerCase();for(const[e,n]of te)if(t.includes(e))return n;return"other"}static lowercaseHeaders(e){const t={};for(const n in e)t[n.toLowerCase()]=e[n];return t}requestForURL(e){return this.dispatcher.requestForURL(e)}requestForId(e){return this.dispatcher.requestForId(e)}requestForLoaderId(e){return this.dispatcher.requestForLoaderId(e)}cacheDisabledSettingChanged({data:e}){this.#V.invoke_setCacheDisabled({cacheDisabled:e})}dispose(){e.Settings.Settings.instance().moduleSetting("cacheDisabled").removeChangeListener(this.cacheDisabledSettingChanged,this)}bypassServiceWorkerChanged(){this.#V.invoke_setBypassServiceWorker({bypass:this.#G.get()})}async getSecurityIsolationStatus(e){const t=await this.#V.invoke_getSecurityIsolationStatus({frameId:e??void 0});return t.getError()?null:t.status}async enableReportingApi(e=!0){return this.#V.invoke_enableReportingApi({enable:e})}async loadNetworkResource(e,t,n){const r=await this.#V.invoke_loadNetworkResource({frameId:e??void 0,url:t,options:n});if(r.getError())throw new Error(r.getError());return r.resource}clearRequests(){this.dispatcher.clearRequests()}}var re;!function(e){e.RequestStarted="RequestStarted",e.RequestUpdated="RequestUpdated",e.RequestFinished="RequestFinished",e.RequestUpdateDropped="RequestUpdateDropped",e.ResponseReceived="ResponseReceived",e.MessageGenerated="MessageGenerated",e.RequestRedirected="RequestRedirected",e.LoadingFinished="LoadingFinished",e.ReportingApiReportAdded="ReportingApiReportAdded",e.ReportingApiReportUpdated="ReportingApiReportUpdated",e.ReportingApiEndpointsChangedForOrigin="ReportingApiEndpointsChangedForOrigin"}(re||(re={}));const se={title:Z(X.noThrottling),i18nTitleKey:X.noThrottling,download:-1,upload:-1,latency:0},ie={title:Z(X.offline),i18nTitleKey:X.offline,download:0,upload:0,latency:0},ae={title:Z(X.slowG),i18nTitleKey:X.slowG,download:5e4,upload:5e4,latency:2e3},oe={title:Z(X.fastG),i18nTitleKey:X.fastG,download:18e4,upload:84375,latency:562.5},le=65536;class de{#K;#$;constructor(e,t){this.#K=e,this.#$=t}requestPaused({requestId:e,request:t,resourceType:n,responseStatusCode:r,responseHeaders:s,networkId:i}){const a=i?this.#$.requestForId(i):null;0===a?.originalResponseHeaders.length&&s&&(a.originalResponseHeaders=s),ue.instance().requestIntercepted(new ge(this.#K,t,n,e,a,r,s))}authRequired({}){}}class ce{#$;#Q;#X;#J;#Y;#Z;constructor(e){this.#$=e,this.#Q=new Map,this.#X=new Map,this.#J=new Map,this.#Y=new Map,this.#Z=new Map,ue.instance().addEventListener(ue.Events.RequestIntercepted,this.#ee.bind(this))}#ee(e){const t=this.requestForId(e.data);t&&t.setWasIntercepted(!0)}headersMapToHeadersArray(e){const t=[];for(const n in e){const r=e[n].split("\n");for(let e=0;e=0&&t.setTransferSize(n.encodedDataLength),n.requestHeaders&&!t.hasExtraRequestInfo()&&(t.setRequestHeaders(this.headersMapToHeadersArray(n.requestHeaders)),t.setRequestHeadersText(n.requestHeadersText||"")),t.connectionReused=n.connectionReused,t.connectionId=String(n.connectionId),n.remoteIPAddress&&t.setRemoteAddress(n.remoteIPAddress,n.remotePort||-1),n.fromServiceWorker&&(t.fetchedViaServiceWorker=!0),n.fromDiskCache&&t.setFromDiskCache(),n.fromPrefetchCache&&t.setFromPrefetchCache(),n.cacheStorageCacheName&&t.setResponseCacheStorageCacheName(n.cacheStorageCacheName),n.responseTime&&t.setResponseRetrievalTime(new Date(n.responseTime)),t.timing=n.timing,t.protocol=n.protocol||"",t.alternateProtocolUsage=n.alternateProtocolUsage,n.serviceWorkerResponseSource&&t.setServiceWorkerResponseSource(n.serviceWorkerResponseSource),t.setSecurityState(n.securityState),n.securityDetails&&t.setSecurityDetails(n.securityDetails);const r=e.ResourceType.ResourceType.fromMimeTypeOverride(t.mimeType);r&&t.setResourceType(r)}requestForId(e){return this.#Q.get(e)||null}requestForURL(e){return this.#X.get(e)||null}requestForLoaderId(e){return this.#J.get(e)||null}resourceChangedPriority({requestId:e,newPriority:t}){const n=this.#Q.get(e);n&&n.setPriority(t)}signedExchangeReceived({requestId:t,info:n}){let r=this.#Q.get(t);(r||(r=this.#X.get(n.outerResponse.url),r))&&(r.setSignedExchangeInfo(n),r.setResourceType(e.ResourceType.resourceTypes.SignedExchange),this.updateNetworkRequestWithResponse(r,n.outerResponse),this.updateNetworkRequest(r),this.#$.dispatchEventToListeners(re.ResponseReceived,{request:r,response:n.outerResponse}))}requestWillBeSent({requestId:t,loaderId:n,documentURL:r,request:s,timestamp:i,wallTime:a,initiator:o,redirectResponse:l,type:d,frameId:c,hasUserGesture:h}){let u=this.#Q.get(t);if(u){if(!l)return;u.signedExchangeInfo()||this.responseReceived({requestId:t,loaderId:n,timestamp:i,type:d||"Other",response:l,hasExtraInfo:!1,frameId:c}),u=this.appendRedirect(t,i,s.url),this.#$.dispatchEventToListeners(re.RequestRedirected,u)}else u=Me.create(t,s.url,r,c??null,n,o,h),ee.set(u,this.#$);u.hasNetworkData=!0,this.updateNetworkRequestWithRequest(u,s),u.setIssueTime(i,a),u.setResourceType(d?e.ResourceType.resourceTypes[d]:e.ResourceType.resourceTypes.Other),s.trustTokenParams&&u.setTrustTokenParams(s.trustTokenParams);const g=this.#Z.get(t);g&&(u.setTrustTokenOperationDoneEvent(g),this.#Z.delete(t)),this.getExtraInfoBuilder(t).addRequest(u),this.startNetworkRequest(u,s)}requestServedFromCache({requestId:e}){const t=this.#Q.get(e);t&&t.setFromMemoryCache()}responseReceived({requestId:t,loaderId:n,timestamp:r,type:s,response:i,frameId:a}){const o=this.#Q.get(t),l=ne.lowercaseHeaders(i.headers);if(o)o.responseReceivedTime=r,o.setResourceType(e.ResourceType.resourceTypes[s]),this.updateNetworkRequestWithResponse(o,i),this.updateNetworkRequest(o),this.#$.dispatchEventToListeners(re.ResponseReceived,{request:o,response:i});else{const e=l["last-modified"],t={url:i.url,frameId:a??null,loaderId:n,resourceType:s,mimeType:i.mimeType,lastModified:e?new Date(e):null};this.#$.dispatchEventToListeners(re.RequestUpdateDropped,t)}}dataReceived({requestId:e,timestamp:t,dataLength:n,encodedDataLength:r}){let s=this.#Q.get(e);s||(s=this.maybeAdoptMainResourceRequest(e)),s&&(s.resourceSize+=n,-1!==r&&s.increaseTransferSize(r),s.endTime=t,this.updateNetworkRequest(s))}loadingFinished({requestId:e,timestamp:t,encodedDataLength:n,shouldReportCorbBlocking:r}){let s=this.#Q.get(e);s||(s=this.maybeAdoptMainResourceRequest(e)),s&&(this.getExtraInfoBuilder(e).finished(),this.finishNetworkRequest(s,t,n,r),this.#$.dispatchEventToListeners(re.LoadingFinished,s))}loadingFailed({requestId:t,timestamp:n,type:r,errorText:s,canceled:i,blockedReason:a,corsErrorStatus:o}){const l=this.#Q.get(t);if(l){if(l.failed=!0,l.setResourceType(e.ResourceType.resourceTypes[r]),l.canceled=Boolean(i),a&&(l.setBlockedReason(a),"inspector"===a)){const e=Y(X.requestWasBlockedByDevtoolsS,{PH1:l.url()});this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t,warning:!0})}o&&l.setCorsErrorStatus(o),l.localizedFailDescription=s,this.getExtraInfoBuilder(t).finished(),this.finishNetworkRequest(l,n,-1)}}webSocketCreated({requestId:t,url:n,initiator:r}){const s=Me.createForWebSocket(t,n,r);ee.set(s,this.#$),s.setResourceType(e.ResourceType.resourceTypes.WebSocket),this.startNetworkRequest(s,null)}webSocketWillSendHandshakeRequest({requestId:e,timestamp:t,wallTime:n,request:r}){const s=this.#Q.get(e);s&&(s.requestMethod="GET",s.setRequestHeaders(this.headersMapToHeadersArray(r.headers)),s.setIssueTime(t,n),this.updateNetworkRequest(s))}webSocketHandshakeResponseReceived({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.statusCode=n.status,r.statusText=n.statusText,r.responseHeaders=this.headersMapToHeadersArray(n.headers),r.responseHeadersText=n.headersText||"",n.requestHeaders&&r.setRequestHeaders(this.headersMapToHeadersArray(n.requestHeaders)),n.requestHeadersText&&r.setRequestHeadersText(n.requestHeadersText),r.responseReceivedTime=t,r.protocol="websocket",this.updateNetworkRequest(r))}webSocketFrameReceived({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrame(n,t,!1),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketFrameSent({requestId:e,timestamp:t,response:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrame(n,t,!0),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketFrameError({requestId:e,timestamp:t,errorMessage:n}){const r=this.#Q.get(e);r&&(r.addProtocolFrameError(n,t),r.responseReceivedTime=t,this.updateNetworkRequest(r))}webSocketClosed({requestId:e,timestamp:t}){const n=this.#Q.get(e);n&&this.finishNetworkRequest(n,t,-1)}eventSourceMessageReceived({requestId:e,timestamp:t,eventName:n,eventId:r,data:s}){const i=this.#Q.get(e);i&&i.addEventSourceMessage(t,n,r,s)}requestIntercepted({}){}requestWillBeSentExtraInfo({requestId:e,associatedCookies:t,headers:n,clientSecurityState:r,connectTiming:s,siteHasCookieInOtherPartition:i}){const a=[],o=[];for(const{blockedReasons:e,cookie:n}of t)0===e.length?o.push(F.fromProtocolCookie(n)):a.push({blockedReasons:e,cookie:F.fromProtocolCookie(n)});const l={blockedRequestCookies:a,includedRequestCookies:o,requestHeaders:this.headersMapToHeadersArray(n),clientSecurityState:r,connectTiming:s,siteHasCookieInOtherPartition:i};this.getExtraInfoBuilder(e).addRequestExtraInfo(l)}responseReceivedExtraInfo({requestId:e,blockedCookies:t,headers:n,headersText:r,resourceIPAddressSpace:s,statusCode:i,cookiePartitionKey:a,cookiePartitionKeyOpaque:o}){const l={blockedResponseCookies:t.map((e=>({blockedReasons:e.blockedReasons,cookieLine:e.cookieLine,cookie:e.cookie?F.fromProtocolCookie(e.cookie):null}))),responseHeaders:this.headersMapToHeadersArray(n),responseHeadersText:r,resourceIPAddressSpace:s,statusCode:i,cookiePartitionKey:a,cookiePartitionKeyOpaque:o};this.getExtraInfoBuilder(e).addResponseExtraInfo(l)}getExtraInfoBuilder(e){let t;return this.#Y.has(e)?t=this.#Y.get(e):(t=new pe,this.#Y.set(e,t)),t}appendRedirect(e,t,n){const r=this.#Q.get(e);if(!r)throw new Error(`Could not find original network request for ${e}`);let s=0;for(let e=r.redirectSource();e;e=e.redirectSource())s++;r.markAsRedirect(s),this.finishNetworkRequest(r,t,-1);const i=Me.create(e,n,r.documentURL,r.frameId,r.loaderId,r.initiator(),r.hasUserGesture()??void 0);return ee.set(i,this.#$),i.setRedirectSource(r),r.setRedirectDestination(i),i}maybeAdoptMainResourceRequest(e){const t=ue.instance().inflightMainResourceRequests.get(e);if(!t)return null;const n=ne.forRequest(t).dispatcher;n.#Q.delete(e),n.#X.delete(t.url());const r=t.loaderId;r&&n.#J.delete(r);const s=n.#Y.get(e);return n.#Y.delete(e),this.#Q.set(e,t),this.#X.set(t.url(),t),r&&this.#J.set(r,t),s&&this.#Y.set(e,s),ee.set(t,this.#$),t}startNetworkRequest(e,t){this.#Q.set(e.requestId(),e),this.#X.set(e.url(),e);const n=e.loaderId;n&&this.#J.set(n,e),e.loaderId===e.requestId()&&ue.instance().inflightMainResourceRequests.set(e.requestId(),e),this.#$.dispatchEventToListeners(re.RequestStarted,{request:e,originalRequest:t})}updateNetworkRequest(e){this.#$.dispatchEventToListeners(re.RequestUpdated,e)}finishNetworkRequest(t,n,r,s){if(t.endTime=n,t.finished=!0,r>=0){const e=t.redirectSource();e&&e.signedExchangeInfo()?(t.setTransferSize(0),e.setTransferSize(r),this.updateNetworkRequest(e)):t.setTransferSize(r)}if(this.#$.dispatchEventToListeners(re.RequestFinished,t),ue.instance().inflightMainResourceRequests.delete(t.requestId()),s){const e=Y(X.crossoriginReadBlockingCorb,{PH1:t.url(),PH2:t.mimeType});this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t.requestId(),warning:!0})}if(e.Settings.Settings.instance().moduleSetting("monitoringXHREnabled").get()&&t.resourceType().category()===e.ResourceType.resourceCategories.XHR){let e;const n=t.failed||t.hasErrorStatusCode();e=Y(n?X.sFailedLoadingSS:X.sFinishedLoadingSS,{PH1:t.resourceType().title(),PH2:t.requestMethod,PH3:t.url()}),this.#$.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:t.requestId(),warning:!1})}}clearRequests(){for(const[e,t]of this.#Q)t.finished&&this.#Q.delete(e);for(const[e,t]of this.#X)t.finished&&this.#X.delete(e);for(const[e,t]of this.#J)t.finished&&this.#J.delete(e);for(const[e,t]of this.#Y)t.isFinished()&&this.#Y.delete(e)}webTransportCreated({transportId:t,url:n,timestamp:r,initiator:s}){const i=Me.createForWebSocket(t,n,s);i.hasNetworkData=!0,ee.set(i,this.#$),i.setResourceType(e.ResourceType.resourceTypes.WebTransport),i.setIssueTime(r,0),this.startNetworkRequest(i,null)}webTransportConnectionEstablished({transportId:e,timestamp:t}){const n=this.#Q.get(e);n&&(n.responseReceivedTime=t,n.endTime=t+.001,this.updateNetworkRequest(n))}webTransportClosed({transportId:e,timestamp:t}){const n=this.#Q.get(e);n&&(n.endTime=t,this.finishNetworkRequest(n,t,0))}trustTokenOperationDone(e){const t=this.#Q.get(e.requestId);t?t.setTrustTokenOperationDoneEvent(e):this.#Z.set(e.requestId,e)}subresourceWebBundleMetadataReceived({requestId:e,urls:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInfo({resourceUrls:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleMetadataError({requestId:e,errorMessage:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInfo({errorMessage:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleInnerResponseParsed({innerRequestId:e,bundleRequestId:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInnerRequestInfo({bundleRequestId:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}subresourceWebBundleInnerResponseError({innerRequestId:e,errorMessage:t}){const n=this.getExtraInfoBuilder(e);n.setWebBundleInnerRequestInfo({errorMessage:t});const r=n.finalRequest();r&&this.updateNetworkRequest(r)}reportingApiReportAdded(e){this.#$.dispatchEventToListeners(re.ReportingApiReportAdded,e.report)}reportingApiReportUpdated(e){this.#$.dispatchEventToListeners(re.ReportingApiReportUpdated,e.report)}reportingApiEndpointsChangedForOrigin(e){this.#$.dispatchEventToListeners(re.ReportingApiEndpointsChangedForOrigin,e)}createNetworkRequest(e,t,n,r,s,i){const a=Me.create(e,r,s,t,n,i);return ee.set(a,this.#$),a}}let he;class ue extends e.ObjectWrapper.ObjectWrapper{#te;#ne;#re;#se;#ie;inflightMainResourceRequests;#ae;#oe;#le;#de;#ce;#he;#ue;#ge;constructor(){super(),this.#te="",this.#ne=null,this.#re=null,this.#se=new Set,this.#ie=new Set,this.inflightMainResourceRequests=new Map,this.#ae=se,this.#oe=null,this.#le=e.Settings.Settings.instance().moduleSetting("requestBlockingEnabled"),this.#de=e.Settings.Settings.instance().createSetting("networkBlockedPatterns",[]),this.#ce=[],this.updateBlockedPatterns(),this.#he=new t.MapUtilities.Multimap,K.instance().observeModels(ne,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return he&&!t||(he=new ue),he}static dispose(){he=null}static getChromeVersion(){const e=navigator.userAgent.match(/(?:^|\W)(?:Chrome|HeadlessChrome)\/(\S+)/);return e&&e.length>1?e[1]:""}static patchUserAgentWithChromeVersion(e){const n=ue.getChromeVersion();if(n.length>0){const r=n.split(".",1)[0]+".0.100.0";return t.StringUtilities.sprintf(e,n,r)}return e}static patchUserAgentMetadataWithChromeVersion(e){if(!e.brands)return;const n=ue.getChromeVersion();if(0===n.length)return;const r=n.split(".",1)[0];for(const n of e.brands)n.version.includes("%s")&&(n.version=t.StringUtilities.sprintf(n.version,r));e.fullVersion&&e.fullVersion.includes("%s")&&(e.fullVersion=t.StringUtilities.sprintf(e.fullVersion,n))}modelAdded(e){const t=e.target().networkAgent(),n=e.target().fetchAgent();this.#ue&&t.invoke_setExtraHTTPHeaders({headers:this.#ue}),this.currentUserAgent()&&t.invoke_setUserAgentOverride({userAgent:this.currentUserAgent(),userAgentMetadata:this.#ne||void 0}),this.#ce.length&&t.invoke_setBlockedURLs({urls:this.#ce}),this.isIntercepting()&&n.invoke_enable({patterns:this.#he.valuesArray()}),null===this.#re?t.invoke_clearAcceptedEncodingsOverride():t.invoke_setAcceptedEncodings({encodings:this.#re}),this.#se.add(t),this.#ie.add(n),this.isThrottling()&&this.updateNetworkConditions(t)}modelRemoved(e){for(const t of this.inflightMainResourceRequests){ne.forRequest(t[1])===e&&this.inflightMainResourceRequests.delete(t[0])}this.#se.delete(e.target().networkAgent()),this.#ie.delete(e.target().fetchAgent())}isThrottling(){return this.#ae.download>=0||this.#ae.upload>=0||this.#ae.latency>0}isOffline(){return!this.#ae.download&&!this.#ae.upload}setNetworkConditions(e){this.#ae=e;for(const e of this.#se)this.updateNetworkConditions(e);this.dispatchEventToListeners(ue.Events.ConditionsChanged)}networkConditions(){return this.#ae}updateNetworkConditions(e){const t=this.#ae;this.isThrottling()?e.invoke_emulateNetworkConditions({offline:this.isOffline(),latency:t.latency,downloadThroughput:t.download<0?0:t.download,uploadThroughput:t.upload<0?0:t.upload,connectionType:ne.connectionType(t)}):e.invoke_emulateNetworkConditions({offline:!1,latency:0,downloadThroughput:0,uploadThroughput:0})}setExtraHTTPHeaders(e){this.#ue=e;for(const e of this.#se)e.invoke_setExtraHTTPHeaders({headers:this.#ue})}currentUserAgent(){return this.#ge?this.#ge:this.#te}updateUserAgentOverride(){const e=this.currentUserAgent();for(const t of this.#se)t.invoke_setUserAgentOverride({userAgent:e,userAgentMetadata:this.#ne||void 0})}setUserAgentOverride(e,t){const n=this.#te!==e;this.#te=e,this.#ge?this.#ne=null:(this.#ne=t,this.updateUserAgentOverride()),n&&this.dispatchEventToListeners(ue.Events.UserAgentChanged)}userAgentOverride(){return this.#te}setCustomUserAgentOverride(e,t=null){this.#ge=e,this.#ne=t,this.updateUserAgentOverride()}setCustomAcceptedEncodingsOverride(e){this.#re=e,this.updateAcceptedEncodingsOverride(),this.dispatchEventToListeners(ue.Events.AcceptedEncodingsChanged)}clearCustomAcceptedEncodingsOverride(){this.#re=null,this.updateAcceptedEncodingsOverride(),this.dispatchEventToListeners(ue.Events.AcceptedEncodingsChanged)}isAcceptedEncodingOverrideSet(){return null!==this.#re}updateAcceptedEncodingsOverride(){const e=this.#re;for(const t of this.#se)null===e?t.invoke_clearAcceptedEncodingsOverride():t.invoke_setAcceptedEncodings({encodings:e})}blockedPatterns(){return this.#de.get().slice()}blockingEnabled(){return this.#le.get()}isBlocking(){return Boolean(this.#ce.length)}setBlockedPatterns(e){this.#de.set(e),this.updateBlockedPatterns(),this.dispatchEventToListeners(ue.Events.BlockedPatternsChanged)}setBlockingEnabled(e){this.#le.get()!==e&&(this.#le.set(e),this.updateBlockedPatterns(),this.dispatchEventToListeners(ue.Events.BlockedPatternsChanged))}updateBlockedPatterns(){const e=[];if(this.#le.get())for(const t of this.#de.get())t.enabled&&e.push(t.url);if(e.length||this.#ce.length){this.#ce=e;for(const e of this.#se)e.invoke_setBlockedURLs({urls:this.#ce})}}isIntercepting(){return Boolean(this.#he.size)}setInterceptionHandlerForPatterns(e,t){this.#he.deleteAll(t);for(const n of e)this.#he.set(t,n);return this.updateInterceptionPatternsOnNextTick()}updateInterceptionPatternsOnNextTick(){return this.#oe||(this.#oe=Promise.resolve().then(this.updateInterceptionPatterns.bind(this))),this.#oe}async updateInterceptionPatterns(){e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()||e.Settings.Settings.instance().moduleSetting("cacheDisabled").set(!0),this.#oe=null;const t=[];for(const e of this.#ie)t.push(e.invoke_enable({patterns:this.#he.valuesArray()}));this.dispatchEventToListeners(ue.Events.InterceptorsChanged),await Promise.all(t)}async requestIntercepted(e){for(const t of this.#he.keysArray())if(await t(e),e.hasResponded()&&e.networkRequest)return void this.dispatchEventToListeners(ue.Events.RequestIntercepted,e.networkRequest.requestId());e.hasResponded()||e.continueRequestWithoutChange()}clearBrowserCache(){for(const e of this.#se)e.invoke_clearBrowserCache()}clearBrowserCookies(){for(const e of this.#se)e.invoke_clearBrowserCookies()}async getCertificate(e){const t=K.instance().primaryPageTarget();if(!t)return[];const n=await t.networkAgent().invoke_getCertificate({origin:e});return n?n.tableNames:[]}async loadResource(t){const n={},r=this.currentUserAgent();r&&(n["User-Agent"]=r),e.Settings.Settings.instance().moduleSetting("cacheDisabled").get()&&(n["Cache-Control"]="no-cache");const s=e.Settings.Settings.instance().moduleSetting("network.enable-remote-file-loading").get();return new Promise((e=>i.ResourceLoader.load(t,n,((t,n,r,s)=>{e({success:t,content:r,errorDescription:s})}),s)))}}!function(e){let t;!function(e){e.BlockedPatternsChanged="BlockedPatternsChanged",e.ConditionsChanged="ConditionsChanged",e.UserAgentChanged="UserAgentChanged",e.InterceptorsChanged="InterceptorsChanged",e.AcceptedEncodingsChanged="AcceptedEncodingsChanged",e.RequestIntercepted="RequestIntercepted",e.RequestFulfilled="RequestFulfilled"}(t=e.Events||(e.Events={}))}(ue||(ue={}));class ge{#K;#pe;request;resourceType;responseStatusCode;responseHeaders;requestId;networkRequest;constructor(e,t,n,r,s,i,a){this.#K=e,this.#pe=!1,this.request=t,this.resourceType=n,this.responseStatusCode=i,this.responseHeaders=a,this.requestId=r,this.networkRequest=s}hasResponded(){return this.#pe}static mergeSetCookieHeaders(e,t){const n=e=>{const t=new Map;for(const n of e){const e=n.value.match(/^([a-zA-Z0-9!#$%&'*+.^_`|~-]+=)(.*)$/);e?t.has(e[1])?t.get(e[1])?.push(n.value):t.set(e[1],[n.value]):t.has(n.value)?t.get(n.value)?.push(n.value):t.set(n.value,[n.value])}return t},r=n(e),s=n(t),i=[];for(const[e,t]of r)if(s.has(e))for(const t of s.get(e)||[])i.push({name:"set-cookie",value:t});else for(const e of t)i.push({name:"set-cookie",value:e});for(const[e,t]of s)if(!r.has(e))for(const e of t)i.push({name:"set-cookie",value:e});return i}async continueRequestWithContent(e,t,n,r){this.#pe=!0;const s=t?await e.text():await async function(e){const t=new FileReader,n=new Promise((e=>{t.onloadend=e}));if(t.readAsDataURL(e),await n,t.error)return console.error("Could not convert blob to base64.",t.error),"";const r=t.result;if(null==r||"string"!=typeof r)return console.error("Could not convert blob to base64."),"";return r.substring(r.indexOf(",")+1)}(e),i=r?200:this.responseStatusCode||200;if(this.networkRequest){const e=this.networkRequest?.originalResponseHeaders.filter((e=>"set-cookie"===e.name))||[],t=n.filter((e=>"set-cookie"===e.name));this.networkRequest.setCookieHeaders=ge.mergeSetCookieHeaders(e,t)}this.#K.invoke_fulfillRequest({requestId:this.requestId,responseCode:i,body:s,responseHeaders:n}),ue.instance().dispatchEventToListeners(ue.Events.RequestFulfilled,this.request.url)}continueRequestWithoutChange(){console.assert(!this.#pe),this.#pe=!0,this.#K.invoke_continueRequest({requestId:this.requestId})}continueRequestWithError(e){console.assert(!this.#pe),this.#pe=!0,this.#K.invoke_failRequest({requestId:this.requestId,errorReason:e})}async responseBody(){const e=await this.#K.invoke_getResponseBody({requestId:this.requestId}),t=e.getError()||null;return{error:t,content:t?null:e.body,encoded:e.base64Encoded}}isRedirect(){return void 0!==this.responseStatusCode&&this.responseStatusCode>=300&&this.responseStatusCode<400}}class pe{#me;#fe;#be;#ye;#ve;#Ie;constructor(){this.#me=[],this.#fe=[],this.#be=[],this.#ye=!1,this.#ve=null,this.#Ie=null}addRequest(e){this.#me.push(e),this.sync(this.#me.length-1)}addRequestExtraInfo(e){this.#fe.push(e),this.sync(this.#fe.length-1)}addResponseExtraInfo(e){this.#be.push(e),this.sync(this.#be.length-1)}setWebBundleInfo(e){this.#ve=e,this.updateFinalRequest()}setWebBundleInnerRequestInfo(e){this.#Ie=e,this.updateFinalRequest()}finished(){this.#ye=!0,this.updateFinalRequest()}isFinished(){return this.#ye}sync(e){const t=this.#me[e];if(!t)return;const n=this.#fe[e];n&&(t.addExtraRequestInfo(n),this.#fe[e]=null);const r=this.#be[e];r&&(t.addExtraResponseInfo(r),this.#be[e]=null)}finalRequest(){return this.#ye&&this.#me[this.#me.length-1]||null}updateFinalRequest(){if(!this.#ye)return;const e=this.finalRequest();e?.setWebBundleInfo(this.#ve),e?.setWebBundleInnerRequestInfo(this.#Ie)}}c.register(ne,{capabilities:z.Network,autostart:!0});var me=Object.freeze({__proto__:null,NetworkManager:ne,get Events(){return re},NoThrottlingConditions:se,OfflineConditions:ie,Slow3GConditions:ae,Fast3GConditions:oe,FetchDispatcher:de,NetworkDispatcher:ce,get MultitargetNetworkManager(){return ue},InterceptedRequest:ge,ConditionsSerializer:class{stringify(e){const t=e;return JSON.stringify({...t,title:"function"==typeof t.title?t.title():t.title})}parse(e){const t=JSON.parse(e);return{...t,title:t.i18nTitleKey?Z(t.i18nTitleKey):t.title}}},networkConditionsEqual:function(e,t){const n="function"==typeof e.title?e.title():e.title,r="function"==typeof t.title?t.title():t.title;return t.download===e.download&&t.upload===e.upload&&t.latency===e.latency&&r===n}});const fe={deprecatedSyntaxFoundPleaseUse:"Deprecated syntax found. Please use: ;dur=;desc=",duplicateParameterSIgnored:'Duplicate parameter "{PH1}" ignored.',noValueFoundForParameterS:'No value found for parameter "{PH1}".',unrecognizedParameterS:'Unrecognized parameter "{PH1}".',extraneousTrailingCharacters:"Extraneous trailing characters.",unableToParseSValueS:'Unable to parse "{PH1}" value "{PH2}".'},be=s.i18n.registerUIStrings("core/sdk/ServerTiming.ts",fe),ye=s.i18n.getLocalizedString.bind(void 0,be);class ve{metric;value;description;constructor(e,t,n){this.metric=e,this.value=t,this.description=n}static parseHeaders(e){const n=e.filter((e=>"server-timing"===e.name.toLowerCase()));if(!n.length)return null;const r=n.reduce(((e,t)=>{const n=this.createFromHeaderValue(t.value);return e.push(...n.map((function(e){return new ve(e.name,e.hasOwnProperty("dur")?e.dur:null,e.hasOwnProperty("desc")?e.desc:"")}))),e}),[]);return r.sort(((e,n)=>t.StringUtilities.compare(e.metric.toLowerCase(),n.metric.toLowerCase()))),r}static createFromHeaderValue(e){function t(){e=e.replace(/^\s*/,"")}function n(n){return console.assert(1===n.length),t(),e.charAt(0)===n&&(e=e.substring(1),!0)}function r(){const t=/^(?:\s*)([\w!#$%&'*+\-.^`|~]+)(?:\s*)(.*)/.exec(e);return t?(e=t[2],t[1]):null}function s(){return t(),'"'===e.charAt(0)?function(){console.assert('"'===e.charAt(0)),e=e.substring(1);let t="";for(;e.length;){const n=/^([^"\\]*)(.*)/.exec(e);if(!n)return null;if(t+=n[1],'"'===n[2].charAt(0))return e=n[2].substring(1),t;console.assert("\\"===n[2].charAt(0)),t+=n[2].charAt(1),e=n[2].substring(2)}return null}():r()}function i(){const t=/([,;].*)/.exec(e);t&&(e=t[1])}const a=[];let o;for(;null!==(o=r());){const t={name:o};for("="===e.charAt(0)&&this.showWarning(ye(fe.deprecatedSyntaxFoundPleaseUse));n(";");){let e;if(null===(e=r()))continue;e=e.toLowerCase();const a=this.getParserForParameter(e);let o=null;if(n("=")&&(o=s(),i()),a){if(t.hasOwnProperty(e)){this.showWarning(ye(fe.duplicateParameterSIgnored,{PH1:e}));continue}null===o&&this.showWarning(ye(fe.noValueFoundForParameterS,{PH1:e})),a.call(this,t,o)}else this.showWarning(ye(fe.unrecognizedParameterS,{PH1:e}))}if(a.push(t),!n(","))break}return e.length&&this.showWarning(ye(fe.extraneousTrailingCharacters)),a}static getParserForParameter(e){switch(e){case"dur":{function t(t,n){if(t.dur=0,null!==n){const r=parseFloat(n);if(isNaN(r))return void ve.showWarning(ye(fe.unableToParseSValueS,{PH1:e,PH2:n}));t.dur=r}}return t}case"desc":{function e(e,t){e.desc=t||""}return e}default:return null}}static showWarning(t){e.Console.Console.instance().warn(`ServerTiming: ${t}`)}}var Ie=Object.freeze({__proto__:null,ServerTiming:ve});const ke={binary:"(binary)",secureOnly:'This cookie was blocked because it had the "`Secure`" attribute and the connection was not secure.',notOnPath:"This cookie was blocked because its path was not an exact match for or a superdirectory of the request url's path.",domainMismatch:"This cookie was blocked because neither did the request URL's domain exactly match the cookie's domain, nor was the request URL's domain a subdomain of the cookie's Domain attribute value.",sameSiteStrict:'This cookie was blocked because it had the "`SameSite=Strict`" attribute and the request was made from a different site. This includes top-level navigation requests initiated by other sites.',sameSiteLax:'This cookie was blocked because it had the "`SameSite=Lax`" attribute and the request was made from a different site and was not initiated by a top-level navigation.',sameSiteUnspecifiedTreatedAsLax:'This cookie didn\'t specify a "`SameSite`" attribute when it was stored and was defaulted to "SameSite=Lax," and was blocked because the request was made from a different site and was not initiated by a top-level navigation. The cookie had to have been set with "`SameSite=None`" to enable cross-site usage.',sameSiteNoneInsecure:'This cookie was blocked because it had the "`SameSite=None`" attribute but was not marked "Secure". Cookies without SameSite restrictions must be marked "Secure" and sent over a secure connection.',userPreferences:"This cookie was blocked due to user preferences.",unknownError:"An unknown error was encountered when trying to send this cookie.",schemefulSameSiteStrict:'This cookie was blocked because it had the "`SameSite=Strict`" attribute but the request was cross-site. This includes top-level navigation requests initiated by other sites. This request is considered cross-site because the URL has a different scheme than the current site.',schemefulSameSiteLax:'This cookie was blocked because it had the "`SameSite=Lax`" attribute but the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site.',schemefulSameSiteUnspecifiedTreatedAsLax:'This cookie didn\'t specify a "`SameSite`" attribute when it was stored, was defaulted to "`SameSite=Lax"`, and was blocked because the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site.',samePartyFromCrossPartyContext:"This cookie was blocked because it had the \"`SameParty`\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set.",nameValuePairExceedsMaxSize:"This cookie was blocked because it was too large. The combined size of the name and value must be less than or equal to 4096 characters.",thisSetcookieWasBlockedDueToUser:"This attempt to set a cookie via a `Set-Cookie` header was blocked due to user preferences.",thisSetcookieHadInvalidSyntax:"This `Set-Cookie` header had invalid syntax.",theSchemeOfThisConnectionIsNot:"The scheme of this connection is not allowed to store cookies.",anUnknownErrorWasEncounteredWhenTrying:"An unknown error was encountered when trying to store this cookie.",thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "{PH1}" attribute but came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site.',thisSetcookieDidntSpecifyASamesite:'This `Set-Cookie` header didn\'t specify a "`SameSite`" attribute, was defaulted to "`SameSite=Lax"`, and was blocked because it came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site.',thisSetcookieWasBlockedBecauseItHadTheSameparty:"This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the \"`SameParty`\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set.",thisSetcookieWasBlockedBecauseItHadTheSamepartyAttribute:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "`SameParty`" attribute but also had other conflicting attributes. Chrome requires cookies that use the "`SameParty`" attribute to also have the "Secure" attribute, and to not be restricted to "`SameSite=Strict`".',blockedReasonSecureOnly:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "Secure" attribute but was not received over a secure connection.',blockedReasonSameSiteStrictLax:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "{PH1}" attribute but came from a cross-site response which was not the response to a top-level navigation.',blockedReasonSameSiteUnspecifiedTreatedAsLax:'This `Set-Cookie` header didn\'t specify a "`SameSite`" attribute and was defaulted to "`SameSite=Lax,`" and was blocked because it came from a cross-site response which was not the response to a top-level navigation. The `Set-Cookie` had to have been set with "`SameSite=None`" to enable cross-site usage.',blockedReasonSameSiteNoneInsecure:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it had the "`SameSite=None`" attribute but did not have the "Secure" attribute, which is required in order to use "`SameSite=None`".',blockedReasonOverwriteSecure:"This attempt to set a cookie via a `Set-Cookie` header was blocked because it was not sent over a secure connection and would have overwritten a cookie with the Secure attribute.",blockedReasonInvalidDomain:"This attempt to set a cookie via a `Set-Cookie` header was blocked because its Domain attribute was invalid with regards to the current host url.",blockedReasonInvalidPrefix:'This attempt to set a cookie via a `Set-Cookie` header was blocked because it used the "`__Secure-`" or "`__Host-`" prefix in its name and broke the additional rules applied to cookies with these prefixes as defined in `https://tools.ietf.org/html/draft-west-cookie-prefixes-05`.',thisSetcookieWasBlockedBecauseTheNameValuePairExceedsMaxSize:"This attempt to set a cookie via a `Set-Cookie` header was blocked because the cookie was too large. The combined size of the name and value must be less than or equal to 4096 characters.",setcookieHeaderIsIgnoredIn:"Set-Cookie header is ignored in response from url: {PH1}. The combined size of the name and value must be less than or equal to 4096 characters."},Se=s.i18n.registerUIStrings("core/sdk/NetworkRequest.ts",ke),we=s.i18n.getLocalizedString.bind(void 0,Se);var Ce,Te,Re,xe;!function(e){e.HTML="text/html",e.XML="text/xml",e.PLAIN="text/plain",e.XHTML="application/xhtml+xml",e.SVG="image/svg+xml",e.CSS="text/css",e.XSL="text/xsl",e.VTT="text/vtt",e.PDF="application/pdf",e.EVENTSTREAM="text/event-stream"}(Ce||(Ce={}));class Me extends e.ObjectWrapper.ObjectWrapper{#ke;#Se;#we;#Ce;#Te;#Re;#xe;#Me;#Pe;#Le;#Ee;#Ae;#Oe;#Ne;#Fe;#Be;#De;statusCode;statusText;requestMethod;requestTime;protocol;alternateProtocolUsage;mixedContentType;#Ue;#He;#qe;#_e;#ze;#je;#We;#Ve;#Ge;#Ke;#$e;#Qe;#Xe;#Je;#Ye;#Ze;#et;#tt;#nt;#rt;#st;connectionId;connectionReused;hasNetworkData;#it;#at;#ot;#lt;#dt;#ct;#ht;#ut;#gt;#pt;localizedFailDescription;#mt;#ft;#bt;#ye;#yt;#vt;#It;#kt;#St;#u;#wt;#Ct;#Tt;#Rt;#xt;#Mt;#Pt;#Lt;#Et;#At;#Ot;#Nt;#Ft;#Bt;#Dt;#Ut;#Ht;#qt;#_t;#zt;#jt;#Wt;#Vt;#Gt;#Kt=new Map;constructor(t,n,r,s,i,a,o,l){super(),this.#ke=t,this.#Se=n,this.setUrl(r),this.#we=s,this.#Ce=i,this.#Te=a,this.#Re=o,this.#xe=l,this.#Me=null,this.#Pe=null,this.#Le=null,this.#Ee=!1,this.#Ae=null,this.#Oe=-1,this.#Ne=-1,this.#Fe=-1,this.#Be=void 0,this.#De=void 0,this.statusCode=0,this.statusText="",this.requestMethod="",this.requestTime=0,this.protocol="",this.alternateProtocolUsage=void 0,this.mixedContentType="none",this.#Ue=null,this.#He=null,this.#qe=null,this.#_e=null,this.#ze=null,this.#je=e.ResourceType.resourceTypes.Other,this.#We=null,this.#Ve=[],this.#Ge=[],this.#Ke={},this.#$e="",this.#Qe=[],this.#Je=[],this.#Ye=[],this.#Ze={},this.#et="",this.#tt="Unknown",this.#nt=null,this.#rt="unknown",this.#st=null,this.connectionId="0",this.connectionReused=!1,this.hasNetworkData=!1,this.#it=null,this.#at=Promise.resolve(null),this.#ot=!1,this.#lt=!1,this.#dt=[],this.#ct=[],this.#ht=[],this.#pt=!1,this.#ut=null,this.#gt=null,this.localizedFailDescription=null,this.#Vt=null,this.#Gt=!1}static create(e,t,n,r,s,i,a){return new Me(e,e,t,n,r,s,i,a)}static createForWebSocket(e,n,r){return new Me(e,e,n,t.DevToolsPath.EmptyUrlString,null,null,r||null)}static createWithoutBackendRequest(e,t,n,r){return new Me(e,void 0,t,n,null,null,r)}identityCompare(e){const t=this.requestId(),n=e.requestId();return t>n?1:te&&(this.#ft=e)),this.dispatchEventToListeners(Te.TimingChanged,this)}get duration(){return-1===this.#Fe||-1===this.#Ne?-1:this.#Fe-this.#Ne}get latency(){return-1===this.#ft||-1===this.#Ne?-1:this.#ft-this.#Ne}get resourceSize(){return this.#Et||0}set resourceSize(e){this.#Et=e}get transferSize(){return this.#bt||0}increaseTransferSize(e){this.#bt=(this.#bt||0)+e}setTransferSize(e){this.#bt=e}get finished(){return this.#ye}set finished(e){this.#ye!==e&&(this.#ye=e,e&&this.dispatchEventToListeners(Te.FinishedLoading,this))}get failed(){return this.#yt}set failed(e){this.#yt=e}get canceled(){return this.#vt}set canceled(e){this.#vt=e}get preserved(){return this.#It}set preserved(e){this.#It=e}blockedReason(){return this.#Be}setBlockedReason(e){this.#Be=e}corsErrorStatus(){return this.#De}setCorsErrorStatus(e){this.#De=e}wasBlocked(){return Boolean(this.#Be)}cached(){return(Boolean(this.#At)||Boolean(this.#Ot))&&!this.#bt}cachedInMemory(){return Boolean(this.#At)&&!this.#bt}fromPrefetchCache(){return Boolean(this.#Nt)}setFromMemoryCache(){this.#At=!0,this.#Bt=void 0}get fromDiskCache(){return this.#Ot}setFromDiskCache(){this.#Ot=!0}setFromPrefetchCache(){this.#Nt=!0}get fetchedViaServiceWorker(){return Boolean(this.#Ft)}set fetchedViaServiceWorker(e){this.#Ft=e}initiatedByServiceWorker(){const e=ne.forRequest(this);return!!e&&e.target().type()===_.ServiceWorker}get timing(){return this.#Bt}set timing(e){if(!e||this.#At)return;this.#Ne=e.requestTime;const t=e.requestTime+e.receiveHeadersEnd/1e3;((this.#ft||-1)<0||this.#ft>t)&&(this.#ft=t),this.#Ne>this.#ft&&(this.#ft=this.#Ne),this.#Bt=e,this.dispatchEventToListeners(Te.TimingChanged,this)}setConnectTimingFromExtraInfo(e){this.#Ne=e.requestTime,this.dispatchEventToListeners(Te.TimingChanged,this)}get mimeType(){return this.#kt}set mimeType(e){this.#kt=e}get displayName(){return this.#St.displayName}name(){return this.#u||this.parseNameAndPathFromURL(),this.#u}path(){return this.#wt||this.parseNameAndPathFromURL(),this.#wt}parseNameAndPathFromURL(){if(this.#St.isDataURL())this.#u=this.#St.dataURLDisplayName(),this.#wt="";else if(this.#St.isBlobURL())this.#u=this.#St.url,this.#wt="";else if(this.#St.isAboutBlank())this.#u=this.#St.url,this.#wt="";else{this.#wt=this.#St.host+this.#St.folderPathComponents;const n=ne.forRequest(this),r=n?e.ParsedURL.ParsedURL.fromString(n.target().inspectedURL()):null;this.#wt=t.StringUtilities.trimURL(this.#wt,r?r.host:""),this.#St.lastPathComponent||this.#St.queryParams?this.#u=this.#St.lastPathComponent+(this.#St.queryParams?"?"+this.#St.queryParams:""):this.#St.folderPathComponents?(this.#u=this.#St.folderPathComponents.substring(this.#St.folderPathComponents.lastIndexOf("/")+1)+"/",this.#wt=this.#wt.substring(0,this.#wt.lastIndexOf("/"))):(this.#u=this.#St.host,this.#wt="")}}get folder(){let e=this.#St.path;const t=e.indexOf("?");-1!==t&&(e=e.substring(0,t));const n=e.lastIndexOf("/");return-1!==n?e.substring(0,n):""}get pathname(){return this.#St.path}resourceType(){return this.#je}setResourceType(e){this.#je=e}get domain(){return this.#St.host}get scheme(){return this.#St.scheme}redirectSource(){return this.#Me}setRedirectSource(e){this.#Me=e}preflightRequest(){return this.#Pe}setPreflightRequest(e){this.#Pe=e}preflightInitiatorRequest(){return this.#Le}setPreflightInitiatorRequest(e){this.#Le=e}isPreflightRequest(){return null!==this.#Re&&void 0!==this.#Re&&"preflight"===this.#Re.type}redirectDestination(){return this.#Ae}setRedirectDestination(e){this.#Ae=e}requestHeaders(){return this.#Ye}setRequestHeaders(e){this.#Ye=e,this.dispatchEventToListeners(Te.RequestHeadersChanged)}requestHeadersText(){return this.#Dt}setRequestHeadersText(e){this.#Dt=e,this.dispatchEventToListeners(Te.RequestHeadersChanged)}requestHeaderValue(e){return this.#Ze[e]||(this.#Ze[e]=this.computeHeaderValue(this.requestHeaders(),e)),this.#Ze[e]}requestFormData(){return this.#at||(this.#at=ne.requestPostData(this)),this.#at}setRequestFormData(e,t){this.#at=e&&null===t?null:Promise.resolve(t),this.#it=null}filteredProtocolName(){const e=this.protocol.toLowerCase();return"h2"===e?"http/2.0":e.replace(/^http\/2(\.0)?\+/,"http/2.0+")}requestHttpVersion(){const e=this.requestHeadersText();if(!e){const e=this.requestHeaderValue("version")||this.requestHeaderValue(":version");return e||this.filteredProtocolName()}const t=e.split(/\r\n/)[0].match(/(HTTP\/\d+\.\d+)$/);return t?t[1]:"HTTP/0.9"}get responseHeaders(){return this.#Ut||[]}set responseHeaders(e){this.#Ut=e,this.#Ht=void 0,this.#_t=void 0,this.#qt=void 0,this.#Ke={},this.dispatchEventToListeners(Te.ResponseHeadersChanged)}get originalResponseHeaders(){return this.#Qe}set originalResponseHeaders(e){this.#Qe=e,this.#Xe=void 0}get setCookieHeaders(){return this.#Je}set setCookieHeaders(e){this.#Je=e}get responseHeadersText(){return this.#$e}set responseHeadersText(e){this.#$e=e,this.dispatchEventToListeners(Te.ResponseHeadersChanged)}get sortedResponseHeaders(){return void 0!==this.#Ht?this.#Ht:(this.#Ht=this.responseHeaders.slice(),this.#Ht.sort((function(e,n){return t.StringUtilities.compare(e.name.toLowerCase(),n.name.toLowerCase())||t.StringUtilities.compare(e.value,n.value)})))}get sortedOriginalResponseHeaders(){return void 0!==this.#Xe?this.#Xe:(this.#Xe=this.originalResponseHeaders.slice(),this.#Xe.sort((function(e,n){return t.StringUtilities.compare(e.name.toLowerCase(),n.name.toLowerCase())||t.StringUtilities.compare(e.value,n.value)})))}hasOverriddenHeaders(){if(!this.#Qe.length)return!1;const e=this.sortedResponseHeaders,t=this.sortedOriginalResponseHeaders;if(t.length!==e.length)return!0;for(let n=0;ne.cookie)),...this.blockedResponseCookies().map((e=>e.cookie))].filter((e=>Boolean(e)))}get serverTimings(){return void 0===this.#_t&&(this.#_t=ve.parseHeaders(this.responseHeaders)),this.#_t}queryString(){if(void 0!==this.#zt)return this.#zt;let e=null;const t=this.url(),n=t.indexOf("?");if(-1!==n){e=t.substring(n+1);const r=e.indexOf("#");-1!==r&&(e=e.substring(0,r))}return this.#zt=e,this.#zt}get queryParameters(){if(this.#jt)return this.#jt;const e=this.queryString();return e?(this.#jt=this.parseParameters(e),this.#jt):null}async parseFormParameters(){const e=this.requestContentType();if(!e)return null;if(e.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i)){const e=await this.requestFormData();return e?this.parseParameters(e):null}const t=e.match(/^multipart\/form-data\s*;\s*boundary\s*=\s*(\S+)\s*$/);if(!t)return null;const n=t[1];if(!n)return null;const r=await this.requestFormData();return r?this.parseMultipartFormDataParameters(r,n):null}formParameters(){return this.#it||(this.#it=this.parseFormParameters()),this.#it}responseHttpVersion(){const e=this.#$e;if(!e){const e=this.responseHeaderValue("version")||this.responseHeaderValue(":version");return e||this.filteredProtocolName()}const t=e.split(/\r\n/)[0].match(/^(HTTP\/\d+\.\d+)/);return t?t[1]:"HTTP/0.9"}parseParameters(e){return e.split("&").map((function(e){const t=e.indexOf("=");return-1===t?{name:e,value:""}:{name:e.substring(0,t),value:e.substring(t+1)}}))}parseMultipartFormDataParameters(e,n){const r=t.StringUtilities.escapeForRegExp(n),s=new RegExp('^\\r\\ncontent-disposition\\s*:\\s*form-data\\s*;\\s*name="([^"]*)"(?:\\s*;\\s*filename="([^"]*)")?(?:\\r\\ncontent-type\\s*:\\s*([^\\r\\n]*))?\\r\\n\\r\\n(.*)\\r\\n$',"is");return e.split(new RegExp(`--${r}(?:--s*$)?`,"g")).reduce((function(e,t){const[n,r,i,a,o]=t.match(s)||[];if(!n)return e;const l=i||a?we(ke.binary):o;return e.push({name:r,value:l}),e}),[])}computeHeaderValue(e,t){t=t.toLowerCase();const n=[];for(let r=0;r=400}setInitialPriority(e){this.#Ue=e}initialPriority(){return this.#Ue}setPriority(e){this.#He=e}priority(){return this.#He||this.#Ue||null}setSignedExchangeInfo(e){this.#qe=e}signedExchangeInfo(){return this.#qe}setWebBundleInfo(e){this.#_e=e}webBundleInfo(){return this.#_e}setWebBundleInnerRequestInfo(e){this.#ze=e}webBundleInnerRequestInfo(){return this.#ze}async populateImageSource(e){const{content:t,encoded:n}=await this.contentData();let s=r.ContentProvider.contentAsDataURL(t,this.#kt,n);if(null===s&&!this.#yt){(this.responseHeaderValue("cache-control")||"").includes("no-cache")||(s=this.#mt)}null!==s&&(e.src=s)}initiator(){return this.#Re||null}hasUserGesture(){return this.#xe??null}frames(){return this.#Ve}addProtocolFrameError(e,t){this.addFrame({type:xe.Error,text:e,time:this.pseudoWallTime(t),opCode:-1,mask:!1})}addProtocolFrame(e,t,n){const r=n?xe.Send:xe.Receive;this.addFrame({type:r,text:e.payloadData,time:this.pseudoWallTime(t),opCode:e.opcode,mask:e.mask})}addFrame(e){this.#Ve.push(e),this.dispatchEventToListeners(Te.WebsocketFrameAdded,e)}eventSourceMessages(){return this.#Ge}addEventSourceMessage(e,t,n,r){const s={time:this.pseudoWallTime(e),eventName:t,eventId:n,data:r};this.#Ge.push(s),this.dispatchEventToListeners(Te.EventSourceMessageAdded,s)}markAsRedirect(e){this.#Ee=!0,this.#ke=`${this.#Se}:redirected.${e}`}isRedirect(){return this.#Ee}setRequestIdForTest(e){this.#Se=e,this.#ke=e}charset(){const e=this.responseHeaderValue("content-type");if(!e)return null;const t=e.replace(/ /g,"").split(";").filter((e=>e.toLowerCase().startsWith("charset="))).map((e=>e.slice("charset=".length)));return t.length?t[0]:null}addExtraRequestInfo(e){this.#dt=e.blockedRequestCookies,this.#ct=e.includedRequestCookies,this.setRequestHeaders(e.requestHeaders),this.#ot=!0,this.setRequestHeadersText(""),this.#Ct=e.clientSecurityState,this.setConnectTimingFromExtraInfo(e.connectTiming),this.#pt=e.siteHasCookieInOtherPartition??!1}hasExtraRequestInfo(){return this.#ot}blockedRequestCookies(){return this.#dt}includedRequestCookies(){return this.#ct}hasRequestCookies(){return this.#ct.length>0||this.#dt.length>0}siteHasCookieInOtherPartition(){return this.#pt}static parseStatusTextFromResponseHeadersText(e){return e.split("\r")[0].split(" ").slice(2).join(" ")}addExtraResponseInfo(e){if(this.#ht=e.blockedResponseCookies,this.#ut=e.cookiePartitionKey||null,this.#gt=e.cookiePartitionKeyOpaque||null,this.responseHeaders=e.responseHeaders,this.originalResponseHeaders=e.responseHeaders.map((e=>({...e}))),e.responseHeadersText){if(this.responseHeadersText=e.responseHeadersText,!this.requestHeadersText()){let e=`${this.requestMethod} ${this.parsedURL.path}`;this.parsedURL.queryParams&&(e+=`?${this.parsedURL.queryParams}`),e+=" HTTP/1.1\r\n";for(const{name:t,value:n}of this.requestHeaders())e+=`${t}: ${n}\r\n`;this.setRequestHeadersText(e)}this.statusText=Me.parseStatusTextFromResponseHeadersText(e.responseHeadersText)}this.#tt=e.resourceIPAddressSpace,e.statusCode&&(this.statusCode=e.statusCode),this.#lt=!0;const t=ne.forRequest(this);if(t)for(const e of this.#ht)if(e.blockedReasons.includes("NameValuePairExceedsMaxSize")){const e=we(ke.setcookieHeaderIsIgnoredIn,{PH1:this.url()});t.dispatchEventToListeners(re.MessageGenerated,{message:e,requestId:this.#ke,warning:!0})}}hasExtraResponseInfo(){return this.#lt}blockedResponseCookies(){return this.#ht}responseCookiesPartitionKey(){return this.#ut}responseCookiesPartitionKeyOpaque(){return this.#gt}redirectSourceSignedExchangeInfoHasNoErrors(){return null!==this.#Me&&null!==this.#Me.#qe&&!this.#Me.#qe.errors}clientSecurityState(){return this.#Ct}setTrustTokenParams(e){this.#Tt=e}trustTokenParams(){return this.#Tt}setTrustTokenOperationDoneEvent(e){this.#Rt=e,this.dispatchEventToListeners(Te.TrustTokenResultAdded)}trustTokenOperationDoneEvent(){return this.#Rt}setIsSameSite(e){this.#Vt=e}isSameSite(){return this.#Vt}getAssociatedData(e){return this.#Kt.get(e)||null}setAssociatedData(e,t){this.#Kt.set(e,t)}deleteAssociatedData(e){this.#Kt.delete(e)}}!function(e){e.FinishedLoading="FinishedLoading",e.TimingChanged="TimingChanged",e.RemoteAddressChanged="RemoteAddressChanged",e.RequestHeadersChanged="RequestHeadersChanged",e.ResponseHeadersChanged="ResponseHeadersChanged",e.WebsocketFrameAdded="WebsocketFrameAdded",e.EventSourceMessageAdded="EventSourceMessageAdded",e.TrustTokenResultAdded="TrustTokenResultAdded"}(Te||(Te={})),function(e){e.Other="other",e.Parser="parser",e.Redirect="redirect",e.Script="script",e.Preload="preload",e.SignedExchange="signedExchange",e.Preflight="preflight"}(Re||(Re={})),function(e){e.Send="send",e.Receive="receive",e.Error="error"}(xe||(xe={}));var Pe=Object.freeze({__proto__:null,get MIME_TYPE(){return Ce},NetworkRequest:Me,get Events(){return Te},get InitiatorType(){return Re},get WebSocketFrameType(){return xe},cookieBlockedReasonToUiString:function(e){switch(e){case"SecureOnly":return we(ke.secureOnly);case"NotOnPath":return we(ke.notOnPath);case"DomainMismatch":return we(ke.domainMismatch);case"SameSiteStrict":return we(ke.sameSiteStrict);case"SameSiteLax":return we(ke.sameSiteLax);case"SameSiteUnspecifiedTreatedAsLax":return we(ke.sameSiteUnspecifiedTreatedAsLax);case"SameSiteNoneInsecure":return we(ke.sameSiteNoneInsecure);case"UserPreferences":return we(ke.userPreferences);case"UnknownError":return we(ke.unknownError);case"SchemefulSameSiteStrict":return we(ke.schemefulSameSiteStrict);case"SchemefulSameSiteLax":return we(ke.schemefulSameSiteLax);case"SchemefulSameSiteUnspecifiedTreatedAsLax":return we(ke.schemefulSameSiteUnspecifiedTreatedAsLax);case"SamePartyFromCrossPartyContext":return we(ke.samePartyFromCrossPartyContext);case"NameValuePairExceedsMaxSize":return we(ke.nameValuePairExceedsMaxSize)}return""},setCookieBlockedReasonToUiString:function(e){switch(e){case"SecureOnly":return we(ke.blockedReasonSecureOnly);case"SameSiteStrict":return we(ke.blockedReasonSameSiteStrictLax,{PH1:"SameSite=Strict"});case"SameSiteLax":return we(ke.blockedReasonSameSiteStrictLax,{PH1:"SameSite=Lax"});case"SameSiteUnspecifiedTreatedAsLax":return we(ke.blockedReasonSameSiteUnspecifiedTreatedAsLax);case"SameSiteNoneInsecure":return we(ke.blockedReasonSameSiteNoneInsecure);case"UserPreferences":return we(ke.thisSetcookieWasBlockedDueToUser);case"SyntaxError":return we(ke.thisSetcookieHadInvalidSyntax);case"SchemeNotSupported":return we(ke.theSchemeOfThisConnectionIsNot);case"OverwriteSecure":return we(ke.blockedReasonOverwriteSecure);case"InvalidDomain":return we(ke.blockedReasonInvalidDomain);case"InvalidPrefix":return we(ke.blockedReasonInvalidPrefix);case"UnknownError":return we(ke.anUnknownErrorWasEncounteredWhenTrying);case"SchemefulSameSiteStrict":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax,{PH1:"SameSite=Strict"});case"SchemefulSameSiteLax":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax,{PH1:"SameSite=Lax"});case"SchemefulSameSiteUnspecifiedTreatedAsLax":return we(ke.thisSetcookieDidntSpecifyASamesite);case"SamePartyFromCrossPartyContext":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSameparty);case"SamePartyConflictsWithOtherAttributes":return we(ke.thisSetcookieWasBlockedBecauseItHadTheSamepartyAttribute);case"NameValuePairExceedsMaxSize":return we(ke.thisSetcookieWasBlockedBecauseTheNameValuePairExceedsMaxSize)}return""},cookieBlockedReasonToAttribute:function(e){switch(e){case"SecureOnly":return D.Secure;case"NotOnPath":return D.Path;case"DomainMismatch":return D.Domain;case"SameSiteStrict":case"SameSiteLax":case"SameSiteUnspecifiedTreatedAsLax":case"SameSiteNoneInsecure":case"SchemefulSameSiteStrict":case"SchemefulSameSiteLax":case"SchemefulSameSiteUnspecifiedTreatedAsLax":return D.SameSite;case"SamePartyFromCrossPartyContext":case"NameValuePairExceedsMaxSize":case"UserPreferences":case"UnknownError":return null}return null},setCookieBlockedReasonToAttribute:function(e){switch(e){case"SecureOnly":case"OverwriteSecure":return D.Secure;case"SameSiteStrict":case"SameSiteLax":case"SameSiteUnspecifiedTreatedAsLax":case"SameSiteNoneInsecure":case"SchemefulSameSiteStrict":case"SchemefulSameSiteLax":case"SchemefulSameSiteUnspecifiedTreatedAsLax":return D.SameSite;case"InvalidDomain":return D.Domain;case"InvalidPrefix":return D.Name;case"SamePartyConflictsWithOtherAttributes":case"SamePartyFromCrossPartyContext":case"NameValuePairExceedsMaxSize":case"UserPreferences":case"SyntaxError":case"SchemeNotSupported":case"UnknownError":return null}return null}});class Le{static fromLocalObject(e){return new Fe(e)}static type(e){if(null===e)return"null";const t=typeof e;return"object"!==t&&"function"!==t?t:e.type}static isNullOrUndefined(e){if(void 0===e)return!0;switch(e.type){case"object":return"null"===e.subtype;case"undefined":return!0;default:return!1}}static arrayNameFromDescription(e){return e.replace(Ue,"").replace(He,"")}static arrayLength(e){if("array"!==e.subtype&&"typedarray"!==e.subtype)return 0;const t=e.description&&e.description.match(Ue),n=e.description&&e.description.match(He);return t?parseInt(t[1],10):n?parseInt(n[1],10):0}static arrayBufferByteLength(e){if("arraybuffer"!==e.subtype)return 0;const t=e.description&&e.description.match(Ue);return t?parseInt(t[1],10):0}static unserializableDescription(e){const t=typeof e;if("number"===t){const t=String(e);if(0===e&&1/e<0)return"-0";if("NaN"===t||"Infinity"===t||"-Infinity"===t)return t}return"bigint"===t?e+"n":null}static toCallArgument(e){const t=typeof e;if("undefined"===t)return{};const n=Le.unserializableDescription(e);if("number"===t)return null!==n?{unserializableValue:n}:{value:e};if("bigint"===t)return{unserializableValue:n};if("string"===t||"boolean"===t)return{value:e};if(!e)return{value:null};const r=e;if(e instanceof Le){const t=e.unserializableValue();if(void 0!==t)return{unserializableValue:t}}else if(void 0!==r.unserializableValue)return{unserializableValue:r.unserializableValue};return void 0!==r.objectId?{objectId:r.objectId}:{value:r.value}}static async loadFromObjectPerProto(e,t,n=!1){const r=await Promise.all([e.getAllProperties(!0,t,n),e.getOwnProperties(t,n)]),s=r[0].properties,i=r[1].properties,a=r[1].internalProperties;if(!i||!s)return{properties:null,internalProperties:null};const o=new Map,l=[];for(let e=0;e100){r+=",…";break}e&&(r+=", "),r+=t}return r+=t,r}get type(){return typeof this.valueInternal}get subtype(){return null===this.valueInternal?"null":Array.isArray(this.valueInternal)?"array":this.valueInternal instanceof Date?"date":void 0}get hasChildren(){return"object"==typeof this.valueInternal&&null!==this.valueInternal&&Boolean(Object.keys(this.valueInternal).length)}async getOwnProperties(e,t=!1){let n=this.children();return t&&(n=n.filter((e=>!function(e){const t=Number(e)>>>0;return String(t)===e}(e.name)))),{properties:n,internalProperties:null}}async getAllProperties(e,t,n=!1){return e?{properties:[],internalProperties:null}:await this.getOwnProperties(t,n)}children(){if(!this.hasChildren)return[];const e=this.valueInternal;return this.#in||(this.#in=Object.keys(e).map((function(t){let n=e[t];return n instanceof Le||(n=Le.fromLocalObject(n)),new Ne(t,n)}))),this.#in}arrayLength(){return Array.isArray(this.valueInternal)?this.valueInternal.length:0}async callFunction(e,t){const n=this.valueInternal,r=t?t.map((e=>e.value)):[];let s,i=!1;try{s=e.apply(n,r)}catch(e){i=!0}return{object:Le.fromLocalObject(s),wasThrown:i}}async callFunctionJSON(e,t){const n=this.valueInternal,r=t?t.map((e=>e.value)):[];let s;try{s=e.apply(n,r)}catch(e){s=null}return s}}class Be{#an;constructor(e){this.#an=e}static objectAsArray(e){if(!e||"object"!==e.type||"array"!==e.subtype&&"typedarray"!==e.subtype)throw new Error("Object is empty or not an array");return new Be(e)}static createFromRemoteObjects(e){if(!e.length)throw new Error("Input array is empty");const t=[];for(let n=0;n1)return new Array(arguments);return[arguments[0]]}),t).then((function(e){if(e.wasThrown||!e.object)throw new Error("Call function throws exceptions or returns empty value");return Be.objectAsArray(e.object)}))}at(e){if(e<0||e>this.#an.arrayLength())throw new Error("Out of range");return this.#an.callFunction((function(e){return this[e]}),[Le.toCallArgument(e)]).then((function(e){if(e.wasThrown||!e.object)throw new Error("Exception in callFunction or result value is empty");return e.object}))}length(){return this.#an.arrayLength()}map(e){const t=[];for(let n=0;n=this.byteLength())throw new RangeError("start is out of range");if(tthis.byteLength())throw new RangeError("end is out of range");return await this.#an.callFunctionJSON((function(e,t){return[...new Uint8Array(this,e,t)]}),[{value:e},{value:t-e}])}object(){return this.#an}},RemoteArray:Be,RemoteFunction:De});class _e{#on;#ln;#dn;#cn;#hn;constructor(e){this.#on=e.fontFamily,this.#ln=e.fontVariationAxes||[],this.#dn=new Map,this.#cn=e.src,this.#hn=e.fontDisplay;for(const e of this.#ln)this.#dn.set(e.tag,e)}getFontFamily(){return this.#on}getSrc(){return this.#cn}getFontDisplay(){return this.#hn}getVariationAxisByTag(e){return this.#dn.get(e)}}var ze=Object.freeze({__proto__:null,CSSFontFace:_e});class je{text="";range;styleSheetId;cssModel;constructor(e){this.cssModel=e}rebase(e){this.styleSheetId===e.styleSheetId&&this.range&&(e.oldRange.equal(this.range)?this.reinitialize(e.payload):this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}equal(e){return!!(this.styleSheetId&&this.range&&e.range)&&(this.styleSheetId===e.styleSheetId&&this.range.equal(e.range))}lineNumberInSource(){if(this.range)return this.header()?.lineNumberInSource(this.range.startLine)}columnNumberInSource(){if(this.range)return this.header()?.columnNumberInSource(this.range.startLine,this.range.startColumn)}header(){return this.styleSheetId?this.cssModel.styleSheetHeaderForId(this.styleSheetId):null}rawLocation(){const e=this.header();if(!e||void 0===this.lineNumberInSource())return null;const t=Number(this.lineNumberInSource());return new rn(e,t,this.columnNumberInSource())}}var We=Object.freeze({__proto__:null,CSSQuery:je});class Ve extends je{name;physicalAxes;logicalAxes;static parseContainerQueriesPayload(e,t){return t.map((t=>new Ve(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.name=e.name,this.physicalAxes=e.physicalAxes,this.logicalAxes=e.logicalAxes}active(){return!0}async getContainerForNode(e){const t=await this.cssModel.domModel().getContainerForNode(e,this.name,this.physicalAxes,this.logicalAxes);if(t)return new Ge(t)}}class Ge{containerNode;constructor(e){this.containerNode=e}async getContainerSizeDetails(){const e=await this.containerNode.domModel().cssModel().getComputedStyle(this.containerNode.id);if(!e)return;const t=e.get("container-type"),n=e.get("contain"),r=e.get("writing-mode");if(!t||!n||!r)return;const s=Ke(`${t} ${n}`),i=$e(s,r);let a,o;return"Both"!==i&&"Horizontal"!==i||(a=e.get("width")),"Both"!==i&&"Vertical"!==i||(o=e.get("height")),{queryAxis:s,physicalAxis:i,width:a,height:o}}}const Ke=e=>{const t=e.split(" ");let n=!1,r=!1;for(const e of t){if("size"===e)return"size";n=n||"inline-size"===e,r=r||"block-size"===e}return n&&r?"size":n?"inline-size":r?"block-size":""},$e=(e,t)=>{const n=t.startsWith("vertical");switch(e){case"":return"";case"size":return"Both";case"inline-size":return n?"Vertical":"Horizontal";case"block-size":return n?"Horizontal":"Vertical"}};var Qe=Object.freeze({__proto__:null,CSSContainerQuery:Ve,CSSContainerQueryContainer:Ge,getQueryAxis:Ke,getPhysicalAxisFromQueryAxis:$e});class Xe extends je{static parseLayerPayload(e,t){return t.map((t=>new Xe(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId}active(){return!0}}var Je=Object.freeze({__proto__:null,CSSLayer:Xe});class Ye{#un;#gn;constructor(e){this.#un=e.active,this.#gn=[];for(let t=0;tnew et(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){if(this.text=e.text,this.source=e.source,this.sourceURL=e.sourceURL||"",this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.mediaList=null,e.mediaList){this.mediaList=[];for(let t=0;tnew nt(e,t)))}constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId}active(){return!0}}var rt=Object.freeze({__proto__:null,CSSScope:nt});class st extends je{static parseSupportsPayload(e,t){return t.map((t=>new st(e,t)))}#yn=!0;constructor(e,t){super(e),this.reinitialize(t)}reinitialize(e){this.text=e.text,this.range=e.range?r.TextRange.TextRange.fromObject(e.range):null,this.styleSheetId=e.styleSheetId,this.#yn=e.active}active(){return this.#yn}}var it=Object.freeze({__proto__:null,CSSSupports:st});class at{ownerStyle;index;name;value;important;disabled;parsedOk;implicit;text;range;#yn;#vn;#fn;#In;#kn=[];constructor(e,t,n,s,i,a,o,l,d,c,h){if(this.ownerStyle=e,this.index=t,this.name=n,this.value=s,this.important=i,this.disabled=a,this.parsedOk=o,this.implicit=l,this.text=d,this.range=c?r.TextRange.TextRange.fromObject(c):null,this.#yn=!0,this.#vn=null,this.#fn=null,h&&h.length>0)for(const n of h)this.#kn.push(new at(e,++t,n.name,n.value,i,a,o,!0));else{const r=v().getLonghands(n);for(const n of r||[])this.#kn.push(new at(e,++t,n,"",i,a,o,!0))}}static parsePayload(e,t,n){return new at(e,t,n.name,n.value,n.important||!1,n.disabled||!1,!("parsedOk"in n)||Boolean(n.parsedOk),Boolean(n.implicit),n.text,n.range,n.longhandProperties)}ensureRanges(){if(this.#vn&&this.#fn)return;const e=this.range,t=this.text?new r.Text.Text(this.text):null;if(!e||!t)return;const n=t.value().indexOf(this.name),s=t.value().lastIndexOf(this.value);if(-1===n||-1===s||n>s)return;const i=new r.TextRange.SourceRange(n,this.name.length),a=new r.TextRange.SourceRange(s,this.value.length);function o(e,t,n){return 0===e.startLine&&(e.startColumn+=n,e.endColumn+=n),e.startLine+=t,e.endLine+=t,e}this.#vn=o(t.toTextRange(i),e.startLine,e.startColumn),this.#fn=o(t.toTextRange(a),e.startLine,e.startColumn)}nameRange(){return this.ensureRanges(),this.#vn}valueRange(){return this.ensureRanges(),this.#fn}rebase(e){this.ownerStyle.styleSheetId===e.styleSheetId&&this.range&&(this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}setActive(e){this.#yn=e}get propertyText(){return void 0!==this.text?this.text:""===this.name?"":this.name+": "+this.value+(this.important?" !important":"")+";"}activeInStyle(){return this.#yn}trimmedValueWithoutImportant(){const e="!important";return this.value.endsWith(e)?this.value.slice(0,-e.length).trim():this.value.trim()}async setText(n,s,a){if(!this.ownerStyle)throw new Error("No ownerStyle for property");if(!this.ownerStyle.styleSheetId)throw new Error("No owner style id");if(!this.range||!this.ownerStyle.range)throw new Error("Style not editable");if(s&&(i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited),this.name.startsWith("--")&&i.userMetrics.actionTaken(i.UserMetrics.Action.CustomPropertyEdited)),a&&n===this.propertyText)return this.ownerStyle.cssModel().domModel().markUndoableState(!s),!0;const o=this.range.relativeTo(this.ownerStyle.range.startLine,this.ownerStyle.range.startColumn),l=this.ownerStyle.cssText?this.detectIndentation(this.ownerStyle.cssText):e.Settings.Settings.instance().moduleSetting("textEditorIndent").get(),d=this.ownerStyle.cssText?l.substring(0,this.ownerStyle.range.endColumn):"",c=new r.Text.Text(this.ownerStyle.cssText||"").replaceRange(o,t.StringUtilities.sprintf(";%s;",n)),h=await at.formatStyle(c,l,d);return this.ownerStyle.setText(h,s)}static async formatStyle(e,t,n){const s=t.substring(n.length)+t;t&&(t="\n"+t);let i="",a="",o="",l=!1,d=!1;const c=r.CodeMirrorUtils.createCssTokenizer();return await c("*{"+e+"}",(function(e,n){if(!l){const r=n?.includes("comment")&&function(e){const t=e.indexOf(":");if(-1===t)return!1;const n=e.substring(2,t).trim();return v().isCSSPropertyName(n)}(e),s=n?.includes("string")||n?.includes("meta")||n?.includes("property")||n?.includes("variableName")&&"variableName.function"!==n;return r?i=i.trimEnd()+t+e:s?(l=!0,o=e):(";"!==e||d)&&(i+=e,e.trim()&&!n?.includes("comment")&&(d=";"!==e)),void("{"!==e||n||(d=!1))}if("}"===e||";"===e){const n=o.trim();return i=i.trimEnd()+t+n+(n.endsWith(":")?" ":"")+e,d=!1,l=!1,void(a="")}if(v().isGridAreaDefiningProperty(a)){const t=b.exec(e);t&&0===t.index&&!o.trimEnd().endsWith("]")&&(o=o.trimEnd()+"\n"+s)}a||":"!==e||(a=o);o+=e})),l&&(i+=o),i=i.substring(2,i.length-1).trimEnd(),i+(t?"\n"+n:"")}detectIndentation(e){const t=e.split("\n");return t.length<2?"":r.TextUtils.Utils.lineIndent(t[1])}setValue(e,t,n,r){const s=this.name+": "+e+(this.important?" !important":"")+";";this.setText(s,t,n).then(r)}async setDisabled(e){if(!this.ownerStyle)return!1;if(e===this.disabled)return!0;if(!this.text)return!0;const t=this.text.trim(),n=e=>e+(e.endsWith(";")?"":";");let r;return r=e?"/* "+n(t)+" */":n(this.text.substring(2,t.length-2).trim()),this.setText(r,!0,!0)}setDisplayedStringForInvalidProperty(e){this.#In=e}getInvalidStringForInvalidProperty(){return this.#In}getLonghandProperties(){return this.#kn}}var ot,lt=Object.freeze({__proto__:null,CSSProperty:at});class dt{#Sn;parentRule;#wn;styleSheetId;range;cssText;#Cn;#Tn;#Rn;#xn;type;constructor(e,t,n,r){this.#Sn=e,this.parentRule=t,this.#Mn(n),this.type=r}rebase(e){if(this.styleSheetId===e.styleSheetId&&this.range)if(e.oldRange.equal(this.range))this.#Mn(e.payload);else{this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange);for(let t=0;t0||!l.validContent)continue;let s=0;for(const i of l.validContent.split(";")){const a=i.trim();if(a){let o,l;const d=a.indexOf(":");-1===d?(o=a,l=""):(o=a.substring(0,d).trim(),l=a.substring(d+1).trim());const c=new r.TextRange.TextRange(e,s,e,s+i.length);this.#wn.push(new at(this,this.#wn.length,o,l,!1,!1,!1,!1,i,c.relativeFrom(t,n)))}s+=i.length+1}}function d(e,t){t.validContent="";for(let n=0;n=0;--e)if(this.allProperties()[e].range)return e+1;return 0}#On(e){const t=this.propertyAt(e);if(t&&t.range)return t.range.collapseToStart();if(!this.range)throw new Error("CSSStyleDeclaration.range is null");return this.range.collapseToEnd()}newBlankProperty(e){e=void 0===e?this.pastLastSourcePropertyIndex():e;return new at(this,e,"","",!1,!1,!0,!1,"",this.#On(e))}setText(e,t){return this.range&&this.styleSheetId?this.#Sn.setStyleText(this.styleSheetId,this.range,e,t):Promise.resolve(!1)}insertPropertyAt(e,t,n,r){this.newBlankProperty(e).setText(t+": "+n+";",!1,!0).then(r)}appendProperty(e,t,n){this.insertPropertyAt(this.allProperties().length,e,t,n)}}!function(e){e.Regular="Regular",e.Inline="Inline",e.Attributes="Attributes"}(ot||(ot={}));var ct=Object.freeze({__proto__:null,CSSStyleDeclaration:dt,get Type(){return ot}});class ht{cssModelInternal;styleSheetId;sourceURL;origin;style;constructor(e,t){if(this.cssModelInternal=e,this.styleSheetId=t.styleSheetId,this.styleSheetId){const e=this.getStyleSheetHeader(this.styleSheetId);this.sourceURL=e.sourceURL}this.origin=t.origin,this.style=new dt(this.cssModelInternal,this,t.style,ot.Regular)}rebase(e){this.styleSheetId===e.styleSheetId&&this.style.rebase(e)}resourceURL(){if(!this.styleSheetId)return t.DevToolsPath.EmptyUrlString;return this.getStyleSheetHeader(this.styleSheetId).resourceURL()}isUserAgent(){return"user-agent"===this.origin}isInjected(){return"injected"===this.origin}isViaInspector(){return"inspector"===this.origin}isRegular(){return"regular"===this.origin}cssModel(){return this.cssModelInternal}getStyleSheetHeader(e){const t=this.cssModelInternal.styleSheetHeaderForId(e);return console.assert(null!==t),t}}class ut{text;range;specificity;constructor(e){this.text=e.text,e.range&&(this.range=r.TextRange.TextRange.fromObject(e.range)),e.specificity&&(this.specificity=e.specificity)}rebase(e){this.range&&(this.range=this.range.rebaseAfterTextEdit(e.oldRange,e.newRange))}}class gt extends ht{selectors;nestingSelectors;media;containerQueries;supports;scopes;layers;wasUsed;constructor(e,t,n){super(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId}),this.reinitializeSelectors(t.selectorList),this.nestingSelectors=t.nestingSelectors,this.media=t.media?et.parseMediaArrayPayload(e,t.media):[],this.containerQueries=t.containerQueries?Ve.parseContainerQueriesPayload(e,t.containerQueries):[],this.scopes=t.scopes?nt.parseScopesPayload(e,t.scopes):[],this.supports=t.supports?st.parseSupportsPayload(e,t.supports):[],this.layers=t.layers?Xe.parseLayerPayload(e,t.layers):[],this.wasUsed=n||!1}static createDummyRule(e,t){const n={selectorList:{text:"",selectors:[{text:t,value:void 0}]},style:{styleSheetId:"0",range:new r.TextRange.TextRange(0,0,0,0),shorthandEntries:[],cssProperties:[]},origin:"inspector"};return new gt(e,n)}reinitializeSelectors(e){this.selectors=[];for(let t=0;te.text)).join(", ")}selectorRange(){const e=this.selectors[0].range,t=this.selectors[this.selectors.length-1].range;return e&&t?new r.TextRange.TextRange(e.startLine,e.startColumn,t.endLine,t.endColumn):null}lineNumberInSource(e){const t=this.selectors[e];if(!t||!t.range||!this.styleSheetId)return 0;return this.getStyleSheetHeader(this.styleSheetId).lineNumberInSource(t.range.startLine)}columnNumberInSource(e){const t=this.selectors[e];if(!t||!t.range||!this.styleSheetId)return;return this.getStyleSheetHeader(this.styleSheetId).columnNumberInSource(t.range.startLine,t.range.startColumn)}rebase(e){if(this.styleSheetId!==e.styleSheetId)return;const t=this.selectorRange();if(t&&t.equal(e.oldRange))this.reinitializeSelectors(e.payload);else for(let t=0;tt.rebase(e))),this.containerQueries.forEach((t=>t.rebase(e))),this.scopes.forEach((t=>t.rebase(e))),this.supports.forEach((t=>t.rebase(e))),super.rebase(e)}}class pt{#Nn;#Fn;constructor(e,t){this.#Nn=new ut(t.animationName),this.#Fn=t.keyframes.map((t=>new mt(e,t)))}name(){return this.#Nn}keyframes(){return this.#Fn}}class mt extends ht{#Bn;constructor(e,t){super(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId}),this.reinitializeKey(t.keyText)}key(){return this.#Bn}reinitializeKey(e){this.#Bn=new ut(e)}rebase(e){this.styleSheetId===e.styleSheetId&&this.#Bn.range&&(e.oldRange.equal(this.#Bn.range)?this.reinitializeKey(e.payload):this.#Bn.rebase(e),super.rebase(e))}setKeyText(e){const t=this.styleSheetId;if(!t)throw"No rule stylesheet id";const n=this.#Bn.range;if(!n)throw"Keyframe key is not editable";return this.cssModelInternal.setKeyframeKey(t,n,e)}}class ft{#Dn;#Un;constructor(e,t){this.#Dn=new ut(t.name),this.#Un=t.tryRules.map((t=>new ht(e,{origin:t.origin,style:t.style,styleSheetId:t.styleSheetId})))}name(){return this.#Dn}tryRules(){return this.#Un}}var bt,yt=Object.freeze({__proto__:null,CSSRule:ht,CSSStyleRule:gt,CSSKeyframesRule:pt,CSSKeyframeRule:mt,CSSPositionFallbackRule:ft});function vt(e){const t=e.match(/var\(\s*(--(?:[\s\w\P{ASCII}-]|\\.)+),?\s*(.*)\s*\)/u);return{variableName:t&&t[1].trim(),fallback:t&&t[2]}}class It{#Sn;#Hn;#qn;#_n;#Fn;#zn;#jn;#Wn;#Vn;#Gn;#Kn;#$n;#Qn;constructor({cssModel:e,node:t,inlinePayload:n,attributesPayload:r,matchedPayload:s,pseudoPayload:i,inheritedPayload:a,inheritedPseudoPayload:o,animationsPayload:l,parentLayoutNodeId:d,positionFallbackRules:c}){this.#Sn=e,this.#Hn=t,this.#qn=new Map,this.#_n=new Map,this.#Fn=[],l&&(this.#Fn=l.map((t=>new pt(e,t)))),this.#Qn=c.map((t=>new ft(e,t))),this.#$n=d,this.#zn=new Map,this.#jn=new Set,s=h(s);for(const e of a)e.matchedCSSRules=h(e.matchedCSSRules);this.#Wn=this.buildMainCascade(n,r,s,a),[this.#Vn,this.#Gn]=this.buildPseudoCascades(i,o),this.#Kn=new Map;for(const e of Array.from(this.#Gn.values()).concat(Array.from(this.#Vn.values())).concat(this.#Wn))for(const t of e.styles())this.#Kn.set(t,e);function h(e){for(const t of e)s(t);const t=[];for(const s of e){const e=t[t.length-1];e&&"user-agent"===s.rule.origin&&"user-agent"===e.rule.origin&&s.rule.selectorList.text===e.rule.selectorList.text&&r(s)===r(e)?n(s,e):t.push(s)}return t;function n(e,t){const n=new Map,r=new Map;for(const e of t.rule.style.shorthandEntries)n.set(e.name,e.value);for(const e of t.rule.style.cssProperties)r.set(e.name,e.value);for(const t of e.rule.style.shorthandEntries)n.set(t.name,t.value);for(const t of e.rule.style.cssProperties)r.set(t.name,t.value);t.rule.style.shorthandEntries=[...n.entries()].map((([e,t])=>({name:e,value:t}))),t.rule.style.cssProperties=[...r.entries()].map((([e,t])=>({name:e,value:t})))}function r(e){return e.rule.media?e.rule.media.map((e=>e.text)).join(", "):null}function s(e){const{matchingSelectors:t,rule:n}=e;"user-agent"===n.origin&&t.length&&(n.selectorList.selectors=n.selectorList.selectors.filter(((e,n)=>t.includes(n))),n.selectorList.text=n.selectorList.selectors.map((e=>e.text)).join(", "),e.matchingSelectors=t.map(((e,t)=>t)))}}}buildMainCascade(e,t,n,r){const s=[],i=[];function a(){if(!t)return;const e=new dt(this.#Sn,null,t,ot.Attributes);this.#zn.set(e,this.#Hn),i.push(e)}if(e&&this.#Hn.nodeType()===Node.ELEMENT_NODE){const t=new dt(this.#Sn,null,e,ot.Inline);this.#zn.set(t,this.#Hn),i.push(t)}let o;for(let e=n.length-1;e>=0;--e){const t=new gt(this.#Sn,n[e].rule);!t.isInjected()&&!t.isUserAgent()||o||(o=!0,a.call(this)),this.#zn.set(t.style,this.#Hn),i.push(t.style),this.addMatchingSelectors(this.#Hn,t,n[e].matchingSelectors)}o||a.call(this),s.push(new kt(this,i,!1));let l=this.#Hn.parentNode;for(let e=0;l&&r&&e=0;--e){const n=new gt(this.#Sn,o[e].rule);this.addMatchingSelectors(l,n,o[e].matchingSelectors),this.containsInherited(n.style)&&(d(i,n.style)||d(this.#jn,n.style)||(this.#zn.set(n.style,l),t.push(n.style),this.#jn.add(n.style)))}l=l.parentNode,s.push(new kt(this,t,!0))}return new St(s);function d(e,t){if(!t.styleSheetId||!t.range)return!1;for(const n of e)if(t.styleSheetId===n.styleSheetId&&n.range&&t.range.equal(n.range))return!0;return!1}}buildSplitCustomHighlightCascades(e,t,n,r){const s=new Map;for(let r=e.length-1;r>=0;--r){const i=this.customHighlightNamesToMatchingSelectorIndices(e[r]);for(const[a,o]of i){const i=new gt(this.#Sn,e[r].rule);this.#zn.set(i.style,t),n&&this.#jn.add(i.style),this.addMatchingSelectors(t,i,o);const l=s.get(a);l?l.push(i.style):s.set(a,[i.style])}}for(const[e,t]of s){const s=new kt(this,t,n,!0),i=r.get(e);i?i.push(s):r.set(e,[s])}}customHighlightNamesToMatchingSelectorIndices(e){const t=new Map;for(let n=0;n=0;--e){const t=new gt(this.#Sn,o[e].rule);a.push(t.style);const s=v().isHighlightPseudoType(n.pseudoType)?this.#Hn:r;this.#zn.set(t.style,s),s&&this.addMatchingSelectors(s,t,o[e].matchingSelectors)}const e=v().isHighlightPseudoType(n.pseudoType),t=new kt(this,a,!1,e);s.set(n.pseudoType,[t])}}if(t){let e=this.#Hn.parentNode;for(let n=0;e&&n=0;--n){const r=new gt(this.#Sn,a[n].rule);t.push(r.style),this.#zn.set(r.style,e),this.#jn.add(r.style),this.addMatchingSelectors(e,r,a[n].matchingSelectors)}const r=v().isHighlightPseudoType(n.pseudoType),i=new kt(this,t,!0,r),o=s.get(n.pseudoType);o?o.push(i):s.set(n.pseudoType,[i])}}e=e.parentNode}}for(const[e,t]of s.entries())n.set(e,new St(t));for(const[e,t]of i.entries())r.set(e,new St(t));return[n,r]}addMatchingSelectors(e,t,n){for(const r of n){const n=t.selectors[r];n&&this.setSelectorMatches(e,n.text,!0)}}node(){return this.#Hn}cssModel(){return this.#Sn}hasMatchingSelectors(e){return this.getMatchingSelectors(e).length>0&&this.queryMatches(e.style)}getParentLayoutNodeId(){return this.#$n}getMatchingSelectors(e){const t=this.nodeForStyle(e.style);if(!t||"number"!=typeof t.id)return[];const n=this.#_n.get(t.id);if(!n)return[];const r=[];for(let t=0;t=0;e--){const t=this.styles[e],n=t.parentRule;if((!n||n instanceof gt)&&(!n||this.#Xn.hasMatchingSelectors(n)))for(const e of t.allProperties()){const n=v();if(this.#Jn&&!this.#Yn&&!n.isPropertyInherited(e.name))continue;if(t.range&&!e.range)continue;if(!e.activeInStyle()){this.propertiesState.set(e,bt.Overloaded);continue}const r=n.canonicalPropertyName(e.name);this.updatePropertyState(e,r);for(const t of e.getLonghandProperties())n.isCSSPropertyName(t.name)&&this.updatePropertyState(t,t.name)}}}updatePropertyState(e,t){const n=this.activeProperties.get(t);!n?.important||e.important?(n&&this.propertiesState.set(n,bt.Overloaded),this.propertiesState.set(e,bt.Active),this.activeProperties.set(t,e)):this.propertiesState.set(e,bt.Overloaded)}}class St{#Zn;#er;#tr;#nr;#rr;#sr;constructor(e){this.#Zn=e,this.#er=new Map,this.#tr=new Map,this.#nr=new Map,this.#rr=!1,this.#sr=new Map;for(const t of e)for(const e of t.styles)this.#sr.set(e,t)}findAvailableCSSVariables(e){const t=this.#sr.get(e);if(!t)return[];this.ensureInitialized();const n=this.#tr.get(t);return n?Array.from(n.keys()):[]}computeCSSVariable(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);return r&&s?this.innerComputeCSSVariable(r,s,t):null}computeValue(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);return r&&s?this.innerComputeValue(r,s,t):null}computeSingleVariableValue(e,t){const n=this.#sr.get(e);if(!n)return null;this.ensureInitialized();const r=this.#tr.get(n),s=this.#nr.get(n);if(!r||!s)return null;const i=this.innerComputeValue(r,s,t),{variableName:a}=vt(t);return{computedValue:i,fromFallback:null!==a&&!r.has(a)}}innerComputeCSSVariable(e,t,n){if(!e.has(n))return null;if(t.has(n))return t.get(n)||null;t.set(n,null);const r=e.get(n);if(null==r)return null;const s=this.innerComputeValue(e,t,r);return t.set(n,s),s}innerComputeValue(e,t,n){const s=r.TextUtils.Utils.splitStringByRegexes(n,[f]),i=[];for(const n of s){if(-1===n.regexIndex){i.push(n.value);continue}const{variableName:r,fallback:s}=vt(n.value);if(!r)return null;const a=this.innerComputeCSSVariable(e,t,r);if(null===a&&!s)return null;null===a?i.push(s):i.push(a)}return i.map((e=>e?e.trim():"")).join(" ")}styles(){return Array.from(this.#sr.keys())}propertyState(e){return this.ensureInitialized(),this.#er.get(e)||null}reset(){this.#rr=!1,this.#er.clear(),this.#tr.clear(),this.#nr.clear()}ensureInitialized(){if(this.#rr)return;this.#rr=!0;const e=new Map;for(const t of this.#Zn){t.computeActiveProperties();for(const[n,r]of t.propertiesState){if(r===bt.Overloaded){this.#er.set(n,bt.Overloaded);continue}const t=v().canonicalPropertyName(n.name);e.has(t)?this.#er.set(n,bt.Overloaded):(e.set(t,n),this.#er.set(n,bt.Active))}}for(const[t,n]of e){const r=n.ownerStyle,s=n.getLonghandProperties();if(!s.length)continue;let i=!1;for(const t of s){const n=v().canonicalPropertyName(t.name),s=e.get(n);if(s&&s.ownerStyle===r){i=!0;break}}i||(e.delete(t),this.#er.set(n,bt.Overloaded))}const t=new Map;for(let e=this.#Zn.length-1;e>=0;--e){const n=this.#Zn[e],r=[];for(const e of n.activeProperties.entries()){const n=e[0],s=e[1];n.startsWith("--")&&(t.set(n,s.value),r.push(n))}const s=new Map(t),i=new Map;this.#tr.set(n,s),this.#nr.set(n,i);for(const e of r)t.delete(e),t.set(e,this.innerComputeCSSVariable(s,i,e))}}}!function(e){e.Active="Active",e.Overloaded="Overloaded"}(bt||(bt={}));var wt=Object.freeze({__proto__:null,parseCSSVariableNameAndFallback:vt,CSSMatchedStyles:It,get PropertyState(){return bt}});const Ct={couldNotFindTheOriginalStyle:"Could not find the original style sheet.",thereWasAnErrorRetrievingThe:"There was an error retrieving the source styles."},Tt=s.i18n.registerUIStrings("core/sdk/CSSStyleSheetHeader.ts",Ct),Rt=s.i18n.getLocalizedString.bind(void 0,Tt);class xt{#Sn;id;frameId;sourceURL;hasSourceURL;origin;title;disabled;isInline;isMutable;isConstructed;startLine;startColumn;endLine;endColumn;contentLength;ownerNode;sourceMapURL;loadingFailed;#ir;constructor(e,t){this.#Sn=e,this.id=t.styleSheetId,this.frameId=t.frameId,this.sourceURL=t.sourceURL,this.hasSourceURL=Boolean(t.hasSourceURL),this.origin=t.origin,this.title=t.title,this.disabled=t.disabled,this.isInline=t.isInline,this.isMutable=t.isMutable,this.isConstructed=t.isConstructed,this.startLine=t.startLine,this.startColumn=t.startColumn,this.endLine=t.endLine,this.endColumn=t.endColumn,this.contentLength=t.length,t.ownerNode&&(this.ownerNode=new Rn(e.target(),t.ownerNode)),this.sourceMapURL=t.sourceMapURL,this.loadingFailed=t.loadingFailed??!1,this.#ir=null}originalContentProvider(){if(!this.#ir){const e=async()=>{const e=await this.#Sn.originalStyleSheetText(this);return null===e?{content:null,error:Rt(Ct.couldNotFindTheOriginalStyle),isEncoded:!1}:{content:e,isEncoded:!1}};this.#ir=new r.StaticContentProvider.StaticContentProvider(this.contentURL(),this.contentType(),e)}return this.#ir}setSourceMapURL(e){this.sourceMapURL=e}cssModel(){return this.#Sn}isAnonymousInlineStyleSheet(){return!this.resourceURL()&&!this.#Sn.sourceMapManager().sourceMapForClient(this)}isConstructedByNew(){return this.isConstructed&&0===this.sourceURL.length}resourceURL(){const e=this.isViaInspector()?this.viaInspectorResourceURL():this.sourceURL;return!e&&o.Runtime.experiments.isEnabled(o.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)?this.dynamicStyleURL():e}getFrameURLPath(){const t=this.#Sn.target().model(jn);if(console.assert(Boolean(t)),!t)return"";const n=t.frameForId(this.frameId);if(!n)return"";console.assert(Boolean(n));const r=new e.ParsedURL.ParsedURL(n.url);let s=r.host+r.folderPathComponents;return s.endsWith("/")||(s+="/"),s}viaInspectorResourceURL(){return`inspector://${this.getFrameURLPath()}inspector-stylesheet`}dynamicStyleURL(){return`stylesheet://${this.getFrameURLPath()}style#${this.id}`}lineNumberInSource(e){return this.startLine+e}columnNumberInSource(e,t){return(e?0:this.startColumn)+t}containsLocation(e,t){const n=e===this.startLine&&t>=this.startColumn||e>this.startLine,r=ee.isOutermostFrame()));this.#dr=e.length>0?e[0]:null}getFrame(e){const t=this.#or.get(e);return t?t.frame:null}getAllFrames(){return Array.from(this.#or.values(),(e=>e.frame))}getOutermostFrame(){return this.#dr}async getOrWaitForFrame(e,t){const n=this.getFrame(e);return!n||t&&t===n.resourceTreeModel().target()?new Promise((n=>{const r=this.#hr.get(e);r?r.push({notInTarget:t,resolve:n}):this.#hr.set(e,[{notInTarget:t,resolve:n}])})):n}resolveAwaitedFrame(e){const t=this.#hr.get(e.id);if(!t)return;const n=t.filter((({notInTarget:t,resolve:n})=>!(!t||t!==e.resourceTreeModel().target())||(n(e),!1)));n.length>0?this.#hr.set(e.id,n):this.#hr.delete(e.id)}}var Et;!function(e){e.FrameAddedToTarget="FrameAddedToTarget",e.FrameNavigated="FrameNavigated",e.FrameRemoved="FrameRemoved",e.ResourceAdded="ResourceAdded",e.OutermostFrameNavigated="OutermostFrameNavigated"}(Et||(Et={}));var At=Object.freeze({__proto__:null,FrameManager:Lt,get Events(){return Et}});class Ot extends c{constructor(e){super(e)}async read(t,n,r){const s=await this.target().ioAgent().invoke_read({handle:t,offset:r,size:n});if(s.getError())throw new Error(s.getError());return s.eof?null:s.base64Encoded?e.Base64.decode(s.data):s.data}async close(e){(await this.target().ioAgent().invoke_close({handle:e})).getError()&&console.error("Could not close stream.")}async resolveBlob(e){const t=e instanceof Le?e.objectId:e;if(!t)throw new Error("Remote object has undefined objectId");const n=await this.target().ioAgent().invoke_resolveBlob({objectId:t});if(n.getError())throw new Error(n.getError());return`blob:${n.uuid}`}async readToString(e){const t=[],n=new TextDecoder;for(;;){const r=await this.read(e,1048576);if(null===r){t.push(n.decode());break}r instanceof ArrayBuffer?t.push(n.decode(r,{stream:!0})):t.push(r)}return t.join("")}}c.register(Ot,{capabilities:z.IO,autostart:!0});var Nt=Object.freeze({__proto__:null,IOModel:Ot});const Ft={loadCanceledDueToReloadOf:"Load canceled due to reload of inspected page"},Bt=s.i18n.registerUIStrings("core/sdk/PageResourceLoader.ts",Ft),Dt=s.i18n.getLocalizedString.bind(void 0,Bt);let Ut=null;class Ht extends e.ObjectWrapper.ObjectWrapper{#ur;#gr;#pr;#mr;#fr;constructor(e,t){super(),this.#ur=0,this.#gr=t,this.#pr=new Map,this.#mr=[],K.instance().addModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),this.#fr=e}static instance({forceNew:e,loadOverride:t,maxConcurrentLoads:n}={forceNew:!1,loadOverride:null,maxConcurrentLoads:500}){return Ut&&!e||(Ut=new Ht(t,n)),Ut}static removeInstance(){Ut=null}onPrimaryPageChanged(e){if(e.data.frame.isOutermostFrame()){for(const{reject:e}of this.#mr)e(new Error(Dt(Ft.loadCanceledDueToReloadOf)));this.#mr=[],this.#pr.clear(),this.dispatchEventToListeners(_t.Update)}}getResourcesLoaded(){return this.#pr}getNumberOfResources(){return{loading:this.#ur,queued:this.#mr.length,resources:this.#pr.size}}async acquireLoadSlot(){if(this.#ur++,this.#ur>this.#gr){const e={resolve:()=>{},reject:()=>{}},t=new Promise(((t,n)=>{e.resolve=t,e.reject=n}));this.#mr.push(e),await t}}releaseLoadSlot(){this.#ur--;const e=this.#mr.shift();e&&e.resolve()}static makeKey(e,t){if(t.frameId)return`${e}-${t.frameId}`;if(t.target)return`${e}-${t.target.id()}`;throw new Error("Invalid initiator")}async loadResource(e,t){const n=Ht.makeKey(e,t),r={success:null,size:null,errorMessage:void 0,url:e,initiator:t};this.#pr.set(n,r),this.dispatchEventToListeners(_t.Update);try{await this.acquireLoadSlot();const n=this.dispatchLoad(e,t),s=await n;if(r.errorMessage=s.errorDescription.message,r.success=s.success,s.success)return r.size=s.content.length,{content:s.content};throw new Error(s.errorDescription.message)}catch(e){throw void 0===r.errorMessage&&(r.errorMessage=e.message),null===r.success&&(r.success=!1),e}finally{this.releaseLoadSlot(),this.dispatchEventToListeners(_t.Update)}}async dispatchLoad(t,n){let r=null;if(this.#fr)return this.#fr(t);const s=new e.ParsedURL.ParsedURL(t),a=qt().get()&&s&&"file"!==s.scheme&&"data"!==s.scheme&&"devtools"!==s.scheme;if(i.userMetrics.developerResourceScheme(this.getDeveloperResourceScheme(s)),a){try{if(n.target){i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageViaTarget);return await this.loadFromTarget(n.target,n.frameId,t)}const e=Lt.instance().getFrame(n.frameId);if(e){i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageViaFrame);return await this.loadFromTarget(e.resourceTreeModel().target(),n.frameId,t)}}catch(e){e instanceof Error&&(i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageFailure),r=e.message)}i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.LoadThroughPageFallback),console.warn("Fallback triggered",t,n)}else{const e=qt().get()?i.UserMetrics.DeveloperResourceLoaded.FallbackPerProtocol:i.UserMetrics.DeveloperResourceLoaded.FallbackPerOverride;i.userMetrics.developerResourceLoaded(e)}const o=await ue.instance().loadResource(t);return a&&!o.success&&i.userMetrics.developerResourceLoaded(i.UserMetrics.DeveloperResourceLoaded.FallbackFailure),r&&(o.errorDescription.message=`Fetch through target failed: ${r}; Fallback: ${o.errorDescription.message}`),o}getDeveloperResourceScheme(e){if(!e||""===e.scheme)return i.UserMetrics.DeveloperResourceScheme.SchemeUnknown;const t="localhost"===e.host||e.host.endsWith(".localhost");switch(e.scheme){case"file":return i.UserMetrics.DeveloperResourceScheme.SchemeFile;case"data":return i.UserMetrics.DeveloperResourceScheme.SchemeData;case"blob":return i.UserMetrics.DeveloperResourceScheme.SchemeBlob;case"http":return t?i.UserMetrics.DeveloperResourceScheme.SchemeHttpLocalhost:i.UserMetrics.DeveloperResourceScheme.SchemeHttp;case"https":return t?i.UserMetrics.DeveloperResourceScheme.SchemeHttpsLocalhost:i.UserMetrics.DeveloperResourceScheme.SchemeHttps}return i.UserMetrics.DeveloperResourceScheme.SchemeOther}async loadFromTarget(t,n,r){const s=t.model(ne),a=t.model(Ot),o=e.Settings.Settings.instance().moduleSetting("cacheDisabled").get(),l=await s.loadNetworkResource(n,r,{disableCache:o,includeCredentials:!0});try{const e=l.stream?await a.readToString(l.stream):"";return{success:l.success,content:e,errorDescription:{statusCode:l.httpStatusCode||0,netError:l.netError,netErrorName:l.netErrorName,message:i.ResourceLoader.netErrorToMessage(l.netError,l.httpStatusCode,l.netErrorName)||"",urlValid:void 0}}}finally{l.stream&&a.close(l.stream)}}}function qt(){return e.Settings.Settings.instance().createSetting("loadThroughTarget",!0)}var _t;(_t||(_t={})).Update="Update";var zt=Object.freeze({__proto__:null,PageResourceLoader:Ht,getLoadThroughTargetSetting:qt,get Events(){return _t}});function jt(e){return e.startsWith(")]}")&&(e=e.substring(e.indexOf("\n"))),65279===e.charCodeAt(0)&&(e=e.slice(1)),JSON.parse(e)}class Wt{lineNumber;columnNumber;sourceURL;sourceLineNumber;sourceColumnNumber;name;constructor(e,t,n,r,s,i){this.lineNumber=e,this.columnNumber=t,this.sourceURL=n,this.sourceLineNumber=r,this.sourceColumnNumber=s,this.name=i}static compare(e,t){return e.lineNumber!==t.lineNumber?e.lineNumber-t.lineNumber:e.columnNumber-t.columnNumber}}const Vt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",Gt=new Map;for(let e=0;e"url"in e))&&e.Console.Console.instance().warn(`SourceMap "${n}" contains unsupported "URL" field in one of its sections.`),this.eachSection(this.parseSources.bind(this))}compiledURL(){return this.#yr}url(){return this.#vr}sourceURLs(){return[...this.#Sr.keys()]}embeddedContentByURL(e){const t=this.#Sr.get(e);return t?t.content:null}findEntry(e,n){const r=this.mappings(),s=t.ArrayUtilities.upperBound(r,void 0,((t,r)=>e-r.lineNumber||n-r.columnNumber));return s?r[s-1]:null}findEntryRanges(e,n){const s=this.mappings(),i=t.ArrayUtilities.upperBound(s,void 0,((t,r)=>e-r.lineNumber||n-r.columnNumber));if(!i)return null;const a=i-1,o=s[a].sourceURL;if(!o)return null;const l=iu-s[t].sourceLineNumber||g-s[t].sourceColumnNumber));if(!p)return null;const m=p=i.length||s[i[a]].sourceLineNumber!==n)return null;const l=i.slice(a,o);if(!l.length)return null;const d=t.ArrayUtilities.lowerBound(l,r,((e,t)=>e-s[t].sourceColumnNumber));return d>=l.length?s[l[l.length-1]]:s[l[d]];function c(e,t){return e-s[t].sourceLineNumber}}findReverseIndices(e,n,r){const s=this.mappings(),i=this.reversedMappings(e),a=t.ArrayUtilities.upperBound(i,void 0,((e,t)=>n-s[t].sourceLineNumber||r-s[t].sourceColumnNumber));let o=a;for(;o>0&&s[i[o-1]].sourceLineNumber===s[i[a-1]].sourceLineNumber&&s[i[o-1]].sourceColumnNumber===s[i[a-1]].sourceColumnNumber;)--o;return i.slice(o,a)}findReverseEntries(e,t,n){const r=this.mappings();return this.findReverseIndices(e,t,n).map((e=>r[e]))}findReverseRanges(e,t,n){const s=this.mappings(),i=this.findReverseIndices(e,t,n),a=[];for(let e=0;e>=1,s?-t:t}reverseMapTextRanges(e,n){const s=this.reversedMappings(e),i=this.mappings();if(0===s.length)return[];let a=t.ArrayUtilities.lowerBound(s,n,(({startLine:e,startColumn:t},n)=>{const{sourceLineNumber:r,sourceColumnNumber:s}=i[n];return e-r||t-s}));for(;a===s.length||a>0&&(i[s[a]].sourceLineNumber>n.startLine||i[s[a]].sourceColumnNumber>n.startColumn);)a--;let o=a+1;for(;o0){const t=e[0];return 0===t?.lineNumber||0===t.columnNumber}return!1}hasIgnoreListHint(e){return this.#Sr.get(e)?.ignoreListHint??!1}findRanges(e,t){const n=this.mappings(),s=[];if(!n.length)return[];let i=null;0===n[0].lineNumber&&0===n[0].columnNumber||!t?.isStartMatching||(i=r.TextRange.TextRange.createUnboundedFromLocation(0,0),s.push(i));for(const{sourceURL:t,lineNumber:a,columnNumber:o}of n){const n=t&&e(t);i||!n?i&&!n&&(i.endLine=a,i.endColumn=o,i=null):(i=r.TextRange.TextRange.createUnboundedFromLocation(a,o),s.push(i))}return s}compatibleForURL(e,t){return this.embeddedContentByURL(e)===t.embeddedContentByURL(e)&&this.hasIgnoreListHint(e)===t.hasIgnoreListHint(e)}}!function(e){e._VLQ_BASE_SHIFT=5,e._VLQ_BASE_MASK=31,e._VLQ_CONTINUATION_MASK=32;e.StringCharIterator=class{string;position;constructor(e){this.string=e,this.position=0}next(){return this.string.charAt(this.position++)}peek(){return this.string.charAt(this.position)}hasNext(){return this.position{const n=new $t(i,a,e);return this.#Rr.get(t)===s&&(s.sourceMap=n,this.#xr.set(n,t),this.dispatchEventToListeners(Qt.SourceMapAttached,{client:t,sourceMap:n})),n}),(n=>{e.Console.Console.instance().warn(`DevTools failed to load source map: ${n.message}`),this.#Rr.get(t)===s&&this.dispatchEventToListeners(Qt.SourceMapFailedToAttach,{client:t})}))}}this.#Rr.set(t,s)}detachSourceMap(e){const t=this.#Rr.get(e);if(!t)return;if(this.#Rr.delete(e),!this.#Tr)return;const{sourceMap:n}=t;n?(this.#xr.delete(n),this.dispatchEventToListeners(Qt.SourceMapDetached,{client:e,sourceMap:n})):this.dispatchEventToListeners(Qt.SourceMapFailedToAttach,{client:e})}dispose(){K.instance().removeEventListener($.InspectedURLChanged,this.inspectedURLChanged,this)}}!function(e){e.SourceMapWillAttach="SourceMapWillAttach",e.SourceMapFailedToAttach="SourceMapFailedToAttach",e.SourceMapAttached="SourceMapAttached",e.SourceMapDetached="SourceMapDetached"}(Qt||(Qt={}));var Yt,Zt=Object.freeze({__proto__:null,SourceMapManager:Jt,get Events(){return Qt}});class en extends c{agent;#Mr;#Pr;#Lr;#Er;#Ar;#Or;#Nr;#Fr;#Br;#Dr;#Ur;#Hr;#qr;#Tr;#_r;#zr;constructor(t){super(t),this.#Tr=!1,this.#Dr=null,this.#Ur=null,this.#Mr=t.model(Pn),this.#Ar=new Jt(t),this.agent=t.cssAgent(),this.#Or=new an(this),this.#Er=t.model(jn),this.#Er&&this.#Er.addEventListener(_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),t.registerCSSDispatcher(new sn(this)),t.suspended()||this.enable(),this.#Br=new Map,this.#Fr=new Map,this.#Lr=new Map,this.#_r=!1,this.#Pr=new Map,this.#Hr=null,this.#qr=!1,this.#zr=!1,this.#Nr=new e.Throttler.Throttler(dn),this.#Ar.setEnabled(e.Settings.Settings.instance().moduleSetting("cssSourceMapsEnabled").get()),e.Settings.Settings.instance().moduleSetting("cssSourceMapsEnabled").addChangeListener((e=>this.#Ar.setEnabled(e.data)))}headersForSourceURL(e){const t=[];for(const n of this.getStyleSheetIdsForURL(e)){const e=this.styleSheetHeaderForId(n);e&&t.push(e)}return t}createRawLocationsByURL(e,n,r=0){const s=this.headersForSourceURL(e);s.sort((function(e,t){return e.startLine-t.startLine||e.startColumn-t.startColumn||e.id.localeCompare(t.id)}));const i=t.ArrayUtilities.upperBound(s,void 0,((e,t)=>n-t.startLine||r-t.startColumn));if(!i)return[];const a=[],o=s[i-1];for(let e=i-1;e>=0&&s[e].startLine===o.startLine&&s[e].startColumn===o.startColumn;--e)s[e].containsLocation(n,r)&&a.push(new rn(s[e],n,r));return a}sourceMapManager(){return this.#Ar}static readableLayerName(e){return e||""}static trimSourceURL(e){let t=e.lastIndexOf("/*# sourceURL=");if(-1===t&&(t=e.lastIndexOf("/*@ sourceURL="),-1===t))return e;const n=e.lastIndexOf("\n",t);if(-1===n)return e;const r=e.substr(n+1).split("\n",1)[0];return-1===r.search(/[\040\t]*\/\*[#@] sourceURL=[\040\t]*([^\s]*)[\040\t]*\*\/[\040\t]*$/)?e:e.substr(0,n)+e.substr(n+r.length+1)}domModel(){return this.#Mr}async setStyleText(e,t,n,r){try{await this.ensureOriginalStyleSheetText(e);const{styles:s}=await this.agent.invoke_setStyleTexts({edits:[{styleSheetId:e,range:t.serializeToObject(),text:n}]});if(!s||1!==s.length)return!1;this.#Mr.markUndoableState(!r);const i=new nn(e,t,n,s[0]);return this.fireStyleSheetChanged(e,i),!0}catch(e){return!1}}async setSelectorText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{selectorList:r}=await this.agent.invoke_setRuleSelector({styleSheetId:e,range:t,selector:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setKeyframeKey(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{keyText:r}=await this.agent.invoke_setKeyframeKey({styleSheetId:e,range:t,keyText:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}startCoverage(){return this.#_r=!0,this.agent.invoke_startRuleUsageTracking()}async takeCoverageDelta(){const e=await this.agent.invoke_takeCoverageDelta();return{timestamp:e&&e.timestamp||0,coverage:e&&e.coverage||[]}}setLocalFontsEnabled(e){return this.agent.invoke_setLocalFontsEnabled({enabled:e})}async stopCoverage(){this.#_r=!1,await this.agent.invoke_stopRuleUsageTracking()}async getMediaQueries(){const{medias:e}=await this.agent.invoke_getMediaQueries();return e?et.parseMediaArrayPayload(this,e):[]}async getRootLayer(e){const{rootLayer:t}=await this.agent.invoke_getLayersForNode({nodeId:e});return t}isEnabled(){return this.#Tr}async enable(){await this.agent.invoke_enable(),this.#Tr=!0,this.#_r&&await this.startCoverage(),this.dispatchEventToListeners(Yt.ModelWasEnabled)}async getMatchedStyles(e){const t=await this.agent.invoke_getMatchedStylesForNode({nodeId:e});if(t.getError())return null;const n=this.#Mr.nodeForId(e);return n?new It({cssModel:this,node:n,inlinePayload:t.inlineStyle||null,attributesPayload:t.attributesStyle||null,matchedPayload:t.matchedCSSRules||[],pseudoPayload:t.pseudoElements||[],inheritedPayload:t.inherited||[],inheritedPseudoPayload:t.inheritedPseudoElements||[],animationsPayload:t.cssKeyframesRules||[],parentLayoutNodeId:t.parentLayoutNodeId,positionFallbackRules:t.cssPositionFallbackRules||[]}):null}async getClassNames(e){const{classNames:t}=await this.agent.invoke_collectClassNames({styleSheetId:e});return t||[]}async getComputedStyle(e){return this.isEnabled()||await this.enable(),this.#Or.computedStylePromise(e)}async getBackgroundColors(e){const t=await this.agent.invoke_getBackgroundColors({nodeId:e});return t.getError()?null:{backgroundColors:t.backgroundColors||null,computedFontSize:t.computedFontSize||"",computedFontWeight:t.computedFontWeight||""}}async getPlatformFonts(e){const{fonts:t}=await this.agent.invoke_getPlatformFontsForNode({nodeId:e});return t}allStyleSheets(){const e=[...this.#Br.values()];return e.sort((function(e,t){return e.sourceURLt.sourceURL?1:e.startLine-t.startLine||e.startColumn-t.startColumn})),e}async getInlineStyles(e){const t=await this.agent.invoke_getInlineStylesForNode({nodeId:e});if(t.getError()||!t.inlineStyle)return null;const n=new dt(this,null,t.inlineStyle,ot.Inline),r=t.attributesStyle?new dt(this,null,t.attributesStyle,ot.Attributes):null;return new on(n,r)}forcePseudoState(e,n,r){const s=e.marker(tn)||[],i=s.includes(n);if(r){if(i)return!1;s.push(n),e.setMarker(tn,s)}else{if(!i)return!1;t.ArrayUtilities.removeElement(s,n),s.length?e.setMarker(tn,s):e.setMarker(tn,null)}return void 0!==e.id&&(this.agent.invoke_forcePseudoState({nodeId:e.id,forcedPseudoClasses:s}),this.dispatchEventToListeners(Yt.PseudoStateForced,{node:e,pseudoClass:n,enable:r}),!0)}pseudoState(e){return e.marker(tn)||[]}async setMediaText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{media:r}=await this.agent.invoke_setMediaText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setContainerQueryText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{containerQuery:r}=await this.agent.invoke_setContainerQueryText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setSupportsText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{supports:r}=await this.agent.invoke_setSupportsText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return!1}}async setScopeText(e,t,n){i.userMetrics.actionTaken(i.UserMetrics.Action.StyleRuleEdited);try{await this.ensureOriginalStyleSheetText(e);const{scope:r}=await this.agent.invoke_setScopeText({styleSheetId:e,range:t,text:n});if(!r)return!1;this.#Mr.markUndoableState();const s=new nn(e,t,n,r);return this.fireStyleSheetChanged(e,s),!0}catch(e){return console.error(e),!1}}async addRule(e,t,n){try{await this.ensureOriginalStyleSheetText(e);const{rule:r}=await this.agent.invoke_addRule({styleSheetId:e,ruleText:t,location:n});if(!r)return null;this.#Mr.markUndoableState();const s=new nn(e,n,t,r);return this.fireStyleSheetChanged(e,s),new gt(this,r)}catch(e){return null}}async requestViaInspectorStylesheet(e){const t=e.frameId()||(this.#Er&&this.#Er.mainFrame?this.#Er.mainFrame.id:null),n=[...this.#Br.values()].find((e=>e.frameId===t&&e.isViaInspector()));if(n)return n;if(!t)return null;try{const{styleSheetId:e}=await this.agent.invoke_createStyleSheet({frameId:t});return e&&this.#Br.get(e)||null}catch(e){return null}}mediaQueryResultChanged(){this.dispatchEventToListeners(Yt.MediaQueryResultChanged)}fontsUpdated(e){e&&this.#Pr.set(e.src,new _e(e)),this.dispatchEventToListeners(Yt.FontsUpdated)}fontFaces(){return[...this.#Pr.values()]}fontFaceForSource(e){return this.#Pr.get(e)}styleSheetHeaderForId(e){return this.#Br.get(e)||null}styleSheetHeaders(){return[...this.#Br.values()]}fireStyleSheetChanged(e,t){this.dispatchEventToListeners(Yt.StyleSheetChanged,{styleSheetId:e,edit:t})}ensureOriginalStyleSheetText(e){const t=this.styleSheetHeaderForId(e);if(!t)return Promise.resolve(null);let n=this.#Lr.get(t);return n||(n=this.getStyleSheetText(t.id),this.#Lr.set(t,n),this.originalContentRequestedForTest(t)),n}originalContentRequestedForTest(e){}originalStyleSheetText(e){return this.ensureOriginalStyleSheetText(e.id)}getAllStyleSheetHeaders(){return this.#Br.values()}styleSheetAdded(e){console.assert(!this.#Br.get(e.styleSheetId)),e.loadingFailed&&(e.hasSourceURL=!1,e.isConstructed=!0,e.isInline=!1,e.isMutable=!1,e.sourceURL="",e.sourceMapURL=void 0);const t=new xt(this,e);this.#Br.set(e.styleSheetId,t);const n=t.resourceURL();let r=this.#Fr.get(n);if(r||(r=new Map,this.#Fr.set(n,r)),r){let e=r.get(t.frameId);e||(e=new Set,r.set(t.frameId,e)),e.add(t.id)}this.#Ar.attachSourceMap(t,t.sourceURL,t.sourceMapURL),this.dispatchEventToListeners(Yt.StyleSheetAdded,t)}styleSheetRemoved(e){const t=this.#Br.get(e);if(console.assert(Boolean(t)),!t)return;this.#Br.delete(e);const n=t.resourceURL(),r=this.#Fr.get(n);if(console.assert(Boolean(r),"No frameId to styleSheetId map is available for given style sheet URL."),r){const s=r.get(t.frameId);s&&(s.delete(e),s.size||(r.delete(t.frameId),r.size||this.#Fr.delete(n)))}this.#Lr.delete(t),this.#Ar.detachSourceMap(t),this.dispatchEventToListeners(Yt.StyleSheetRemoved,t)}getStyleSheetIdsForURL(e){const t=this.#Fr.get(e);if(!t)return[];const n=[];for(const e of t.values())n.push(...e);return n}async setStyleSheetText(e,t,n){const r=this.#Br.get(e);if(!r)return"Unknown stylesheet in CSS.setStyleSheetText";t=en.trimSourceURL(t),r.hasSourceURL&&(t+="\n/*# sourceURL="+r.sourceURL+" */"),await this.ensureOriginalStyleSheetText(e);const s=(await this.agent.invoke_setStyleSheetText({styleSheetId:r.id,text:t})).sourceMapURL;return this.#Ar.detachSourceMap(r),r.setSourceMapURL(s),this.#Ar.attachSourceMap(r,r.sourceURL,r.sourceMapURL),null===s?"Error in CSS.setStyleSheetText":(this.#Mr.markUndoableState(!n),this.fireStyleSheetChanged(e),null)}async getStyleSheetText(e){try{const{text:t}=await this.agent.invoke_getStyleSheetText({styleSheetId:e});return t&&en.trimSourceURL(t)}catch(e){return null}}async onPrimaryPageChanged(e){e.data.frame.backForwardCacheDetails.restoredFromCache?(await this.suspendModel(),await this.resumeModel()):(this.resetStyleSheets(),this.resetFontFaces())}resetStyleSheets(){const e=[...this.#Br.values()];this.#Fr.clear(),this.#Br.clear();for(const t of e)this.#Ar.detachSourceMap(t),this.dispatchEventToListeners(Yt.StyleSheetRemoved,t)}resetFontFaces(){this.#Pr.clear()}async suspendModel(){this.#Tr=!1,await this.agent.invoke_disable(),this.resetStyleSheets(),this.resetFontFaces()}async resumeModel(){return this.enable()}setEffectivePropertyValueForNode(e,t,n){this.agent.invoke_setEffectivePropertyValueForNode({nodeId:e,propertyName:t,value:n})}cachedMatchedCascadeForNode(e){if(this.#Dr!==e&&this.discardCachedMatchedCascade(),this.#Dr=e,!this.#Ur){if(!e.id)return Promise.resolve(null);this.#Ur=this.getMatchedStyles(e.id)}return this.#Ur}discardCachedMatchedCascade(){this.#Dr=null,this.#Ur=null}createCSSPropertyTracker(e){return new ln(this,e)}enableCSSPropertyTracker(e){const t=e.getTrackedProperties();0!==t.length&&(this.agent.invoke_trackComputedStyleUpdates({propertiesToTrack:t}),this.#qr=!0,this.#Hr=e,this.pollComputedStyleUpdates())}disableCSSPropertyTracker(){this.#qr=!1,this.#Hr=null,this.agent.invoke_trackComputedStyleUpdates({propertiesToTrack:[]})}async pollComputedStyleUpdates(){if(!this.#zr){if(this.#qr){this.#zr=!0;const e=await this.agent.invoke_takeComputedStyleUpdates();if(this.#zr=!1,e.getError()||!e.nodeIds||!this.#qr)return;this.#Hr&&this.#Hr.dispatchEventToListeners(cn.TrackedCSSPropertiesUpdated,e.nodeIds.map((e=>this.#Mr.nodeForId(e))))}this.#qr&&this.#Nr.schedule(this.pollComputedStyleUpdates.bind(this))}}dispose(){this.disableCSSPropertyTracker(),super.dispose(),this.#Ar.dispose()}getAgent(){return this.agent}}!function(e){e.FontsUpdated="FontsUpdated",e.MediaQueryResultChanged="MediaQueryResultChanged",e.ModelWasEnabled="ModelWasEnabled",e.PseudoStateForced="PseudoStateForced",e.StyleSheetAdded="StyleSheetAdded",e.StyleSheetChanged="StyleSheetChanged",e.StyleSheetRemoved="StyleSheetRemoved"}(Yt||(Yt={}));const tn="pseudo-state-marker";class nn{styleSheetId;oldRange;newRange;newText;payload;constructor(e,t,n,s){this.styleSheetId=e,this.oldRange=t,this.newRange=r.TextRange.TextRange.fromEdit(t,n),this.newText=n,this.payload=s}}class rn{#Sn;styleSheetId;url;lineNumber;columnNumber;constructor(e,t,n){this.#Sn=e.cssModel(),this.styleSheetId=e.id,this.url=e.resourceURL(),this.lineNumber=t,this.columnNumber=n||0}cssModel(){return this.#Sn}header(){return this.#Sn.styleSheetHeaderForId(this.styleSheetId)}}class sn{#jr;constructor(e){this.#jr=e}mediaQueryResultChanged(){this.#jr.mediaQueryResultChanged()}fontsUpdated({font:e}){this.#jr.fontsUpdated(e)}styleSheetChanged({styleSheetId:e}){this.#jr.fireStyleSheetChanged(e)}styleSheetAdded({header:e}){this.#jr.styleSheetAdded(e)}styleSheetRemoved({styleSheetId:e}){this.#jr.styleSheetRemoved(e)}}class an{#jr;#Wr;constructor(e){this.#jr=e,this.#Wr=new Map}computedStylePromise(e){let t=this.#Wr.get(e);return t||(t=this.#jr.getAgent().invoke_getComputedStyleForNode({nodeId:e}).then((({computedStyle:t})=>{if(this.#Wr.delete(e),!t||!t.length)return null;const n=new Map;for(const e of t)n.set(e.name,e.value);return n})),this.#Wr.set(e,t),t)}}class on{inlineStyle;attributesStyle;constructor(e,t){this.inlineStyle=e,this.attributesStyle=t}}class ln extends e.ObjectWrapper.ObjectWrapper{#jr;#Vr;constructor(e,t){super(),this.#jr=e,this.#Vr=t}start(){this.#jr.enableCSSPropertyTracker(this)}stop(){this.#jr.disableCSSPropertyTracker()}getTrackedProperties(){return this.#Vr}}const dn=1e3;var cn;!function(e){e.TrackedCSSPropertiesUpdated="TrackedCSSPropertiesUpdated"}(cn||(cn={})),c.register(en,{capabilities:z.DOM,autostart:!0});var hn=Object.freeze({__proto__:null,CSSModel:en,get Events(){return Yt},Edit:nn,CSSLocation:rn,InlineStyleResult:on,CSSPropertyTracker:ln,get CSSPropertyTrackerEvents(){return cn}});class un{#Gr;#Kr;constructor(){const t="rgba";this.#Gr=[new e.Color.Legacy([.9607843137254902,.592156862745098,.5803921568627451,1],t),new e.Color.Legacy([.9411764705882353,.7490196078431373,.2980392156862745,1],t),new e.Color.Legacy([.8313725490196079,.9294117647058824,.19215686274509805,1],t),new e.Color.Legacy([.6196078431372549,.9215686274509803,.2784313725490196,1],t),new e.Color.Legacy([.3568627450980392,.8196078431372549,.8431372549019608,1],t),new e.Color.Legacy([.7372549019607844,.807843137254902,.984313725490196,1],t),new e.Color.Legacy([.7764705882352941,.7450980392156863,.9333333333333333,1],t),new e.Color.Legacy([.8156862745098039,.5803921568627451,.9176470588235294,1],t),new e.Color.Legacy([.9215686274509803,.5803921568627451,.8117647058823529,1],t)],this.#Kr=0}next(){const e=this.#Gr[this.#Kr];return this.#Kr++,this.#Kr>=this.#Gr.length&&(this.#Kr=0),e}}var gn=Object.freeze({__proto__:null,OverlayColorGenerator:un});class pn{#$r;#Qr;#Xr;#Jr;#Yr;#Zr;#Gr;#es;#ts;#ns;#rs;#ss;#is;#as;constructor(t,n=!0){this.#$r=t,this.#Qr=new Map,this.#Xr=new Map,this.#Jr=new Map,this.#Yr=new Map,this.#Zr=new Map,this.#Gr=new Map,this.#es=new un,this.#ts=new un,this.#ns=n,this.#rs=e.Settings.Settings.instance().moduleSetting("showGridLineLabels"),this.#rs.addChangeListener(this.onSettingChange,this),this.#ss=e.Settings.Settings.instance().moduleSetting("extendGridLines"),this.#ss.addChangeListener(this.onSettingChange,this),this.#is=e.Settings.Settings.instance().moduleSetting("showGridAreas"),this.#is.addChangeListener(this.onSettingChange,this),this.#as=e.Settings.Settings.instance().moduleSetting("showGridTrackSizes"),this.#as.addChangeListener(this.onSettingChange,this)}onSettingChange(){this.resetOverlay()}buildGridHighlightConfig(e){const t=this.colorOfGrid(e).asLegacyColor(),n=t.setAlpha(.1).asLegacyColor(),r=t.setAlpha(.3).asLegacyColor(),s=t.setAlpha(.8).asLegacyColor(),i=this.#ss.get(),a="lineNumbers"===this.#rs.get(),o=a,l="lineNames"===this.#rs.get();return{rowGapColor:r.toProtocolRGBA(),rowHatchColor:s.toProtocolRGBA(),columnGapColor:r.toProtocolRGBA(),columnHatchColor:s.toProtocolRGBA(),gridBorderColor:t.toProtocolRGBA(),gridBorderDash:!1,rowLineColor:t.toProtocolRGBA(),columnLineColor:t.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0,showGridExtensionLines:i,showPositiveLineNumbers:a,showNegativeLineNumbers:o,showLineNames:l,showAreaNames:this.#is.get(),showTrackSizes:this.#as.get(),areaBorderColor:t.toProtocolRGBA(),gridBackgroundColor:n.toProtocolRGBA()}}buildFlexContainerHighlightConfig(e){const t=this.colorOfFlex(e).asLegacyColor();return{containerBorder:{color:t.toProtocolRGBA(),pattern:"dashed"},itemSeparator:{color:t.toProtocolRGBA(),pattern:"dotted"},lineSeparator:{color:t.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:t.toProtocolRGBA()},crossDistributedSpace:{hatchColor:t.toProtocolRGBA()}}}buildScrollSnapContainerHighlightConfig(t){return{snapAreaBorder:{color:e.Color.PageHighlight.GridBorder.toProtocolRGBA(),pattern:"dashed"},snapportBorder:{color:e.Color.PageHighlight.GridBorder.toProtocolRGBA()},scrollMarginColor:e.Color.PageHighlight.Margin.toProtocolRGBA(),scrollPaddingColor:e.Color.PageHighlight.Padding.toProtocolRGBA()}}highlightGridInOverlay(e){this.#Qr.set(e,this.buildGridHighlightConfig(e)),this.updateHighlightsInOverlay()}isGridHighlighted(e){return this.#Qr.has(e)}colorOfGrid(e){let t=this.#Gr.get(e);return t||(t=this.#es.next(),this.#Gr.set(e,t)),t}setColorOfGrid(e,t){this.#Gr.set(e,t)}hideGridInOverlay(e){this.#Qr.has(e)&&(this.#Qr.delete(e),this.updateHighlightsInOverlay())}highlightScrollSnapInOverlay(e){this.#Xr.set(e,this.buildScrollSnapContainerHighlightConfig(e)),this.updateHighlightsInOverlay()}isScrollSnapHighlighted(e){return this.#Xr.has(e)}hideScrollSnapInOverlay(e){this.#Xr.has(e)&&(this.#Xr.delete(e),this.updateHighlightsInOverlay())}highlightFlexInOverlay(e){this.#Jr.set(e,this.buildFlexContainerHighlightConfig(e)),this.updateHighlightsInOverlay()}isFlexHighlighted(e){return this.#Jr.has(e)}colorOfFlex(e){let t=this.#Gr.get(e);return t||(t=this.#ts.next(),this.#Gr.set(e,t)),t}setColorOfFlex(e,t){this.#Gr.set(e,t)}hideFlexInOverlay(e){this.#Jr.has(e)&&(this.#Jr.delete(e),this.updateHighlightsInOverlay())}highlightContainerQueryInOverlay(e){this.#Yr.set(e,this.buildContainerQueryContainerHighlightConfig()),this.updateHighlightsInOverlay()}hideContainerQueryInOverlay(e){this.#Yr.has(e)&&(this.#Yr.delete(e),this.updateHighlightsInOverlay())}isContainerQueryHighlighted(e){return this.#Yr.has(e)}buildContainerQueryContainerHighlightConfig(){return{containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},descendantBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}}}highlightIsolatedElementInOverlay(e){this.#Zr.set(e,this.buildIsolationModeHighlightConfig()),this.updateHighlightsInOverlay()}hideIsolatedElementInOverlay(e){this.#Zr.has(e)&&(this.#Zr.delete(e),this.updateHighlightsInOverlay())}isIsolatedElementHighlighted(e){return this.#Zr.has(e)}buildIsolationModeHighlightConfig(){return{resizerColor:e.Color.IsolationModeHighlight.Resizer.toProtocolRGBA(),resizerHandleColor:e.Color.IsolationModeHighlight.ResizerHandle.toProtocolRGBA(),maskColor:e.Color.IsolationModeHighlight.Mask.toProtocolRGBA()}}hideAllInOverlay(){this.#Jr.clear(),this.#Qr.clear(),this.#Xr.clear(),this.#Yr.clear(),this.#Zr.clear(),this.updateHighlightsInOverlay()}refreshHighlights(){const e=this.updateHighlightsForDeletedNodes(this.#Qr),t=this.updateHighlightsForDeletedNodes(this.#Jr),n=this.updateHighlightsForDeletedNodes(this.#Xr),r=this.updateHighlightsForDeletedNodes(this.#Yr),s=this.updateHighlightsForDeletedNodes(this.#Zr);(t||e||n||r||s)&&this.updateHighlightsInOverlay()}updateHighlightsForDeletedNodes(e){let t=!1;for(const n of e.keys())null===this.#$r.getDOMModel().nodeForId(n)&&(e.delete(n),t=!0);return t}resetOverlay(){for(const e of this.#Qr.keys())this.#Qr.set(e,this.buildGridHighlightConfig(e));for(const e of this.#Jr.keys())this.#Jr.set(e,this.buildFlexContainerHighlightConfig(e));for(const e of this.#Xr.keys())this.#Xr.set(e,this.buildScrollSnapContainerHighlightConfig(e));for(const e of this.#Yr.keys())this.#Yr.set(e,this.buildContainerQueryContainerHighlightConfig());for(const e of this.#Zr.keys())this.#Zr.set(e,this.buildIsolationModeHighlightConfig());this.updateHighlightsInOverlay()}updateHighlightsInOverlay(){const e=this.#Qr.size>0||this.#Jr.size>0||this.#Yr.size>0||this.#Zr.size>0;this.#$r.setShowViewportSizeOnResize(!e),this.updateGridHighlightsInOverlay(),this.updateFlexHighlightsInOverlay(),this.updateScrollSnapHighlightsInOverlay(),this.updateContainerQueryHighlightsInOverlay(),this.updateIsolatedElementHighlightsInOverlay()}updateGridHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Qr.entries())t.push({nodeId:e,gridHighlightConfig:n});e.target().overlayAgent().invoke_setShowGridOverlays({gridNodeHighlightConfigs:t})}updateFlexHighlightsInOverlay(){if(!this.#ns)return;const e=this.#$r,t=[];for(const[e,n]of this.#Jr.entries())t.push({nodeId:e,flexContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowFlexOverlays({flexNodeHighlightConfigs:t})}updateScrollSnapHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Xr.entries())t.push({nodeId:e,scrollSnapContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowScrollSnapOverlays({scrollSnapHighlightConfigs:t})}updateContainerQueryHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Yr.entries())t.push({nodeId:e,containerQueryContainerHighlightConfig:n});e.target().overlayAgent().invoke_setShowContainerQueryOverlays({containerQueryHighlightConfigs:t})}updateIsolatedElementHighlightsInOverlay(){const e=this.#$r,t=[];for(const[e,n]of this.#Zr.entries())t.push({nodeId:e,isolationModeHighlightConfig:n});e.target().overlayAgent().invoke_setShowIsolatedElements({isolatedElementHighlightConfigs:t})}}var mn=Object.freeze({__proto__:null,OverlayPersistentHighlighter:pn});const fn={pausedInDebugger:"Paused in debugger"},bn=s.i18n.registerUIStrings("core/sdk/OverlayModel.ts",fn),yn=s.i18n.getLocalizedString.bind(void 0,bn);class vn extends c{#Mr;overlayAgent;#os;#ls;#ds;#cs;#hs;#us;#gs;#ps;#ms;#fs;#bs;#ys;#vs;#Is;#ks;#Ss;#ws;constructor(t){super(t),this.#Mr=t.model(Pn),t.registerOverlayDispatcher(this),this.overlayAgent=t.overlayAgent(),this.#os=t.model(or),this.#os&&(e.Settings.Settings.instance().moduleSetting("disablePausedStateOverlay").addChangeListener(this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.DebuggerPaused,this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.DebuggerResumed,this.updatePausedInDebuggerMessage,this),this.#os.addEventListener(cr.GlobalObjectCleared,this.updatePausedInDebuggerMessage,this)),this.#ls=!1,this.#ds=null,this.#cs=new kn(this),this.#hs=this.#cs,this.#us=e.Settings.Settings.instance().moduleSetting("showPaintRects"),this.#gs=e.Settings.Settings.instance().moduleSetting("showLayoutShiftRegions"),this.#ps=e.Settings.Settings.instance().moduleSetting("showAdHighlights"),this.#ms=e.Settings.Settings.instance().moduleSetting("showDebugBorders"),this.#fs=e.Settings.Settings.instance().moduleSetting("showFPSCounter"),this.#bs=e.Settings.Settings.instance().moduleSetting("showScrollBottleneckRects"),this.#ys=e.Settings.Settings.instance().moduleSetting("showWebVitals"),this.#vs=[],this.#Is=!0,t.suspended()||(this.overlayAgent.invoke_enable(),this.wireAgentToSettings()),this.#ks=new pn(this),this.#Mr.addEventListener(wn.NodeRemoved,(()=>{this.#ks&&this.#ks.refreshHighlights()})),this.#Mr.addEventListener(wn.DocumentUpdated,(()=>{this.#ks&&this.#ks.hideAllInOverlay()})),this.#Ss=new Sn(this),this.#ws=!1}static highlightObjectAsDOMNode(e){const t=e.runtimeModel().target().model(Pn);t&&t.overlayModel().highlightInOverlay({object:e,selectorList:void 0})}static hideDOMNodeHighlight(){for(const e of K.instance().models(vn))e.delayedHideHighlight(0)}static async muteHighlight(){return Promise.all(K.instance().models(vn).map((e=>e.suspendModel())))}static async unmuteHighlight(){return Promise.all(K.instance().models(vn).map((e=>e.resumeModel())))}static highlightRect(e){for(const t of K.instance().models(vn))t.highlightRect(e)}static clearHighlight(){for(const e of K.instance().models(vn))e.clearHighlight()}getDOMModel(){return this.#Mr}highlightRect({x:e,y:t,width:n,height:r,color:s,outlineColor:i}){const a=s||{r:255,g:0,b:255,a:.3},o=i||{r:255,g:0,b:255,a:.5};return this.overlayAgent.invoke_highlightRect({x:e,y:t,width:n,height:r,color:a,outlineColor:o})}clearHighlight(){return this.overlayAgent.invoke_hideHighlight()}async wireAgentToSettings(){this.#vs=[this.#us.addChangeListener((()=>this.overlayAgent.invoke_setShowPaintRects({result:this.#us.get()}))),this.#gs.addChangeListener((()=>this.overlayAgent.invoke_setShowLayoutShiftRegions({result:this.#gs.get()}))),this.#ps.addChangeListener((()=>this.overlayAgent.invoke_setShowAdHighlights({show:this.#ps.get()}))),this.#ms.addChangeListener((()=>this.overlayAgent.invoke_setShowDebugBorders({show:this.#ms.get()}))),this.#fs.addChangeListener((()=>this.overlayAgent.invoke_setShowFPSCounter({show:this.#fs.get()}))),this.#bs.addChangeListener((()=>this.overlayAgent.invoke_setShowScrollBottleneckRects({show:this.#bs.get()}))),this.#ys.addChangeListener((()=>this.overlayAgent.invoke_setShowWebVitals({show:this.#ys.get()})))],this.#us.get()&&this.overlayAgent.invoke_setShowPaintRects({result:!0}),this.#gs.get()&&this.overlayAgent.invoke_setShowLayoutShiftRegions({result:!0}),this.#ps.get()&&this.overlayAgent.invoke_setShowAdHighlights({show:!0}),this.#ms.get()&&this.overlayAgent.invoke_setShowDebugBorders({show:!0}),this.#fs.get()&&this.overlayAgent.invoke_setShowFPSCounter({show:!0}),this.#bs.get()&&this.overlayAgent.invoke_setShowScrollBottleneckRects({show:!0}),this.#ys.get()&&this.overlayAgent.invoke_setShowWebVitals({show:!0}),this.#os&&this.#os.isPaused()&&this.updatePausedInDebuggerMessage(),await this.overlayAgent.invoke_setShowViewportSizeOnResize({show:this.#Is})}async suspendModel(){e.EventTarget.removeEventListeners(this.#vs),await this.overlayAgent.invoke_disable()}async resumeModel(){await Promise.all([this.overlayAgent.invoke_enable(),this.wireAgentToSettings()])}setShowViewportSizeOnResize(e){this.#Is!==e&&(this.#Is=e,this.target().suspended()||this.overlayAgent.invoke_setShowViewportSizeOnResize({show:e}))}updatePausedInDebuggerMessage(){if(this.target().suspended())return;const t=this.#os&&this.#os.isPaused()&&!e.Settings.Settings.instance().moduleSetting("disablePausedStateOverlay").get()?yn(fn.pausedInDebugger):void 0;this.overlayAgent.invoke_setPausedInDebuggerMessage({message:t})}setHighlighter(e){this.#hs=e||this.#cs}async setInspectMode(e,t=!0){await this.#Mr.requestDocument(),this.#ls="none"!==e,this.dispatchEventToListeners(In.InspectModeWillBeToggled,this),this.#hs.setInspectMode(e,this.buildHighlightConfig("all",t))}inspectModeEnabled(){return this.#ls}highlightInOverlay(e,t,n){if(this.#ws)return;this.#ds&&(clearTimeout(this.#ds),this.#ds=null);const r=this.buildHighlightConfig(t);void 0!==n&&(r.showInfo=n),this.#hs.highlightInOverlay(e,r)}highlightInOverlayForTwoSeconds(e){this.highlightInOverlay(e),this.delayedHideHighlight(2e3)}highlightGridInPersistentOverlay(e){this.#ks&&(this.#ks.highlightGridInOverlay(e),this.dispatchEventToListeners(In.PersistentGridOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedGridInPersistentOverlay(e){return!!this.#ks&&this.#ks.isGridHighlighted(e)}hideGridInPersistentOverlay(e){this.#ks&&(this.#ks.hideGridInOverlay(e),this.dispatchEventToListeners(In.PersistentGridOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightScrollSnapInPersistentOverlay(e){this.#ks&&(this.#ks.highlightScrollSnapInOverlay(e),this.dispatchEventToListeners(In.PersistentScrollSnapOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedScrollSnapInPersistentOverlay(e){return!!this.#ks&&this.#ks.isScrollSnapHighlighted(e)}hideScrollSnapInPersistentOverlay(e){this.#ks&&(this.#ks.hideScrollSnapInOverlay(e),this.dispatchEventToListeners(In.PersistentScrollSnapOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightFlexContainerInPersistentOverlay(e){this.#ks&&(this.#ks.highlightFlexInOverlay(e),this.dispatchEventToListeners(In.PersistentFlexContainerOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedFlexContainerInPersistentOverlay(e){return!!this.#ks&&this.#ks.isFlexHighlighted(e)}hideFlexContainerInPersistentOverlay(e){this.#ks&&(this.#ks.hideFlexInOverlay(e),this.dispatchEventToListeners(In.PersistentFlexContainerOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightContainerQueryInPersistentOverlay(e){this.#ks&&(this.#ks.highlightContainerQueryInOverlay(e),this.dispatchEventToListeners(In.PersistentContainerQueryOverlayStateChanged,{nodeId:e,enabled:!0}))}isHighlightedContainerQueryInPersistentOverlay(e){return!!this.#ks&&this.#ks.isContainerQueryHighlighted(e)}hideContainerQueryInPersistentOverlay(e){this.#ks&&(this.#ks.hideContainerQueryInOverlay(e),this.dispatchEventToListeners(In.PersistentContainerQueryOverlayStateChanged,{nodeId:e,enabled:!1}))}highlightSourceOrderInOverlay(t){const n={parentOutlineColor:e.Color.SourceOrderHighlight.ParentOutline.toProtocolRGBA(),childOutlineColor:e.Color.SourceOrderHighlight.ChildOutline.toProtocolRGBA()};this.#Ss.highlightSourceOrderInOverlay(t,n)}colorOfGridInPersistentOverlay(e){return this.#ks?this.#ks.colorOfGrid(e).asString("hex"):null}setColorOfGridInPersistentOverlay(t,n){if(!this.#ks)return;const r=e.Color.parse(n);r&&(this.#ks.setColorOfGrid(t,r),this.#ks.resetOverlay())}colorOfFlexInPersistentOverlay(e){return this.#ks?this.#ks.colorOfFlex(e).asString("hex"):null}setColorOfFlexInPersistentOverlay(t,n){if(!this.#ks)return;const r=e.Color.parse(n);r&&(this.#ks.setColorOfFlex(t,r),this.#ks.resetOverlay())}hideSourceOrderInOverlay(){this.#Ss.hideSourceOrderHighlight()}setSourceOrderActive(e){this.#ws=e}sourceOrderModeActive(){return this.#ws}highlightIsolatedElementInPersistentOverlay(e){this.#ks&&this.#ks.highlightIsolatedElementInOverlay(e)}hideIsolatedElementInPersistentOverlay(e){this.#ks&&this.#ks.hideIsolatedElementInOverlay(e)}isHighlightedIsolatedElementInPersistentOverlay(e){return!!this.#ks&&this.#ks.isIsolatedElementHighlighted(e)}delayedHideHighlight(e){null===this.#ds&&(this.#ds=window.setTimeout((()=>this.highlightInOverlay({clear:!0})),e))}highlightFrame(e){this.#ds&&(clearTimeout(this.#ds),this.#ds=null),this.#hs.highlightFrame(e)}showHingeForDualScreen(e){if(e){const{x:t,y:n,width:r,height:s,contentColor:i,outlineColor:a}=e;this.overlayAgent.invoke_setShowHinge({hingeConfig:{rect:{x:t,y:n,width:r,height:s},contentColor:i,outlineColor:a}})}else this.overlayAgent.invoke_setShowHinge({})}buildHighlightConfig(t="all",n=!1){const r=e.Settings.Settings.instance().moduleSetting("showMetricsRulers").get(),s=e.Settings.Settings.instance().moduleSetting("colorFormat").get(),i={showInfo:"all"===t||"container-outline"===t,showRulers:r,showStyles:n,showAccessibilityInfo:n,showExtensionLines:r,gridHighlightConfig:{},flexContainerHighlightConfig:{},flexItemHighlightConfig:{},contrastAlgorithm:o.Runtime.experiments.isEnabled("APCA")?"apca":"aa"};"all"!==t&&"content"!==t||(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA()),"all"!==t&&"padding"!==t||(i.paddingColor=e.Color.PageHighlight.Padding.toProtocolRGBA()),"all"!==t&&"border"!==t||(i.borderColor=e.Color.PageHighlight.Border.toProtocolRGBA()),"all"!==t&&"margin"!==t||(i.marginColor=e.Color.PageHighlight.Margin.toProtocolRGBA()),"all"===t&&(i.eventTargetColor=e.Color.PageHighlight.EventTarget.toProtocolRGBA(),i.shapeColor=e.Color.PageHighlight.Shape.toProtocolRGBA(),i.shapeMarginColor=e.Color.PageHighlight.ShapeMargin.toProtocolRGBA(),i.gridHighlightConfig={rowGapColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA(),rowHatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),columnGapColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA(),columnHatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0},i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},itemSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},lineSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},crossDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},rowGapSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()},columnGapSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}},i.flexItemHighlightConfig={baseSizeBox:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA()},baseSizeBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},flexibilityArrow:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),t.endsWith("gap")&&(i.gridHighlightConfig={gridBorderColor:e.Color.PageHighlight.GridBorder.toProtocolRGBA(),gridBorderDash:!0},"gap"!==t&&"row-gap"!==t||(i.gridHighlightConfig.rowGapColor=e.Color.PageHighlight.GapBackground.toProtocolRGBA(),i.gridHighlightConfig.rowHatchColor=e.Color.PageHighlight.GapHatch.toProtocolRGBA()),"gap"!==t&&"column-gap"!==t||(i.gridHighlightConfig.columnGapColor=e.Color.PageHighlight.GapBackground.toProtocolRGBA(),i.gridHighlightConfig.columnHatchColor=e.Color.PageHighlight.GapHatch.toProtocolRGBA())),t.endsWith("gap")&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}},"gap"!==t&&"row-gap"!==t||(i.flexContainerHighlightConfig.rowGapSpace={hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}),"gap"!==t&&"column-gap"!==t||(i.flexContainerHighlightConfig.columnGapSpace={hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()})),"grid-areas"===t&&(i.gridHighlightConfig={rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0,columnLineDash:!0,showAreaNames:!0,areaBorderColor:e.Color.PageHighlight.GridAreaBorder.toProtocolRGBA()}),"grid-template-columns"===t&&(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA(),i.gridHighlightConfig={columnLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),columnLineDash:!0}),"grid-template-rows"===t&&(i.contentColor=e.Color.PageHighlight.Content.toProtocolRGBA(),i.gridHighlightConfig={rowLineColor:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),rowLineDash:!0}),"justify-content"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},mainDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}}),"align-content"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},crossDistributedSpace:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA(),fillColor:e.Color.PageHighlight.GapBackground.toProtocolRGBA()}}),"align-items"===t&&(i.flexContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},lineSeparator:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"},crossAlignment:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),"flexibility"===t&&(i.flexItemHighlightConfig={baseSizeBox:{hatchColor:e.Color.PageHighlight.GapHatch.toProtocolRGBA()},baseSizeBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dotted"},flexibilityArrow:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA()}}),"container-outline"===t&&(i.containerQueryContainerHighlightConfig={containerBorder:{color:e.Color.PageHighlight.LayoutLine.toProtocolRGBA(),pattern:"dashed"}});return new Set(["rgb","hsl","hex"]).has(s)&&(i.colorFormat=s),i}nodeHighlightRequested({nodeId:e}){const t=this.#Mr.nodeForId(e);t&&this.dispatchEventToListeners(In.HighlightNodeRequested,t)}static setInspectNodeHandler(e){vn.inspectNodeHandler=e}inspectNodeRequested({backendNodeId:t}){const n=new Rn(this.target(),t);vn.inspectNodeHandler?n.resolvePromise().then((e=>{e&&vn.inspectNodeHandler&&vn.inspectNodeHandler(e)})):e.Revealer.reveal(n),this.dispatchEventToListeners(In.ExitedInspectMode)}screenshotRequested({viewport:e}){this.dispatchEventToListeners(In.ScreenshotRequested,e),this.dispatchEventToListeners(In.ExitedInspectMode)}inspectModeCanceled(){this.dispatchEventToListeners(In.ExitedInspectMode)}static inspectNodeHandler=null;getOverlayAgent(){return this.overlayAgent}}var In;!function(e){e.InspectModeWillBeToggled="InspectModeWillBeToggled",e.ExitedInspectMode="InspectModeExited",e.HighlightNodeRequested="HighlightNodeRequested",e.ScreenshotRequested="ScreenshotRequested",e.PersistentGridOverlayStateChanged="PersistentGridOverlayStateChanged",e.PersistentFlexContainerOverlayStateChanged="PersistentFlexContainerOverlayStateChanged",e.PersistentScrollSnapOverlayStateChanged="PersistentScrollSnapOverlayStateChanged",e.PersistentContainerQueryOverlayStateChanged="PersistentContainerQueryOverlayStateChanged"}(In||(In={}));class kn{#$r;constructor(e){this.#$r=e}highlightInOverlay(e,t){const{node:n,deferredNode:r,object:s,selectorList:i}={node:void 0,deferredNode:void 0,object:void 0,selectorList:void 0,...e},a=n?n.id:void 0,o=r?r.backendNodeId():void 0,l=s?s.objectId:void 0;a||o||l?this.#$r.target().overlayAgent().invoke_highlightNode({highlightConfig:t,nodeId:a,backendNodeId:o,objectId:l,selector:i}):this.#$r.target().overlayAgent().invoke_hideHighlight()}async setInspectMode(e,t){await this.#$r.target().overlayAgent().invoke_setInspectMode({mode:e,highlightConfig:t})}highlightFrame(t){this.#$r.target().overlayAgent().invoke_highlightFrame({frameId:t,contentColor:e.Color.PageHighlight.Content.toProtocolRGBA(),contentOutlineColor:e.Color.PageHighlight.ContentOutline.toProtocolRGBA()})}}class Sn{#$r;constructor(e){this.#$r=e}highlightSourceOrderInOverlay(e,t){this.#$r.setSourceOrderActive(!0),this.#$r.setShowViewportSizeOnResize(!1),this.#$r.getOverlayAgent().invoke_highlightSourceOrder({sourceOrderConfig:t,nodeId:e.id})}hideSourceOrderHighlight(){this.#$r.setSourceOrderActive(!1),this.#$r.setShowViewportSizeOnResize(!0),this.#$r.clearHighlight()}}c.register(vn,{capabilities:z.DOM,autostart:!0});var wn,Cn=Object.freeze({__proto__:null,OverlayModel:vn,get Events(){return In},SourceOrderHighlighter:Sn});class Tn{#Cs;#Ts;ownerDocument;#Rs;id;index;#xs;#Ms;#Ps;#Ls;nodeValueInternal;#Es;#As;#Os;#Ns;#Fs;#Bs;#Ds;#Us;#Hs;assignedSlot;shadowRootsInternal;#qs;#_s;#zs;childNodeCountInternal;childrenInternal;nextSibling;previousSibling;firstChild;lastChild;parentNode;templateContentInternal;contentDocumentInternal;childDocumentPromiseForTesting;#js;publicId;systemId;internalSubset;name;value;constructor(e){this.#Cs=e,this.#Ts=this.#Cs.getAgent(),this.index=void 0,this.#Ds=null,this.#Us=new Map,this.#Hs=[],this.assignedSlot=null,this.shadowRootsInternal=[],this.#qs=new Map,this.#_s=new Map,this.#zs=0,this.childrenInternal=null,this.nextSibling=null,this.previousSibling=null,this.firstChild=null,this.lastChild=null,this.parentNode=null}static create(e,t,n,r){const s=new Tn(e);return s.init(t,n,r),s}init(e,t,n){if(this.#Ts=this.#Cs.getAgent(),this.ownerDocument=e,this.#Rs=t,this.id=n.nodeId,this.#xs=n.backendNodeId,this.#Cs.registerNode(this),this.#Ms=n.nodeType,this.#Ps=n.nodeName,this.#Ls=n.localName,this.nodeValueInternal=n.nodeValue,this.#Es=n.pseudoType,this.#As=n.pseudoIdentifier,this.#Os=n.shadowRootType,this.#Ns=n.frameId||null,this.#Fs=n.xmlVersion,this.#Bs=Boolean(n.isSVG),n.attributes&&this.setAttributesPayload(n.attributes),this.childNodeCountInternal=n.childNodeCount||0,n.shadowRoots)for(let e=0;ee.creation||null)),this.#Ds}get subtreeMarkerCount(){return this.#zs}domModel(){return this.#Cs}backendNodeId(){return this.#xs}children(){return this.childrenInternal?this.childrenInternal.slice():null}setChildren(e){this.childrenInternal=e}hasAttributes(){return this.#qs.size>0}childNodeCount(){return this.childNodeCountInternal}setChildNodeCount(e){this.childNodeCountInternal=e}hasShadowRoots(){return Boolean(this.shadowRootsInternal.length)}shadowRoots(){return this.shadowRootsInternal.slice()}templateContent(){return this.templateContentInternal||null}contentDocument(){return this.contentDocumentInternal||null}setContentDocument(e){this.contentDocumentInternal=e}isIframe(){return"IFRAME"===this.#Ps}isPortal(){return"PORTAL"===this.#Ps}importedDocument(){return this.#js||null}nodeType(){return this.#Ms}nodeName(){return this.#Ps}pseudoType(){return this.#Es}pseudoIdentifier(){return this.#As}hasPseudoElements(){return this.#Us.size>0}pseudoElements(){return this.#Us}beforePseudoElement(){return this.#Us.get("before")?.at(-1)}afterPseudoElement(){return this.#Us.get("after")?.at(-1)}markerPseudoElement(){return this.#Us.get("marker")?.at(-1)}backdropPseudoElement(){return this.#Us.get("backdrop")?.at(-1)}viewTransitionPseudoElements(){return[...this.#Us.get("view-transition")||[],...this.#Us.get("view-transition-group")||[],...this.#Us.get("view-transition-image-pair")||[],...this.#Us.get("view-transition-old")||[],...this.#Us.get("view-transition-new")||[]]}hasAssignedSlot(){return null!==this.assignedSlot}isInsertionPoint(){return!this.isXMLNode()&&("SHADOW"===this.#Ps||"CONTENT"===this.#Ps||"SLOT"===this.#Ps)}distributedNodes(){return this.#Hs}isInShadowTree(){return this.#Rs}ancestorShadowHost(){const e=this.ancestorShadowRoot();return e?e.parentNode:null}ancestorShadowRoot(){if(!this.#Rs)return null;let e=this;for(;e&&!e.isShadowRoot();)e=e.parentNode;return e}ancestorUserAgentShadowRoot(){const e=this.ancestorShadowRoot();return e&&e.shadowRootType()===Tn.ShadowRootTypes.UserAgent?e:null}isShadowRoot(){return Boolean(this.#Os)}shadowRootType(){return this.#Os||null}nodeNameInCorrectCase(){const e=this.shadowRootType();return e?"#shadow-root ("+e+")":this.localName()?this.localName().length!==this.nodeName().length?this.nodeName():this.localName():this.nodeName()}setNodeName(e,t){this.#Ts.invoke_setNodeName({nodeId:this.id,name:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}localName(){return this.#Ls}nodeValue(){return this.nodeValueInternal}setNodeValueInternal(e){this.nodeValueInternal=e}setNodeValue(e,t){this.#Ts.invoke_setNodeValue({nodeId:this.id,value:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null)}))}getAttribute(e){const t=this.#qs.get(e);return t?t.value:void 0}setAttribute(e,t,n){this.#Ts.invoke_setAttributesAsText({nodeId:this.id,text:t,name:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null)}))}setAttributeValue(e,t,n){this.#Ts.invoke_setAttributeValue({nodeId:this.id,name:e,value:t}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null)}))}setAttributeValuePromise(e,t){return new Promise((n=>this.setAttributeValue(e,t,n)))}attributes(){return[...this.#qs.values()]}async removeAttribute(e){(await this.#Ts.invoke_removeAttribute({nodeId:this.id,name:e})).getError()||(this.#qs.delete(e),this.#Cs.markUndoableState())}getChildNodes(e){this.childrenInternal?e(this.children()):this.#Ts.invoke_requestChildNodes({nodeId:this.id}).then((t=>{e(t.getError()?null:this.children())}))}async getSubtree(e,t){return(await this.#Ts.invoke_requestChildNodes({nodeId:this.id,depth:e,pierce:t})).getError()?null:this.childrenInternal}async getOuterHTML(){const{outerHTML:e}=await this.#Ts.invoke_getOuterHTML({nodeId:this.id});return e}setOuterHTML(e,t){this.#Ts.invoke_setOuterHTML({nodeId:this.id,outerHTML:e}).then((e=>{e.getError()||this.#Cs.markUndoableState(),t&&t(e.getError()||null)}))}removeNode(e){return this.#Ts.invoke_removeNode({nodeId:this.id}).then((t=>{t.getError()||this.#Cs.markUndoableState(),e&&e(t.getError()||null)}))}async copyNode(){const{outerHTML:e}=await this.#Ts.invoke_getOuterHTML({nodeId:this.id});return null!==e&&i.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(e),e}path(){function e(e){return(void 0!==e.index||e.isShadowRoot()&&e.parentNode)&&e.#Ps.length}const t=[];let n=this;for(;n&&e(n);){const e="number"==typeof n.index?n.index:n.shadowRootType()===Tn.ShadowRootTypes.UserAgent?"u":"a";t.push([e,n.#Ps]),n=n.parentNode}return t.reverse(),t.join(",")}isAncestor(e){if(!e)return!1;let t=e.parentNode;for(;t;){if(this===t)return!0;t=t.parentNode}return!1}isDescendant(e){return null!==e&&e.isAncestor(this)}frameOwnerFrameId(){return this.#Ns}frameId(){let e=this.parentNode||this;for(;!e.#Ns&&e.parentNode;)e=e.parentNode;return e.#Ns}setAttributesPayload(e){let t=!this.#qs||e.length!==2*this.#qs.size;const n=this.#qs||new Map;this.#qs=new Map;for(let r=0;rt!==e));n&&n.length>0?this.#Us.set(t,n):this.#Us.delete(t)}else{const t=this.shadowRootsInternal.indexOf(e);if(-1!==t)this.shadowRootsInternal.splice(t,1);else{if(!this.childrenInternal)throw new Error("DOMNode._children is expected to not be null.");if(-1===this.childrenInternal.indexOf(e))throw new Error("DOMNode._children is expected to contain the node to be removed.");this.childrenInternal.splice(this.childrenInternal.indexOf(e),1)}}e.parentNode=null,this.#zs-=e.#zs,e.#zs&&this.#Cs.dispatchEventToListeners(wn.MarkersChanged,this),this.renumber()}setChildrenPayload(e){this.childrenInternal=[];for(let t=0;t=0?this.childrenInternal[e-1]:null,t.parentNode=this}}addAttribute(e,t){const n={name:e,value:t,_node:this};this.#qs.set(e,n)}setAttributeInternal(e,t){const n=this.#qs.get(e);n?n.value=t:this.addAttribute(e,t)}removeAttributeInternal(e){this.#qs.delete(e)}copyTo(e,t,n){this.#Ts.invoke_copyTo({nodeId:this.id,targetNodeId:e.id,insertBeforeNodeId:t?t.id:void 0}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}moveTo(e,t,n){this.#Ts.invoke_moveTo({nodeId:this.id,targetNodeId:e.id,insertBeforeNodeId:t?t.id:void 0}).then((e=>{e.getError()||this.#Cs.markUndoableState(),n&&n(e.getError()||null,this.#Cs.nodeForId(e.nodeId))}))}isXMLNode(){return Boolean(this.#Fs)}setMarker(e,t){if(null!==t){if(this.parentNode&&!this.#_s.has(e))for(let e=this;e;e=e.parentNode)++e.#zs;this.#_s.set(e,t);for(let e=this;e;e=e.parentNode)this.#Cs.dispatchEventToListeners(wn.MarkersChanged,e)}else{if(!this.#_s.has(e))return;this.#_s.delete(e);for(let e=this;e;e=e.parentNode)--e.#zs;for(let e=this;e;e=e.parentNode)this.#Cs.dispatchEventToListeners(wn.MarkersChanged,e)}}marker(e){return this.#_s.get(e)||null}getMarkerKeysForTest(){return[...this.#_s.keys()]}traverseMarkers(e){!function t(n){if(n.#zs){for(const t of n.#_s.keys())e(n,t);if(n.childrenInternal)for(const e of n.childrenInternal)t(e)}}(this)}resolveURL(t){if(!t)return t;for(let n=this;n;n=n.parentNode)if(n instanceof Mn&&n.baseURL)return e.ParsedURL.ParsedURL.completeURL(n.baseURL,t);return null}highlight(e){this.#Cs.overlayModel().highlightInOverlay({node:this,selectorList:void 0},e)}highlightForTwoSeconds(){this.#Cs.overlayModel().highlightInOverlayForTwoSeconds({node:this,selectorList:void 0})}async resolveToObject(e){const{object:t}=await this.#Ts.invoke_resolveNode({nodeId:this.id,backendNodeId:void 0,objectGroup:e});return t&&this.#Cs.runtimeModelInternal.createRemoteObject(t)||null}async boxModel(){const{model:e}=await this.#Ts.invoke_getBoxModel({nodeId:this.id});return e}async setAsInspectedNode(){let e=this;for(e&&e.pseudoType()&&(e=e.parentNode);e;){let t=e.ancestorUserAgentShadowRoot();if(!t)break;if(t=e.ancestorShadowHost(),!t)break;e=t}if(!e)throw new Error("In DOMNode.setAsInspectedNode: node is expected to not be null.");await this.#Ts.invoke_setInspectedNode({nodeId:e.id})}enclosingElementOrSelf(){let e=this;return e&&e.nodeType()===Node.TEXT_NODE&&e.parentNode&&(e=e.parentNode),e&&e.nodeType()!==Node.ELEMENT_NODE&&(e=null),e}async scrollIntoView(){const e=this.enclosingElementOrSelf();if(!e)return;const t=await e.resolveToObject();t&&(t.callFunction((function(){this.scrollIntoViewIfNeeded(!0)})),t.release(),e.highlightForTwoSeconds())}async focus(){const e=this.enclosingElementOrSelf();if(!e)throw new Error("DOMNode.focus expects node to not be null.");const t=await e.resolveToObject();t&&(await t.callFunction((function(){this.focus()})),t.release(),e.highlightForTwoSeconds(),await this.#Cs.target().pageAgent().invoke_bringToFront())}simpleSelector(){const e=this.localName()||this.nodeName().toLowerCase();if(this.nodeType()!==Node.ELEMENT_NODE)return e;const t=this.getAttribute("type"),n=this.getAttribute("id"),r=this.getAttribute("class");if("input"===e&&t&&!n&&!r)return e+'[type="'+CSS.escape(t)+'"]';if(n)return e+"#"+CSS.escape(n);if(r){return("div"===e?"":e)+"."+r.trim().split(/\s+/g).map((e=>CSS.escape(e))).join(".")}return e}}!function(e){let t;!function(e){e.UserAgent="user-agent",e.Open="open",e.Closed="closed"}(t=e.ShadowRootTypes||(e.ShadowRootTypes={}))}(Tn||(Tn={}));class Rn{#Cs;#xs;constructor(e,t){this.#Cs=e.model(Pn),this.#xs=t}resolve(e){this.resolvePromise().then(e)}async resolvePromise(){const e=await this.#Cs.pushNodesByBackendIdsToFrontend(new Set([this.#xs]));return e&&e.get(this.#xs)||null}backendNodeId(){return this.#xs}domModel(){return this.#Cs}highlight(){this.#Cs.overlayModel().highlightInOverlay({deferredNode:this,selectorList:void 0})}}class xn{nodeType;nodeName;deferredNode;constructor(e,t,n,r){this.nodeType=n,this.nodeName=r,this.deferredNode=new Rn(e,t)}}class Mn extends Tn{body;documentElement;documentURL;baseURL;constructor(e,t){super(e),this.body=null,this.documentElement=null,this.init(this,!1,t),this.documentURL=t.documentURL||"",this.baseURL=t.baseURL||""}}class Pn extends c{agent;idToDOMNode=new Map;#Ws;#Vs;runtimeModelInternal;#Gs;#Ks;#$s;#Qs;#Xs;constructor(e){super(e),this.agent=e.domAgent(),this.#Ws=null,this.#Vs=new Set,e.registerDOMDispatcher(new Ln(this)),this.runtimeModelInternal=e.model(Cr),this.#Ks=null,e.suspended()||this.agent.invoke_enable({}),o.Runtime.experiments.isEnabled("captureNodeCreationStacks")&&this.agent.invoke_setNodeStackTracesEnabled({enable:!0})}runtimeModel(){return this.runtimeModelInternal}cssModel(){return this.target().model(en)}overlayModel(){return this.target().model(vn)}static cancelSearch(){for(const e of K.instance().models(Pn))e.cancelSearch()}scheduleMutationEvent(e){this.hasEventListeners(wn.DOMMutated)&&(this.#Gs=(this.#Gs||0)+1,Promise.resolve().then(function(e,t){if(!this.hasEventListeners(wn.DOMMutated)||this.#Gs!==t)return;this.dispatchEventToListeners(wn.DOMMutated,e)}.bind(this,e,this.#Gs)))}requestDocument(){return this.#Ws?Promise.resolve(this.#Ws):(this.#Ks||(this.#Ks=this.requestDocumentInternal()),this.#Ks)}async getOwnerNodeForFrame(e){const t=await this.agent.invoke_getFrameOwner({frameId:e});return t.getError()?null:new Rn(this.target(),t.backendNodeId)}async requestDocumentInternal(){const e=await this.agent.invoke_getDocument({});if(e.getError())return null;const{root:t}=e;if(this.#Ks=null,t&&this.setDocument(t),!this.#Ws)return console.error("No document"),null;const n=this.parentModel();if(n&&!this.#$s){await n.requestDocument();const e=this.target().model(jn)?.mainFrame;if(e){const t=await n.agent.invoke_getFrameOwner({frameId:e.id});!t.getError()&&t.nodeId&&(this.#$s=n.nodeForId(t.nodeId))}}if(this.#$s){const e=this.#$s.contentDocument();this.#$s.setContentDocument(this.#Ws),this.#$s.setChildren([]),this.#Ws?(this.#Ws.parentNode=this.#$s,this.dispatchEventToListeners(wn.NodeInserted,this.#Ws)):e&&this.dispatchEventToListeners(wn.NodeRemoved,{node:e,parent:this.#$s})}return this.#Ws}existingDocument(){return this.#Ws}async pushNodeToFrontend(e){await this.requestDocument();const{nodeId:t}=await this.agent.invoke_requestNode({objectId:e});return t?this.nodeForId(t):null}pushNodeByPathToFrontend(e){return this.requestDocument().then((()=>this.agent.invoke_pushNodeByPathToFrontend({path:e}))).then((({nodeId:e})=>e))}async pushNodesByBackendIdsToFrontend(e){await this.requestDocument();const t=[...e],{nodeIds:n}=await this.agent.invoke_pushNodesByBackendIdsToFrontend({backendNodeIds:t});if(!n)return null;const r=new Map;for(let e=0;e{if(!t)return;const n=this.idToDOMNode.get(e);n&&n.setAttributesPayload(t)&&(this.dispatchEventToListeners(wn.AttrModified,{node:n,name:"style"}),this.scheduleMutationEvent(n))}));this.#Vs.clear()}characterDataModified(e,t){const n=this.idToDOMNode.get(e);n?(n.setNodeValueInternal(t),this.dispatchEventToListeners(wn.CharacterDataModified,n),this.scheduleMutationEvent(n)):console.error("nodeId could not be resolved to a node")}nodeForId(e){return e&&this.idToDOMNode.get(e)||null}documentUpdated(){const e=this.#Ks;this.setDocument(null),this.parentModel()&&!e&&this.requestDocument()}setDocument(e){this.idToDOMNode=new Map,this.#Ws=e&&"nodeId"in e?new Mn(this,e):null,An.instance().dispose(this),this.parentModel()||this.dispatchEventToListeners(wn.DocumentUpdated,this)}setDetachedRoot(e){"#document"===e.nodeName?new Mn(this,e):Tn.create(this,null,!1,e)}setChildNodes(e,t){if(!e&&t.length)return void this.setDetachedRoot(t[0]);this.idToDOMNode.get(e)?.setChildrenPayload(t)}childNodeCountUpdated(e,t){const n=this.idToDOMNode.get(e);n?(n.setChildNodeCount(t),this.dispatchEventToListeners(wn.ChildNodeCountUpdated,n),this.scheduleMutationEvent(n)):console.error("nodeId could not be resolved to a node")}childNodeInserted(e,t,n){const r=this.idToDOMNode.get(e),s=this.idToDOMNode.get(t);if(!r)return void console.error("parentId could not be resolved to a node");const i=r.insertChild(s,n);this.idToDOMNode.set(i.id,i),this.dispatchEventToListeners(wn.NodeInserted,i),this.scheduleMutationEvent(i)}childNodeRemoved(e,t){const n=this.idToDOMNode.get(e),r=this.idToDOMNode.get(t);n&&r?(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r)):console.error("parentId or nodeId could not be resolved to a node")}shadowRootPushed(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=Tn.create(this,n.ownerDocument,!0,t);r.parentNode=n,this.idToDOMNode.set(r.id,r),n.shadowRootsInternal.unshift(r),this.dispatchEventToListeners(wn.NodeInserted,r),this.scheduleMutationEvent(r)}shadowRootPopped(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=this.idToDOMNode.get(t);r&&(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r))}pseudoElementAdded(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=Tn.create(this,n.ownerDocument,!1,t);r.parentNode=n,this.idToDOMNode.set(r.id,r);const s=r.pseudoType();if(!s)throw new Error("DOMModel._pseudoElementAdded expects pseudoType to be defined.");const i=n.pseudoElements().get(s);i?i.push(r):n.pseudoElements().set(s,[r]),this.dispatchEventToListeners(wn.NodeInserted,r),this.scheduleMutationEvent(r)}topLayerElementsUpdated(){this.dispatchEventToListeners(wn.TopLayerElementsChanged)}pseudoElementRemoved(e,t){const n=this.idToDOMNode.get(e);if(!n)return;const r=this.idToDOMNode.get(t);r&&(n.removeChild(r),this.unbind(r),this.dispatchEventToListeners(wn.NodeRemoved,{node:r,parent:n}),this.scheduleMutationEvent(r))}distributedNodesUpdated(e,t){const n=this.idToDOMNode.get(e);n&&(n.setDistributedNodePayloads(t),this.dispatchEventToListeners(wn.DistributedNodesChanged,n),this.scheduleMutationEvent(n))}unbind(e){this.idToDOMNode.delete(e.id);const t=e.children();for(let e=0;t&&ee||[]))}querySelector(e,t){return this.agent.invoke_querySelector({nodeId:e,selector:t}).then((({nodeId:e})=>e))}querySelectorAll(e,t){return this.agent.invoke_querySelectorAll({nodeId:e,selector:t}).then((({nodeIds:e})=>e))}getTopLayerElements(){return this.agent.invoke_getTopLayerElements().then((({nodeIds:e})=>e))}markUndoableState(e){An.instance().markUndoableState(this,e||!1)}async nodeForLocation(e,t,n){const r=await this.agent.invoke_getNodeForLocation({x:e,y:t,includeUserAgentShadowDOM:n});return r.getError()||!r.nodeId?null:this.nodeForId(r.nodeId)}async getContainerForNode(e,t,n,r){const{nodeId:s}=await this.agent.invoke_getContainerForNode({nodeId:e,containerName:t,physicalAxes:n,logicalAxes:r});return s?this.nodeForId(s):null}pushObjectAsNodeToFrontend(e){return e.isNode()&&e.objectId?this.pushNodeToFrontend(e.objectId):Promise.resolve(null)}suspendModel(){return this.agent.invoke_disable().then((()=>this.setDocument(null)))}async resumeModel(){await this.agent.invoke_enable({})}dispose(){An.instance().dispose(this)}parentModel(){const e=this.target().parentTarget();return e?e.model(Pn):null}getAgent(){return this.agent}registerNode(e){this.idToDOMNode.set(e.id,e)}}!function(e){e.AttrModified="AttrModified",e.AttrRemoved="AttrRemoved",e.CharacterDataModified="CharacterDataModified",e.DOMMutated="DOMMutated",e.NodeInserted="NodeInserted",e.NodeRemoved="NodeRemoved",e.DocumentUpdated="DocumentUpdated",e.ChildNodeCountUpdated="ChildNodeCountUpdated",e.DistributedNodesChanged="DistributedNodesChanged",e.MarkersChanged="MarkersChanged",e.TopLayerElementsChanged="TopLayerElementsChanged"}(wn||(wn={}));class Ln{#Mr;constructor(e){this.#Mr=e}documentUpdated(){this.#Mr.documentUpdated()}attributeModified({nodeId:e,name:t,value:n}){this.#Mr.attributeModified(e,t,n)}attributeRemoved({nodeId:e,name:t}){this.#Mr.attributeRemoved(e,t)}inlineStyleInvalidated({nodeIds:e}){this.#Mr.inlineStyleInvalidated(e)}characterDataModified({nodeId:e,characterData:t}){this.#Mr.characterDataModified(e,t)}setChildNodes({parentId:e,nodes:t}){this.#Mr.setChildNodes(e,t)}childNodeCountUpdated({nodeId:e,childNodeCount:t}){this.#Mr.childNodeCountUpdated(e,t)}childNodeInserted({parentNodeId:e,previousNodeId:t,node:n}){this.#Mr.childNodeInserted(e,t,n)}childNodeRemoved({parentNodeId:e,nodeId:t}){this.#Mr.childNodeRemoved(e,t)}shadowRootPushed({hostId:e,root:t}){this.#Mr.shadowRootPushed(e,t)}shadowRootPopped({hostId:e,rootId:t}){this.#Mr.shadowRootPopped(e,t)}pseudoElementAdded({parentId:e,pseudoElement:t}){this.#Mr.pseudoElementAdded(e,t)}pseudoElementRemoved({parentId:e,pseudoElementId:t}){this.#Mr.pseudoElementRemoved(e,t)}distributedNodesUpdated({insertionPointId:e,distributedNodes:t}){this.#Mr.distributedNodesUpdated(e,t)}topLayerElementsUpdated(){this.#Mr.topLayerElementsUpdated()}}let En;class An{#Js;#Kr;#Ys;constructor(){this.#Js=[],this.#Kr=0,this.#Ys=null}static instance(e={forceNew:null}){const{forceNew:t}=e;return En&&!t||(En=new An),En}async markUndoableState(e,t){this.#Ys&&e!==this.#Ys&&(this.#Ys.markUndoableState(),this.#Ys=null),t&&this.#Ys===e||(this.#Js=this.#Js.slice(0,this.#Kr),this.#Js.push(e),this.#Kr=this.#Js.length,t?this.#Ys=e:(await e.getAgent().invoke_markUndoableState(),this.#Ys=null))}async undo(){if(0===this.#Kr)return Promise.resolve();--this.#Kr,this.#Ys=null,await this.#Js[this.#Kr].getAgent().invoke_undo()}async redo(){if(this.#Kr>=this.#Js.length)return Promise.resolve();++this.#Kr,this.#Ys=null,await this.#Js[this.#Kr-1].getAgent().invoke_redo()}dispose(e){let n=0;for(let t=0;t{this.#ai.push(e),this.#Zs&&!this.#Zs.finished||this.innerRequestContent()}))}canonicalMimeType(){return this.contentType().canonicalMimeType()||this.mimeType}async searchInContent(e,t,n){if(!this.frameId)return[];if(this.request)return this.request.searchInContent(e,t,n);return(await this.#Er.target().pageAgent().invoke_searchInResource({frameId:this.frameId,url:this.url,query:e,caseSensitive:t,isRegex:n})).result||[]}async populateImageSource(e){const{content:t}=await this.requestContent(),n=this.#ii;e.src=r.ContentProvider.contentAsDataURL(t,this.#kt,n)||this.#mt}requestFinished(){this.#Zs&&this.#Zs.removeEventListener(Te.FinishedLoading,this.requestFinished,this),this.#ai.length&&this.innerRequestContent()}async innerRequestContent(){if(this.#oi)return;this.#oi=!0;let e=null;if(this.request){const t=await this.request.contentData();t.error||(this.#si=t.content,this.#ii=t.encoded,e={content:t.content,isEncoded:t.encoded})}if(!e){const t=await this.#Er.target().pageAgent().invoke_getResourceContent({frameId:this.frameId,url:this.url}),n=t.getError();n?(this.#si=null,e={content:null,error:n,isEncoded:!1}):(this.#si=t.content,e={content:t.content,isEncoded:t.base64Encoded}),this.#ii=t.base64Encoded}null===this.#si&&(this.#ii=!1);for(const t of this.#ai.splice(0))t(e);this.#oi=void 0}hasTextContent(){return!!this.#ei.isTextType()||this.#ei===e.ResourceType.resourceTypes.Other&&(Boolean(this.#si)&&!this.#ii)}frame(){return this.#Ce?this.#Er.frameForId(this.#Ce):null}statusCode(){return this.#Zs?this.#Zs.statusCode:0}}var Fn,Bn=Object.freeze({__proto__:null,Resource:Nn});class Dn extends c{#li;#di;#ci;constructor(e){super(e),this.#li="",this.#di="",this.#ci=new Set}updateSecurityOrigins(e){const t=this.#ci;this.#ci=e;for(const e of t)this.#ci.has(e)||this.dispatchEventToListeners(Fn.SecurityOriginRemoved,e);for(const e of this.#ci)t.has(e)||this.dispatchEventToListeners(Fn.SecurityOriginAdded,e)}securityOrigins(){return[...this.#ci]}mainSecurityOrigin(){return this.#li}unreachableMainSecurityOrigin(){return this.#di}setMainSecurityOrigin(e,t){this.#li=e,this.#di=t||null,this.dispatchEventToListeners(Fn.MainSecurityOriginChanged,{mainSecurityOrigin:this.#li,unreachableMainSecurityOrigin:this.#di})}}!function(e){e.SecurityOriginAdded="SecurityOriginAdded",e.SecurityOriginRemoved="SecurityOriginRemoved",e.MainSecurityOriginChanged="MainSecurityOriginChanged"}(Fn||(Fn={})),c.register(Dn,{capabilities:z.None,autostart:!1});var Un,Hn=Object.freeze({__proto__:null,SecurityOriginManager:Dn,get Events(){return Fn}});class qn extends c{#hi;#ui;constructor(e){super(e),this.#hi="",this.#ui=new Set}updateStorageKeys(e){const t=this.#ui;this.#ui=e;for(const e of t)this.#ui.has(e)||this.dispatchEventToListeners(Un.StorageKeyRemoved,e);for(const e of this.#ui)t.has(e)||this.dispatchEventToListeners(Un.StorageKeyAdded,e)}storageKeys(){return[...this.#ui]}mainStorageKey(){return this.#hi}setMainStorageKey(e){this.#hi=e,this.dispatchEventToListeners(Un.MainStorageKeyChanged,{mainStorageKey:this.#hi})}}!function(e){e.StorageKeyAdded="StorageKeyAdded",e.StorageKeyRemoved="StorageKeyRemoved",e.MainStorageKeyChanged="MainStorageKeyChanged"}(Un||(Un={})),c.register(qn,{capabilities:z.None,autostart:!1});var _n,zn=Object.freeze({__proto__:null,StorageKeyManager:qn,parseStorageKey:function(t){const n=t.split("^"),r={origin:e.ParsedURL.ParsedURL.extractOrigin(n[0]),components:new Map};for(let e=1;e{this.processCachedResources(e.getError()?null:e.frameTree),this.mainFrame&&this.processPendingEvents(this.mainFrame)}))}static frameForRequest(e){const t=ne.forRequest(e),n=t?t.target().model(jn):null;return n&&e.frameId?n.frameForId(e.frameId):null}static frames(){const e=[];for(const t of K.instance().models(jn))e.push(...t.frames());return e}static resourceForURL(e){for(const t of K.instance().models(jn)){const n=t.mainFrame,r=n?n.resourceForURL(e):null;if(r)return r}return null}static reloadAllPages(e,t){for(const n of K.instance().models(jn))n.target().parentTarget()?.type()!==_.Frame&&n.reloadPage(e,t)}async storageKeyForFrame(e){if(!this.framesInternal.has(e))return null;const t=await this.storageAgent.invoke_getStorageKeyForFrame({frameId:e});return"Frame tree node for given frame not found"===t.getError()?null:t.storageKey}domModel(){return this.target().model(Pn)}processCachedResources(e){e&&":"!==e.frame.url&&(this.dispatchEventToListeners(_n.WillLoadCachedResources),this.addFramesRecursively(null,e),this.target().setInspectedURL(e.frame.url)),this.#mi=!0;const t=this.target().model(Cr);t&&(t.setExecutionContextComparator(this.executionContextComparator.bind(this)),t.fireExecutionContextOrderChanged()),this.dispatchEventToListeners(_n.CachedResourcesLoaded,this)}cachedResourcesLoaded(){return this.#mi}addFrame(e,t){this.framesInternal.set(e.id,e),e.isMainFrame()&&(this.mainFrame=e),this.dispatchEventToListeners(_n.FrameAdded,e),this.updateSecurityOrigins(),this.updateStorageKeys()}frameAttached(e,t,n){const r=t&&this.framesInternal.get(t)||null;if(!this.#mi&&r)return null;if(this.framesInternal.has(e))return null;const s=new Wn(this,r,e,null,n||null);return t&&!r&&(s.crossTargetParentFrameId=t),s.isMainFrame()&&this.mainFrame&&this.frameDetached(this.mainFrame.id,!1),this.addFrame(s,!0),s}frameNavigated(e,t){const n=e.parentId&&this.framesInternal.get(e.parentId)||null;if(!this.#mi&&n)return;let r=this.framesInternal.get(e.id)||null;if(!r&&(r=this.frameAttached(e.id,e.parentId||null),console.assert(Boolean(r)),!r))return;this.dispatchEventToListeners(_n.FrameWillNavigate,r),r.navigate(e),t&&(r.backForwardCacheDetails.restoredFromCache="BackForwardCacheRestore"===t),this.dispatchEventToListeners(_n.FrameNavigated,r),r.isPrimaryFrame()&&this.primaryPageChanged(r,"Navigation");const s=r.resources();for(let e=0;e=0,"Unbalanced call to ResourceTreeModel.resumeReload()"),!this.#bi&&this.#fi){const{ignoreCache:e,scriptToEvaluateOnLoad:t}=this.#fi;this.reloadPage(e,t)}}reloadPage(e,t){if(this.#fi||this.dispatchEventToListeners(_n.PageReloadRequested,this),this.#bi)return void(this.#fi={ignoreCache:e,scriptToEvaluateOnLoad:t});this.#fi=null;const n=this.target().model(ne);n&&n.clearRequests(),this.dispatchEventToListeners(_n.WillReloadPage),this.agent.invoke_reload({ignoreCache:e,scriptToEvaluateOnLoad:t})}navigate(e){return this.agent.invoke_navigate({url:e})}async navigationHistory(){const e=await this.agent.invoke_getNavigationHistory();return e.getError()?null:{currentIndex:e.currentIndex,entries:e.entries}}navigateToHistoryEntry(e){this.agent.invoke_navigateToHistoryEntry({entryId:e.id})}setLifecycleEventsEnabled(e){return this.agent.invoke_setLifecycleEventsEnabled({enabled:e})}async fetchAppManifest(){const e=await this.agent.invoke_getAppManifest();return e.getError()?{url:e.url,data:null,errors:[]}:{url:e.url,data:e.data||null,errors:e.errors}}async getInstallabilityErrors(){return(await this.agent.invoke_getInstallabilityErrors()).installabilityErrors||[]}async getAppId(){return this.agent.invoke_getAppId()}executionContextComparator(e,t){function n(e){let t=e;const n=[];for(;t;)n.push(t),t=t.sameTargetParentFrame();return n.reverse()}if(e.target()!==t.target())return Mr.comparator(e,t);const r=e.frameId?n(this.frameForId(e.frameId)):[],s=t.frameId?n(this.frameForId(t.frameId)):[];let i,a;for(let e=0;;e++)if(!r[e]||!s[e]||r[e]!==s[e]){i=r[e],a=s[e];break}return!i&&a?-1:!a&&i?1:i&&a?i.id.localeCompare(a.id):Mr.comparator(e,t)}getSecurityOriginData(){const t=new Set;let n=null,r=null;for(const s of this.framesInternal.values()){const i=s.securityOrigin;if(i&&(t.add(i),s.isMainFrame()&&(n=i,s.unreachableUrl()))){r=new e.ParsedURL.ParsedURL(s.unreachableUrl()).securityOrigin()}}return{securityOrigins:t,mainSecurityOrigin:n,unreachableMainSecurityOrigin:r}}async getStorageKeyData(){const e=new Set;let t=null;for(const{isMainFrame:n,storageKey:r}of await Promise.all([...this.framesInternal.values()].map((e=>e.getStorageKey(!1).then((t=>({isMainFrame:e.isMainFrame(),storageKey:t})))))))n&&(t=r),r&&e.add(r);return{storageKeys:e,mainStorageKey:t}}updateSecurityOrigins(){const e=this.getSecurityOriginData();this.#gi.setMainSecurityOrigin(e.mainSecurityOrigin||"",e.unreachableMainSecurityOrigin||""),this.#gi.updateSecurityOrigins(e.securityOrigins)}async updateStorageKeys(){const e=await this.getStorageKeyData();this.#pi.setMainStorageKey(e.mainStorageKey||""),this.#pi.updateStorageKeys(e.storageKeys)}async getMainStorageKey(){return this.mainFrame?this.mainFrame.getStorageKey(!1):null}getMainSecurityOrigin(){const e=this.getSecurityOriginData();return e.mainSecurityOrigin||e.unreachableMainSecurityOrigin}onBackForwardCacheNotUsed(e){this.mainFrame&&this.mainFrame.id===e.frameId&&this.mainFrame.loaderId===e.loaderId?(this.mainFrame.setBackForwardCacheDetails(e),this.dispatchEventToListeners(_n.BackForwardCacheDetailsUpdated,this.mainFrame)):this.#yi.add(e)}onPrerenderAttemptCompleted(e){this.mainFrame&&this.mainFrame.id===e.initiatingFrameId?(this.mainFrame.setPrerenderFinalStatus(e.finalStatus),this.dispatchEventToListeners(_n.PrerenderingStatusUpdated,this.mainFrame),e.disallowedApiMethod&&this.mainFrame.setPrerenderDisallowedApiMethod(e.disallowedApiMethod)):this.#vi.add(e),this.dispatchEventToListeners(_n.PrerenderAttemptCompleted,e)}processPendingEvents(e){if(e.isMainFrame()){for(const t of this.#yi)if(e.id===t.frameId&&e.loaderId===t.loaderId){e.setBackForwardCacheDetails(t),this.#yi.delete(t);break}for(const t of this.#vi)if(e.id===t.initiatingFrameId){e.setPrerenderFinalStatus(t.finalStatus),t.disallowedApiMethod&&e.setPrerenderDisallowedApiMethod(t.disallowedApiMethod),this.#vi.delete(t);break}}}}!function(e){e.FrameAdded="FrameAdded",e.FrameNavigated="FrameNavigated",e.FrameDetached="FrameDetached",e.FrameResized="FrameResized",e.FrameWillNavigate="FrameWillNavigate",e.PrimaryPageChanged="PrimaryPageChanged",e.ResourceAdded="ResourceAdded",e.WillLoadCachedResources="WillLoadCachedResources",e.CachedResourcesLoaded="CachedResourcesLoaded",e.DOMContentLoaded="DOMContentLoaded",e.LifecycleEvent="LifecycleEvent",e.Load="Load",e.PageReloadRequested="PageReloadRequested",e.WillReloadPage="WillReloadPage",e.InterstitialShown="InterstitialShown",e.InterstitialHidden="InterstitialHidden",e.BackForwardCacheDetailsUpdated="BackForwardCacheDetailsUpdated",e.PrerenderingStatusUpdated="PrerenderingStatusUpdated",e.PrerenderAttemptCompleted="PrerenderAttemptCompleted",e.JavaScriptDialogOpening="JavaScriptDialogOpening"}(_n||(_n={}));class Wn{#$r;#ki;#E;crossTargetParentFrameId;#Te;#u;#mt;#Si;#wi;#Ci;#Ti;#Ri;#xi;#Mi;#Pi;#Li;#Ei;#Ai;resourcesMap;backForwardCacheDetails={restoredFromCache:void 0,explanations:[],explanationsTree:void 0};prerenderFinalStatus;prerenderDisallowedApiMethod;constructor(e,n,r,s,i){this.#$r=e,this.#ki=n,this.#E=r,this.crossTargetParentFrameId=null,this.#Te=s&&s.loaderId||"",this.#u=s&&s.name,this.#mt=s&&s.url||t.DevToolsPath.EmptyUrlString,this.#Si=s&&s.domainAndRegistry||"",this.#wi=s&&s.securityOrigin,this.#Ti=s&&s.unreachableUrl||t.DevToolsPath.EmptyUrlString,this.#Ri=s?.adFrameStatus,this.#xi=s&&s.secureContextType,this.#Mi=s&&s.crossOriginIsolatedContextType,this.#Pi=s&&s.gatedAPIFeatures,this.#Li=i,this.#Ei=null,this.#Ai=new Set,this.resourcesMap=new Map,this.prerenderFinalStatus=null,this.prerenderDisallowedApiMethod=null,this.#ki&&this.#ki.#Ai.add(this)}isSecureContext(){return null!==this.#xi&&this.#xi.startsWith("Secure")}getSecureContextType(){return this.#xi}isCrossOriginIsolated(){return null!==this.#Mi&&this.#Mi.startsWith("Isolated")}getCrossOriginIsolatedContextType(){return this.#Mi}getGatedAPIFeatures(){return this.#Pi}getCreationStackTraceData(){return{creationStackTrace:this.#Li,creationStackTraceTarget:this.#Ei||this.resourceTreeModel().target()}}navigate(e){this.#Te=e.loaderId,this.#u=e.name,this.#mt=e.url,this.#Si=e.domainAndRegistry,this.#wi=e.securityOrigin,this.getStorageKey(!0),this.#Ti=e.unreachableUrl||t.DevToolsPath.EmptyUrlString,this.#Ri=e?.adFrameStatus,this.#xi=e.secureContextType,this.#Mi=e.crossOriginIsolatedContextType,this.#Pi=e.gatedAPIFeatures,this.backForwardCacheDetails={restoredFromCache:void 0,explanations:[],explanationsTree:void 0};const n=this.resourcesMap.get(this.#mt);this.resourcesMap.clear(),this.removeChildFrames(),n&&n.loaderId===this.#Te&&this.addResource(n)}resourceTreeModel(){return this.#$r}get id(){return this.#E}get name(){return this.#u||""}get url(){return this.#mt}domainAndRegistry(){return this.#Si}async getAdScriptId(e){return(await this.#$r.agent.invoke_getAdScriptId({frameId:e})).adScriptId||null}get securityOrigin(){return this.#wi}getStorageKey(e){return this.#Ci&&!e||(this.#Ci=this.#$r.storageKeyForFrame(this.#E)),this.#Ci}unreachableUrl(){return this.#Ti}get loaderId(){return this.#Te}adFrameType(){return this.#Ri?.adFrameType||"none"}adFrameStatus(){return this.#Ri}get childFrames(){return[...this.#Ai]}sameTargetParentFrame(){return this.#ki}crossTargetParentFrame(){if(!this.crossTargetParentFrameId)return null;const e=this.#$r.target().parentTarget();if(e?.type()!==_.Frame)return null;const t=e.model(jn);return t&&t.framesInternal.get(this.crossTargetParentFrameId)||null}parentFrame(){return this.sameTargetParentFrame()||this.crossTargetParentFrame()}isMainFrame(){return!this.#ki}isOutermostFrame(){return this.#$r.target().parentTarget()?.type()!==_.Frame&&!this.#ki&&!this.crossTargetParentFrameId}isPrimaryFrame(){return!this.#ki&&this.#$r.target()===K.instance().primaryPageTarget()}removeChildFrame(e,t){this.#Ai.delete(e),e.remove(t)}removeChildFrames(){const e=this.#Ai;this.#Ai=new Set;for(const t of e)t.remove(!1)}remove(e){this.removeChildFrames(),this.#$r.framesInternal.delete(this.id),this.#$r.dispatchEventToListeners(_n.FrameDetached,{frame:this,isSwap:e})}addResource(e){this.resourcesMap.get(e.url)!==e&&(this.resourcesMap.set(e.url,e),this.#$r.dispatchEventToListeners(_n.ResourceAdded,e))}addRequest(e){let t=this.resourcesMap.get(e.url());t&&t.request===e||(t=new Nn(this.#$r,e,e.url(),e.documentURL,e.frameId,e.loaderId,e.resourceType(),e.mimeType,null,null),this.resourcesMap.set(t.url,t),this.#$r.dispatchEventToListeners(_n.ResourceAdded,t))}resources(){return Array.from(this.resourcesMap.values())}resourceForURL(e){const t=this.resourcesMap.get(e);if(t)return t;for(const t of this.#Ai){const n=t.resourceForURL(e);if(n)return n}return null}callForFrameResources(e){for(const t of this.resourcesMap.values())if(e(t))return!0;for(const t of this.#Ai)if(t.callForFrameResources(e))return!0;return!1}displayName(){if(this.isOutermostFrame())return s.i18n.lockedString("top");const t=new e.ParsedURL.ParsedURL(this.#mt).displayName;return t?this.#u?this.#u+" ("+t+")":t:s.i18n.lockedString("iframe")}async getOwnerDeferredDOMNode(){const e=this.parentFrame();return e?e.resourceTreeModel().domModel().getOwnerNodeForFrame(this.#E):null}async getOwnerDOMNodeOrDocument(){const e=await this.getOwnerDeferredDOMNode();return e?e.resolvePromise():this.isOutermostFrame()?this.resourceTreeModel().domModel().requestDocument():null}async highlight(){const e=this.parentFrame(),t=this.resourceTreeModel().target().parentTarget(),n=async e=>{const t=await e.getOwnerNodeForFrame(this.#E);t&&e.overlayModel().highlightInOverlay({deferredNode:t,selectorList:""},"all",!0)};if(e)return n(e.resourceTreeModel().domModel());if(t?.type()===_.Frame){const e=t.model(Pn);if(e)return n(e)}const r=await this.resourceTreeModel().domModel().requestDocument();r&&this.resourceTreeModel().domModel().overlayModel().highlightInOverlay({node:r,selectorList:""},"all",!0)}async getPermissionsPolicyState(){const e=await this.resourceTreeModel().target().pageAgent().invoke_getPermissionsPolicyState({frameId:this.#E});return e.getError()?null:e.states}async getOriginTrials(){const e=await this.resourceTreeModel().target().pageAgent().invoke_getOriginTrials({frameId:this.#E});return e.getError()?[]:e.originTrials}setCreationStackTrace(e){this.#Li=e.creationStackTrace,this.#Ei=e.creationStackTraceTarget}setBackForwardCacheDetails(e){this.backForwardCacheDetails.restoredFromCache=!1,this.backForwardCacheDetails.explanations=e.notRestoredExplanations,this.backForwardCacheDetails.explanationsTree=e.notRestoredExplanationsTree}getResourcesMap(){return this.resourcesMap}setPrerenderFinalStatus(e){this.prerenderFinalStatus=e}setPrerenderDisallowedApiMethod(e){this.prerenderDisallowedApiMethod=e}}class Vn{#Er;constructor(e){this.#Er=e}backForwardCacheNotUsed(e){this.#Er.onBackForwardCacheNotUsed(e)}domContentEventFired({timestamp:e}){this.#Er.dispatchEventToListeners(_n.DOMContentLoaded,e)}loadEventFired({timestamp:e}){this.#Er.dispatchEventToListeners(_n.Load,{resourceTreeModel:this.#Er,loadTime:e})}lifecycleEvent({frameId:e,name:t}){this.#Er.dispatchEventToListeners(_n.LifecycleEvent,{frameId:e,name:t})}frameAttached({frameId:e,parentFrameId:t,stack:n}){this.#Er.frameAttached(e,t,n)}frameNavigated({frame:e,type:t}){this.#Er.frameNavigated(e,t)}documentOpened({frame:e}){this.#Er.documentOpened(e)}frameDetached({frameId:e,reason:t}){this.#Er.frameDetached(e,"swap"===t)}frameStartedLoading({}){}frameStoppedLoading({}){}frameRequestedNavigation({}){}frameScheduledNavigation({}){}frameClearedScheduledNavigation({}){}navigatedWithinDocument({}){}frameResized(){this.#Er.dispatchEventToListeners(_n.FrameResized)}javascriptDialogOpening(e){this.#Er.dispatchEventToListeners(_n.JavaScriptDialogOpening,e),e.hasBrowserHandler||this.#Er.agent.invoke_handleJavaScriptDialog({accept:!1})}javascriptDialogClosed({}){}screencastFrame({}){}screencastVisibilityChanged({}){}interstitialShown(){this.#Er.isInterstitialShowing=!0,this.#Er.dispatchEventToListeners(_n.InterstitialShown)}interstitialHidden(){this.#Er.isInterstitialShowing=!1,this.#Er.dispatchEventToListeners(_n.InterstitialHidden)}windowOpen({}){}compilationCacheProduced({}){}fileChooserOpened({}){}downloadWillBegin({}){}downloadProgress(){}}class Gn{#Er;constructor(e){this.#Er=e}ruleSetUpdated(e){}ruleSetRemoved(e){}prerenderAttemptCompleted(e){this.#Er.onPrerenderAttemptCompleted(e)}prefetchStatusUpdated(e){}prerenderStatusUpdated(e){}preloadEnabledStateUpdated(e){}preloadingAttemptSourcesUpdated(){}}c.register(jn,{capabilities:z.DOM,autostart:!0,early:!0});var Kn=Object.freeze({__proto__:null,ResourceTreeModel:jn,get Events(){return _n},ResourceTreeFrame:Wn,PageDispatcher:Vn});const $n={scriptRemovedOrDeleted:"Script removed or deleted.",unableToFetchScriptSource:"Unable to fetch script source."},Qn=s.i18n.registerUIStrings("core/sdk/Script.ts",$n),Xn=s.i18n.getLocalizedString.bind(void 0,Qn);let Jn=null;class Yn{debuggerModel;scriptId;sourceURL;lineOffset;columnOffset;endLine;endColumn;executionContextId;hash;#Oi;#Ni;sourceMapURL;debugSymbols;hasSourceURL;contentLength;originStackTrace;#Fi;#Bi;#Di;#Ui;isModule;constructor(e,t,n,r,s,i,a,o,l,d,c,h,u,g,p,m,f,b,y,v){this.debuggerModel=e,this.scriptId=t,this.sourceURL=n,this.lineOffset=r,this.columnOffset=s,this.endLine=i,this.endColumn=a,this.isModule=p,this.executionContextId=o,this.hash=l,this.#Oi=d,this.#Ni=c,this.sourceMapURL=h,this.debugSymbols=y,this.hasSourceURL=u,this.contentLength=g,this.originStackTrace=m,this.#Fi=f,this.#Bi=b,this.#Di=null,this.#Ui=v}embedderName(){return this.#Ui}target(){return this.debuggerModel.target()}static trimSourceURLComment(e){let t=e.lastIndexOf("//# sourceURL=");if(-1===t&&(t=e.lastIndexOf("//@ sourceURL="),-1===t))return e;const n=e.lastIndexOf("\n",t);if(-1===n)return e;return e.substr(n+1).match(er)?e.substr(0,n):e}isContentScript(){return this.#Oi}codeOffset(){return this.#Fi}isJavaScript(){return"JavaScript"===this.#Bi}isWasm(){return"WebAssembly"===this.#Bi}scriptLanguage(){return this.#Bi}executionContext(){return this.debuggerModel.runtimeModel().executionContext(this.executionContextId)}isLiveEdit(){return this.#Ni}contentURL(){return this.sourceURL}contentType(){return e.ResourceType.resourceTypes.Script}async loadTextContent(){const e=await this.debuggerModel.target().debuggerAgent().invoke_getScriptSource({scriptId:this.scriptId});if(e.getError())throw new Error(e.getError());const{scriptSource:t,bytecode:n}=e;if(n)return{content:n,isEncoded:!0};let r=t||"";return this.hasSourceURL&&this.sourceURL.startsWith("snippet://")&&(r=Yn.trimSourceURLComment(r)),{content:r,isEncoded:!1}}async loadWasmContent(){if(!this.isWasm())throw new Error("Not a wasm script");const t=await this.debuggerModel.target().debuggerAgent().invoke_disassembleWasmModule({scriptId:this.scriptId});if(t.getError())return this.loadTextContent();const{streamId:n,functionBodyOffsets:r,chunk:{lines:s,bytecodeOffsets:i}}=t,a=[],o=[];let l=s.reduce(((e,t)=>e+t.length+1),0);const d="",c=1e9-d.length;if(n)for(;;){const e=await this.debuggerModel.target().debuggerAgent().invoke_nextWasmDisassemblyChunk({streamId:n});if(e.getError())throw new Error(e.getError());const{chunk:{lines:t,bytecodeOffsets:r}}=e;if(l+=t.reduce(((e,t)=>e+t.length+1),0),0===t.length)break;if(l>=c){a.push([d]),o.push([0]);break}a.push(t),o.push(r)}const h=[];for(let e=0;ee){Jn||(Jn={cache:new Map,registry:new FinalizationRegistry((e=>Jn?.cache.delete(e)))});const e=[this.#Bi,this.contentLength,this.lineOffset,this.columnOffset,this.endLine,this.endColumn,this.#Fi,this.hash].join(":"),t=Jn.cache.get(e)?.deref();t?this.#Di=t:(this.#Di=this.requestContentInternal(),Jn.cache.set(e,new WeakRef(this.#Di)),Jn.registry.register(this.#Di,e))}else this.#Di=this.requestContentInternal()}return this.#Di}async requestContentInternal(){if(!this.scriptId)return{content:null,error:Xn($n.scriptRemovedOrDeleted),isEncoded:!1};try{return this.isWasm()?await this.loadWasmContent():await this.loadTextContent()}catch(e){return{content:null,error:Xn($n.unableToFetchScriptSource),isEncoded:!1}}}async getWasmBytecode(){const e=await this.debuggerModel.target().debuggerAgent().invoke_getWasmBytecode({scriptId:this.scriptId});return(await fetch(`data:application/wasm;base64,${e.bytecode}`)).arrayBuffer()}originalContentProvider(){return new r.StaticContentProvider.StaticContentProvider(this.contentURL(),this.contentType(),(()=>this.requestContent()))}async searchInContent(e,t,n){if(!this.scriptId)return[];return((await this.debuggerModel.target().debuggerAgent().invoke_searchInContent({scriptId:this.scriptId,query:e,caseSensitive:t,isRegex:n})).result||[]).map((e=>new r.ContentProvider.SearchMatch(e.lineNumber,e.lineContent)))}appendSourceURLCommentIfNeeded(e){return this.hasSourceURL?e+"\n //# sourceURL="+this.sourceURL:e}async editSource(e){e=Yn.trimSourceURLComment(e),e=this.appendSourceURLCommentIfNeeded(e);const{content:t}=await this.requestContent();if(t===e)return{changed:!1,status:"Ok"};const n=await this.debuggerModel.target().debuggerAgent().invoke_setScriptSource({scriptId:this.scriptId,scriptSource:e,allowTopFrameEditing:!0});if(n.getError())throw new Error(`Script#editSource failed for script with id ${this.scriptId}: ${n.getError()}`);return n.getError()||"Ok"!==n.status||(this.#Di=Promise.resolve({content:e,isEncoded:!1})),this.debuggerModel.dispatchEventToListeners(cr.ScriptSourceWasEdited,{script:this,status:n.status}),{changed:!0,status:n.status,exceptionDetails:n.exceptionDetails}}rawLocation(e,t){return this.containsLocation(e,t)?new ur(this.debuggerModel,this.scriptId,e,t):null}isInlineScript(){const e=!this.lineOffset&&!this.columnOffset;return!this.isWasm()&&Boolean(this.sourceURL)&&!e}isAnonymousScript(){return!this.sourceURL}async setBlackboxedRanges(e){return!(await this.debuggerModel.target().debuggerAgent().invoke_setBlackboxedRanges({scriptId:this.scriptId,positions:e})).getError()}containsLocation(e,t){const n=e===this.lineOffset&&t>=this.columnOffset||e>this.lineOffset,r=e=0:!(r>0)||t(e.start,n.end)<=0}if(0===e.length)return[];e.sort(((e,n)=>e.scriptIdn.scriptId?1:t(e.start,n.start)||t(e.end,n.end)));let r=e[0];const s=[];for(let i=1;ithis.#Hi.setEnabled(e.data)));const n=t.model(jn);n&&n.addEventListener(_n.FrameNavigated,this.onFrameNavigated,this)}sourceMapManager(){return this.#Hi}runtimeModel(){return this.runtimeModelInternal}debuggerEnabled(){return Boolean(this.#Vi)}debuggerId(){return this.#Gi}async enableDebugger(){if(this.#Vi)return;this.#Vi=!0;const t=o.Runtime.Runtime.queryParam("remoteFrontend")||o.Runtime.Runtime.queryParam("ws")?1e7:1e8,n=this.agent.invoke_enable({maxScriptsCacheSize:t});let r;o.Runtime.experiments.isEnabled(o.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS)&&(r=this.agent.invoke_setInstrumentationBreakpoint({instrumentation:"beforeScriptExecution"})),this.pauseOnExceptionStateChanged(),this.asyncStackTracesStateChanged(),e.Settings.Settings.instance().moduleSetting("breakpointsActive").get()||this.breakpointsActiveChanged(),this.dispatchEventToListeners(cr.DebuggerWasEnabled,this);const[s]=await Promise.all([n,r]);this.registerDebugger(s)}async syncDebuggerId(){const e=o.Runtime.Runtime.queryParam("remoteFrontend")||o.Runtime.Runtime.queryParam("ws")?1e7:1e8,t=this.agent.invoke_enable({maxScriptsCacheSize:e});return t.then(this.registerDebugger.bind(this)),t}onFrameNavigated(){or.shouldResyncDebuggerId||(or.shouldResyncDebuggerId=!0)}registerDebugger(e){if(e.getError())return;const{debuggerId:t}=e;lr.set(t,this),this.#Gi=t,this.dispatchEventToListeners(cr.DebuggerIsReadyToPause,this)}isReadyToPause(){return Boolean(this.#Gi)}static async modelForDebuggerId(e){return or.shouldResyncDebuggerId&&(await or.resyncDebuggerIdForModels(),or.shouldResyncDebuggerId=!1),lr.get(e)||null}static async resyncDebuggerIdForModels(){const e=lr.values();for(const t of e)t.debuggerEnabled()&&await t.syncDebuggerId()}async disableDebugger(){this.#Vi&&(this.#Vi=!1,await this.asyncStackTracesStateChanged(),await this.agent.invoke_disable(),this.#ea=!1,this.globalObjectCleared(),this.dispatchEventToListeners(cr.DebuggerWasDisabled,this),"string"==typeof this.#Gi&&lr.delete(this.#Gi),this.#Gi=null)}skipAllPauses(e){this.#Ki&&(clearTimeout(this.#Ki),this.#Ki=0),this.agent.invoke_setSkipAllPauses({skip:e})}skipAllPausesUntilReloadOrTimeout(e){this.#Ki&&clearTimeout(this.#Ki),this.agent.invoke_setSkipAllPauses({skip:!0}),this.#Ki=window.setTimeout(this.skipAllPauses.bind(this,!1),e)}pauseOnExceptionStateChanged(){const t=e.Settings.Settings.instance().moduleSetting("pauseOnCaughtException").get();let n;const r=e.Settings.Settings.instance().moduleSetting("pauseOnUncaughtException").get();n=t&&r?"all":t?"caught":r?"uncaught":"none",this.agent.invoke_setPauseOnExceptions({state:n})}asyncStackTracesStateChanged(){const t=!e.Settings.Settings.instance().moduleSetting("disableAsyncStackTraces").get()&&this.#Vi?32:0;return this.agent.invoke_setAsyncCallStackDepth({maxDepth:t})}breakpointsActiveChanged(){this.agent.invoke_setBreakpointsActive({active:e.Settings.Settings.instance().moduleSetting("breakpointsActive").get()})}setComputeAutoStepRangesCallback(e){this.#Qi=e}async computeAutoStepSkipList(e){let t=[];if(this.#Qi&&this.#qi&&this.#qi.callFrames.length>0){const[n]=this.#qi.callFrames;t=await this.#Qi.call(null,e,n)}return ir(t.map((({start:e,end:t})=>({scriptId:e.scriptId,start:{lineNumber:e.lineNumber,columnNumber:e.columnNumber},end:{lineNumber:t.lineNumber,columnNumber:t.columnNumber}}))))}async stepInto(){const e=await this.computeAutoStepSkipList(ar.StepInto);this.agent.invoke_stepInto({breakOnAsyncCall:!1,skipList:e})}async stepOver(){this.#Zi=this.#qi?.callFrames[0]?.functionLocation()??null;const e=await this.computeAutoStepSkipList(ar.StepOver);this.agent.invoke_stepOver({skipList:e})}async stepOut(){const e=await this.computeAutoStepSkipList(ar.StepOut);0!==e.length?this.agent.invoke_stepOver({skipList:e}):this.agent.invoke_stepOut()}scheduleStepIntoAsync(){this.computeAutoStepSkipList(ar.StepInto).then((e=>{this.agent.invoke_stepInto({breakOnAsyncCall:!0,skipList:e})}))}resume(){this.agent.invoke_resume({terminateOnResume:!1}),this.#ea=!1}pause(){this.#ea=!0,this.skipAllPauses(!1),this.agent.invoke_pause()}async setBreakpointByURL(n,r,s,a){let o;if(this.target().type()===_.Node&&n.startsWith("file://")){const r=e.ParsedURL.ParsedURL.urlToRawPathString(n,i.Platform.isWin());o=`${t.StringUtilities.escapeForRegExp(r)}|${t.StringUtilities.escapeForRegExp(n)}`,i.Platform.isWin()&&r.match(/^.:\\/)&&(o=`[${r[0].toUpperCase()}${r[0].toLowerCase()}]`+o.substr(1))}let l=0;const d=this.#zi.get(n)||[];for(let e=0,t=d.length;eur.fromPayload(this,e)))),{locations:h,breakpointId:c.breakpointId}}async setBreakpointInAnonymousScript(e,t,n,r){const s=await this.agent.invoke_setBreakpointByUrl({lineNumber:t,scriptHash:e,columnNumber:n,condition:r});if(s.getError())return{locations:[],breakpointId:null};let i=[];return s.locations&&(i=s.locations.map((e=>ur.fromPayload(this,e)))),{locations:i,breakpointId:s.breakpointId}}async removeBreakpoint(e){await this.agent.invoke_removeBreakpoint({breakpointId:e})}async getPossibleBreakpoints(e,t,n){const r=await this.agent.invoke_getPossibleBreakpoints({start:e.payload(),end:t?t.payload():void 0,restrictToFunction:n});return r.getError()||!r.locations?[]:r.locations.map((e=>gr.fromPayload(this,e)))}async fetchAsyncStackTrace(e){const t=await this.agent.invoke_getStackTrace({stackTraceId:e});return t.getError()?null:t.stackTrace}breakpointResolved(e,t){this.#Yi.dispatchEventToListeners(e,ur.fromPayload(this,t))}globalObjectCleared(){this.resetDebuggerPausedDetails(),this.reset(),this.dispatchEventToListeners(cr.GlobalObjectCleared,this)}reset(){for(const e of this.#_i.values())this.#Hi.detachSourceMap(e);this.#_i.clear(),this.#zi.clear(),this.#ji=[],this.#Zi=null}scripts(){return Array.from(this.#_i.values())}scriptForId(e){return this.#_i.get(e)||null}scriptsForSourceURL(e){return this.#zi.get(e)||[]}scriptsForExecutionContext(e){const t=[];for(const n of this.#_i.values())n.executionContextId===e.id&&t.push(n);return t}get callFrames(){return this.#qi?this.#qi.callFrames:null}debuggerPausedDetails(){return this.#qi}async setDebuggerPausedDetails(e){return this.#ea=!1,this.#qi=e,!(this.#$i&&!await this.#$i.call(null,e,this.#Zi))&&(this.#Zi=null,this.dispatchEventToListeners(cr.DebuggerPaused,this),this.setSelectedCallFrame(e.callFrames[0]),!0)}resetDebuggerPausedDetails(){this.#ea=!1,this.#qi=null,this.setSelectedCallFrame(null)}setBeforePausedCallback(e){this.#$i=e}setExpandCallFramesCallback(e){this.#Xi=e}setEvaluateOnCallFrameCallback(e){this.evaluateOnCallFrameCallback=e}setSynchronizeBreakpointsCallback(e){this.#Ji=e}async pausedScript(t,n,r,s,i,a){if("instrumentation"===n){const e=this.scriptForId(r.scriptId);return this.#Ji&&e&&await this.#Ji(e),void this.resume()}const o=new fr(this,t,n,r,s,i,a);if(this.#Xi&&(o.callFrames=await this.#Xi.call(null,o.callFrames)),this.continueToLocationCallback){const e=this.continueToLocationCallback;if(this.continueToLocationCallback=null,e(o))return}await this.setDebuggerPausedDetails(o)?e.EventTarget.fireEvent("DevTools.DebuggerPaused"):this.#Zi?this.stepOver():this.stepInto()}resumedScript(){this.resetDebuggerPausedDetails(),this.dispatchEventToListeners(cr.DebuggerResumed,this)}parsedScriptSource(e,t,n,r,s,a,o,l,d,c,h,u,g,p,m,f,b,y,v,I){const k=this.#_i.get(e);if(k)return k;let S=!1;d&&"isDefault"in d&&(S=!d.isDefault);const w=new Yn(this,e,t,n,r,s,a,o,l,S,c,h,u,p,m,f,b,y,v,I);this.registerScript(w),this.dispatchEventToListeners(cr.ParsedScriptSource,w),w.isInlineScript()&&!w.hasSourceURL&&(w.isModule?i.userMetrics.inlineScriptParsed(0):i.userMetrics.inlineScriptParsed(1)),w.sourceMapURL&&!g&&this.#Hi.attachSourceMap(w,w.sourceURL,w.sourceMapURL);return g&&w.isAnonymousScript()&&(this.#ji.push(w),this.collectDiscardedScripts()),w}setSourceMapURL(e,t){this.#Hi.detachSourceMap(e),e.sourceMapURL=t,this.#Hi.attachSourceMap(e,e.sourceURL,e.sourceMapURL)}async setDebugInfoURL(e,t){this.#Xi&&this.#qi&&(this.#qi.callFrames=await this.#Xi.call(null,this.#qi.callFrames)),this.dispatchEventToListeners(cr.DebugInfoAttached,e)}executionContextDestroyed(e){for(const t of this.#_i.values())t.executionContextId===e.id&&this.#Hi.detachSourceMap(t)}registerScript(e){if(this.#_i.set(e.scriptId,e),e.isAnonymousScript())return;let t=this.#zi.get(e.sourceURL);t||(t=[],this.#zi.set(e.sourceURL,t)),t.unshift(e)}unregisterScript(e){console.assert(e.isAnonymousScript()),this.#_i.delete(e.scriptId)}collectDiscardedScripts(){if(this.#ji.length<1e3)return;const e=this.#ji.splice(0,100);for(const t of e)this.unregisterScript(t),this.dispatchEventToListeners(cr.DiscardedAnonymousScriptSource,t)}createRawLocation(e,t,n,r){return this.createRawLocationByScriptId(e.scriptId,t,n,r)}createRawLocationByURL(e,t,n,r){for(const s of this.#zi.get(e)||[])if(!(s.lineOffset>t||s.lineOffset===t&&void 0!==n&&s.columnOffset>n||s.endLinenull===this.#Ta.axNodeForId(e)))}hasUnloadedChildren(){return!(!this.#Na||!this.#Na.length)&&this.#Na.some((e=>null===this.#Ta.axNodeForId(e)))}getFrameId(){return this.#Oa||this.parentNode()?.getFrameId()||null}}(Lr||(Lr={})).TreeUpdated="TreeUpdated";class Or extends c{agent;#Fa;#Ba;#Da;#Ua;#Ha;constructor(e){super(e),e.registerAccessibilityDispatcher(this),this.agent=e.accessibilityAgent(),this.resumeModel(),this.#Fa=new Map,this.#Ba=new Map,this.#Da=new Map,this.#Ua=new Map,this.#Ha=null}clear(){this.#Ha=null,this.#Fa.clear(),this.#Ba.clear(),this.#Da.clear()}async resumeModel(){await this.agent.invoke_enable()}async suspendModel(){await this.agent.invoke_disable()}async requestPartialAXTree(e){const{nodes:t}=await this.agent.invoke_getPartialAXTree({nodeId:e.id,fetchRelatives:!0});if(!t)return;const n=[];for(const e of t)n.push(new Ar(this,e))}loadComplete({root:e}){this.clear(),this.#Ha=new Ar(this,e),this.dispatchEventToListeners(Lr.TreeUpdated,{root:this.#Ha})}nodesUpdated({nodes:e}){this.createNodesFromPayload(e),this.dispatchEventToListeners(Lr.TreeUpdated,{})}createNodesFromPayload(e){return e.map((e=>new Ar(this,e)))}async requestRootNode(e){if(e&&this.#Da.has(e))return this.#Da.get(e);if(!e&&this.#Ha)return this.#Ha;const{node:t}=await this.agent.invoke_getRootAXNode({frameId:e});return t?this.createNodesFromPayload([t])[0]:void 0}async requestAXChildren(e,t){const n=this.#Fa.get(e);if(!n)throw Error("Cannot request children before parent");if(!n.hasUnloadedChildren())return n.children();const r=this.#Ua.get(e);if(r)await r;else{const n=this.agent.invoke_getChildAXNodes({id:e,frameId:t});this.#Ua.set(e,n);const r=await n;r.getError()||(this.createNodesFromPayload(r.nodes),this.#Ua.delete(e))}return n.children()}async requestAndLoadSubTreeToNode(e){const t=[];let n=this.axNodeForDOMNode(e);for(;n;){t.push(n);const e=n.parentNode();if(!e)return t;n=e}const{nodes:r}=await this.agent.invoke_getAXNodeAndAncestors({backendNodeId:e.backendNodeId()});if(!r)return null;return this.createNodesFromPayload(r)}axNodeForId(e){return this.#Fa.get(e)||null}setRootAXNodeForFrameId(e,t){this.#Da.set(e,t)}axNodeForFrameId(e){return this.#Da.get(e)??null}setAXNodeForAXId(e,t){this.#Fa.set(e,t)}axNodeForDOMNode(e){return e?this.#Ba.get(e.backendNodeId())??null:null}setAXNodeForBackendDOMNodeId(e,t){this.#Ba.set(e,t)}getAgent(){return this.agent}}c.register(Or,{capabilities:z.DOM,autostart:!1});var Nr=Object.freeze({__proto__:null,get CoreAxPropertyName(){return Pr},AccessibilityNode:Ar,get Events(){return Lr},AccessibilityModel:Or});class Fr{#qa;titleInternal;enabledInternal;constructor(e,t){this.#qa=e,this.titleInternal=t,this.enabledInternal=!1}category(){return this.#qa}enabled(){return this.enabledInternal}setEnabled(e){this.enabledInternal=e}title(){return this.titleInternal}setTitle(e){this.titleInternal=e}}var Br=Object.freeze({__proto__:null,CategorizedBreakpoint:Fr});class Dr{onMessage;#_a;#za;#ja;#ar;constructor(){this.onMessage=null,this.#_a=null,this.#za="",this.#ja=0,this.#ar=[i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.DispatchMessage,this.dispatchMessage,this),i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.DispatchMessageChunk,this.dispatchMessageChunk,this)]}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}sendRawMessage(e){this.onMessage&&i.InspectorFrontendHost.InspectorFrontendHostInstance.sendMessageToBackend(e)}dispatchMessage(e){this.onMessage&&this.onMessage.call(null,e.data)}dispatchMessageChunk(e){const{messageChunk:t,messageSize:n}=e.data;n&&(this.#za="",this.#ja=n),this.#za+=t,this.#za.length===this.#ja&&this.onMessage&&(this.onMessage.call(null,this.#za),this.#za="",this.#ja=0)}async disconnect(){const t=this.#_a;e.EventTarget.removeEventListeners(this.#ar),this.#_a=null,this.onMessage=null,t&&t.call(null,"force disconnect")}}class Ur{#Wa;onMessage;#_a;#Va;#Ga;#Ka;constructor(e,t){this.#Wa=new WebSocket(e),this.#Wa.onerror=this.onError.bind(this),this.#Wa.onopen=this.onOpen.bind(this),this.#Wa.onmessage=e=>{this.onMessage&&this.onMessage.call(null,e.data)},this.#Wa.onclose=this.onClose.bind(this),this.onMessage=null,this.#_a=null,this.#Va=t,this.#Ga=!1,this.#Ka=[]}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}onError(){this.#Va&&this.#Va.call(null),this.#_a&&this.#_a.call(null,"connection failed"),this.close()}onOpen(){if(this.#Ga=!0,this.#Wa){this.#Wa.onerror=console.error;for(const e of this.#Ka)this.#Wa.send(e)}this.#Ka=[]}onClose(){this.#Va&&this.#Va.call(null),this.#_a&&this.#_a.call(null,"websocket closed"),this.close()}close(e){this.#Wa&&(this.#Wa.onerror=null,this.#Wa.onopen=null,this.#Wa.onclose=e||null,this.#Wa.onmessage=null,this.#Wa.close(),this.#Wa=null),this.#Va=null}sendRawMessage(e){this.#Ga&&this.#Wa?this.#Wa.send(e):this.#Ka.push(e)}disconnect(){return new Promise((e=>{this.close((()=>{this.#_a&&this.#_a.call(null,"force disconnect"),e()}))}))}}class Hr{onMessage;#_a;constructor(){this.onMessage=null,this.#_a=null}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}sendRawMessage(e){window.setTimeout(this.respondWithError.bind(this,e),0)}respondWithError(e){const t=JSON.parse(e),n={message:"This is a stub connection, can't dispatch message.",code:a.InspectorBackend.DevToolsStubErrorCode,data:t};this.onMessage&&this.onMessage.call(null,{id:t.id,error:n})}async disconnect(){this.#_a&&this.#_a.call(null,"force disconnect"),this.#_a=null,this.onMessage=null}}class qr{#$a;#Qa;onMessage;#_a;constructor(e,t){this.#$a=e,this.#Qa=t,this.onMessage=null,this.#_a=null}setOnMessage(e){this.onMessage=e}setOnDisconnect(e){this.#_a=e}getOnDisconnect(){return this.#_a}sendRawMessage(e){const t=JSON.parse(e);t.sessionId||(t.sessionId=this.#Qa),this.#$a.sendRawMessage(JSON.stringify(t))}getSessionId(){return this.#Qa}async disconnect(){this.#_a&&this.#_a.call(null,"force disconnect"),this.#_a=null,this.onMessage=null}}function _r(e){const t=o.Runtime.Runtime.queryParam("ws"),n=o.Runtime.Runtime.queryParam("wss");if(t||n){const r=t?"ws":"wss";let s=t||n;i.InspectorFrontendHost.InspectorFrontendHostInstance.isHostedMode()&&s.startsWith("/")&&(s=`${window.location.host}${s}`);return new Ur(`${r}://${s}`,e)}return i.InspectorFrontendHost.InspectorFrontendHostInstance.isHostedMode()?new Hr:new Dr}var zr,jr=Object.freeze({__proto__:null,MainConnection:Dr,WebSocketConnection:Ur,StubConnection:Hr,ParallelConnection:qr,initMainConnection:async function(e,t){a.InspectorBackend.Connection.setFactory(_r.bind(null,t)),await e(),i.InspectorFrontendHost.InspectorFrontendHostInstance.connectionReady(),i.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(i.InspectorFrontendHostAPI.Events.ReattachRootTarget,(()=>{const t=K.instance().rootTarget();if(t){const e=t.router();e&&e.connection().disconnect()}e()}))}});class Wr extends c{#Xa;#Ja;#Ya;#Za=new Map;#eo=new Map;#to=new Map;#no=new Map;#ro=null;constructor(e){super(e),this.#Xa=e.targetManager(),this.#Ja=e,this.#Ya=e.targetAgent(),e.registerTargetDispatcher(this);const t=this.#Xa.browserTarget();t?t!==e&&t.targetAgent().invoke_autoAttachRelated({targetId:e.id(),waitForDebuggerOnStart:!0}):this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0}),e.parentTarget()?.type()===_.Frame||i.InspectorFrontendHost.isUnderTest()||(this.#Ya.invoke_setDiscoverTargets({discover:!0}),this.#Ya.invoke_setRemoteLocations({locations:[{host:"localhost",port:9229}]}))}static install(e){Wr.attachCallback=e,c.register(Wr,{capabilities:z.Target,autostart:!0})}childTargets(){return Array.from(this.#eo.values())}async suspendModel(){await this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!1,flatten:!0})}async resumeModel(){await this.#Ya.invoke_setAutoAttach({autoAttach:!0,waitForDebuggerOnStart:!0,flatten:!0})}dispose(){for(const e of this.#eo.keys())this.detachedFromTarget({sessionId:e,targetId:void 0})}targetCreated({targetInfo:e}){this.#Za.set(e.targetId,e),this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetCreated,e)}targetInfoChanged({targetInfo:e}){this.#Za.set(e.targetId,e);const t=this.#to.get(e.targetId);if(t)if("prerender"!==t.targetInfo()?.subtype||e.subtype)t.updateTargetInfo(e);else{const n=t.model(jn);t.updateTargetInfo(e),n&&n.mainFrame&&n.primaryPageChanged(n.mainFrame,"Activation")}this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetInfoChanged,e)}targetDestroyed({targetId:e}){this.#Za.delete(e),this.fireAvailableTargetsChanged(),this.dispatchEventToListeners(zr.TargetDestroyed,e)}targetCrashed({targetId:e,status:t,errorCode:n}){}fireAvailableTargetsChanged(){K.instance().dispatchEventToListeners($.AvailableTargetsChanged,[...this.#Za.values()])}async getParentTargetId(){return this.#ro||(this.#ro=(await this.#Ja.targetAgent().invoke_getTargetInfo({})).targetInfo.targetId),this.#ro}async attachedToTarget({sessionId:t,targetInfo:n,waitingForDebugger:r}){if(this.#ro===n.targetId)return;let s=_.Browser,i="";if("worker"===n.type&&n.title&&n.title!==n.url)i=n.title;else if(!["page","iframe","webview"].includes(n.type))if("chrome://print/"===n.url||n.url.startsWith("chrome://")&&n.url.endsWith(".top-chrome/"))s=_.Frame;else{const t=e.ParsedURL.ParsedURL.fromString(n.url);i=t?t.lastPathComponentWithFragment():"#"+ ++Wr.lastAnonymousTargetId,"devtools"===t?.scheme&&"other"===n.type&&(s=_.Frame)}"iframe"===n.type||"webview"===n.type||"background_page"===n.type||"app"===n.type||"popup_page"===n.type||"page"===n.type?s=_.Frame:"worker"===n.type?s=_.Worker:"shared_worker"===n.type?s=_.SharedWorker:"service_worker"===n.type?s=_.ServiceWorker:"auction_worklet"===n.type&&(s=_.AuctionWorklet);const a=this.#Xa.createTarget(n.targetId,i,s,this.#Ja,t,void 0,void 0,n);this.#eo.set(t,a),this.#to.set(a.id(),a),Wr.attachCallback&&await Wr.attachCallback({target:a,waitingForDebugger:r}),r&&a.runtimeAgent().invoke_runIfWaitingForDebugger()}detachedFromTarget({sessionId:e}){if(this.#no.has(e))this.#no.delete(e);else{const t=this.#eo.get(e);t&&(t.dispose("target terminated"),this.#eo.delete(e),this.#to.delete(t.id()))}}receivedMessageFromTarget({}){}async createParallelConnection(e){const t=await this.getParentTargetId(),{connection:n,sessionId:r}=await this.createParallelConnectionAndSessionForTarget(this.#Ja,t);return n.setOnMessage(e),this.#no.set(r,n),{connection:n,sessionId:r}}async createParallelConnectionAndSessionForTarget(e,t){const n=e.targetAgent(),r=e.router(),s=(await n.invoke_attachToTarget({targetId:t,flatten:!0})).sessionId,i=new qr(r.connection(),s);return r.registerSession(e,s,i),i.setOnDisconnect((()=>{r.unregisterSession(s),n.invoke_detachFromTarget({sessionId:s})})),{connection:i,sessionId:s}}targetInfos(){return Array.from(this.#Za.values())}static lastAnonymousTargetId=0;static attachCallback}!function(e){e.TargetCreated="TargetCreated",e.TargetDestroyed="TargetDestroyed",e.TargetInfoChanged="TargetInfoChanged"}(zr||(zr={}));var Vr=Object.freeze({__proto__:null,ChildTargetManager:Wr,get Events(){return zr}});const Gr={couldNotLoadContentForSS:"Could not load content for {PH1} ({PH2})"},Kr=s.i18n.registerUIStrings("core/sdk/CompilerSourceMappingContentProvider.ts",Gr),$r=s.i18n.getLocalizedString.bind(void 0,Kr);var Qr,Xr,Jr=Object.freeze({__proto__:null,CompilerSourceMappingContentProvider:class{#so;#io;#ao;constructor(e,t,n){this.#so=e,this.#io=t,this.#ao=n}contentURL(){return this.#so}contentType(){return this.#io}async requestContent(){try{const{content:e}=await Ht.instance().loadResource(this.#so,this.#ao);return{content:e,isEncoded:!1}}catch(e){const t=$r(Gr.couldNotLoadContentForSS,{PH1:this.#so,PH2:e.message});return console.error(t),{content:null,error:t,isEncoded:!1}}}async searchInContent(e,t,n){const{content:s}=await this.requestContent();return"string"!=typeof s?[]:r.TextUtils.performSearchInContent(s,e,t,n)}}});!function(e){e.Result="result",e.Command="command",e.System="system",e.QueryObjectResult="queryObjectResult"}(Qr||(Qr={})),function(e){e.CSS="css",e.ConsoleAPI="console-api"}(Xr||(Xr={}));const Yr={profileD:"Profile {PH1}"},Zr=s.i18n.registerUIStrings("core/sdk/CPUProfilerModel.ts",Yr),es=s.i18n.getLocalizedString.bind(void 0,Zr);class ts extends c{#oo;#lo;#do;#co;#ho;#uo;registeredConsoleProfileMessages=[];constructor(e){super(e),this.#oo=!1,this.#lo=1,this.#do=new Map,this.#co=e.profilerAgent(),this.#ho=null,e.registerProfilerDispatcher(this),this.#co.invoke_enable(),this.#uo=e.model(or)}runtimeModel(){return this.#uo.runtimeModel()}debuggerModel(){return this.#uo}consoleProfileStarted({id:e,location:t,title:n}){n||(n=es(Yr.profileD,{PH1:this.#lo++}),this.#do.set(e,n));const r=this.createEventDataFrom(e,t,n);this.dispatchEventToListeners(ns.ConsoleProfileStarted,r)}consoleProfileFinished({id:e,location:t,profile:n,title:r}){r||(r=this.#do.get(e),this.#do.delete(e));const s={...this.createEventDataFrom(e,t,r),cpuProfile:n};this.registeredConsoleProfileMessages.push(s),this.dispatchEventToListeners(ns.ConsoleProfileFinished,s)}createEventDataFrom(e,t,n){const r=ur.fromPayload(this.#uo,t);return{id:this.target().id()+"."+e,scriptLocation:r,title:n||"",cpuProfilerModel:this}}isRecordingProfile(){return this.#oo}startRecording(){this.#oo=!0;return this.#co.invoke_setSamplingInterval({interval:100}),this.#co.invoke_start()}stopRecording(){return this.#oo=!1,this.#co.invoke_stop().then((e=>e.profile||null))}startPreciseCoverage(e,t){this.#ho=t;return this.#co.invoke_startPreciseCoverage({callCount:!1,detailed:e,allowTriggeredUpdates:!0})}async takePreciseCoverage(){const e=await this.#co.invoke_takePreciseCoverage();return{timestamp:e&&e.timestamp||0,coverage:e&&e.result||[]}}stopPreciseCoverage(){return this.#ho=null,this.#co.invoke_stopPreciseCoverage()}preciseCoverageDeltaUpdate({timestamp:e,occasion:t,result:n}){this.#ho&&this.#ho(e,t,n)}}var ns;!function(e){e.ConsoleProfileStarted="ConsoleProfileStarted",e.ConsoleProfileFinished="ConsoleProfileFinished"}(ns||(ns={})),c.register(ts,{capabilities:z.JS,autostart:!0});var rs,ss=Object.freeze({__proto__:null,CPUProfilerModel:ts,get Events(){return ns}});class is extends c{#go;constructor(e){super(e),e.registerLogDispatcher(this),this.#go=e.logAgent(),this.#go.invoke_enable(),i.InspectorFrontendHost.isUnderTest()||this.#go.invoke_startViolationsReport({config:[{name:"longTask",threshold:200},{name:"longLayout",threshold:30},{name:"blockedEvent",threshold:100},{name:"blockedParser",threshold:-1},{name:"handler",threshold:150},{name:"recurringHandler",threshold:50},{name:"discouragedAPIUse",threshold:-1}]})}entryAdded({entry:e}){this.dispatchEventToListeners(rs.EntryAdded,{logModel:this,entry:e})}requestClear(){this.#go.invoke_clear()}}(rs||(rs={})).EntryAdded="EntryAdded",c.register(is,{capabilities:z.Log,autostart:!0});var as=Object.freeze({__proto__:null,LogModel:is,get Events(){return rs}});const os={navigatedToS:"Navigated to {PH1}",bfcacheNavigation:"Navigation to {PH1} was restored from back/forward cache (see https://web.dev/bfcache/)",profileSStarted:"Profile ''{PH1}'' started.",profileSFinished:"Profile ''{PH1}'' finished.",failedToSaveToTempVariable:"Failed to save to temp variable."},ls=s.i18n.registerUIStrings("core/sdk/ConsoleModel.ts",os),ds=s.i18n.getLocalizedString.bind(void 0,ls);class cs extends c{#po;#mo;#fo;#bo;#yo;#vo;#Io;#ko;constructor(n){super(n),this.#po=[],this.#mo=new t.MapUtilities.Multimap,this.#fo=new Map,this.#bo=0,this.#yo=0,this.#vo=0,this.#Io=0,this.#ko=new WeakMap;const r=n.model(jn);if(!r||r.cachedResourcesLoaded())return void this.initTarget(n);const s=r.addEventListener(_n.CachedResourcesLoaded,(()=>{e.EventTarget.removeEventListeners([s]),this.initTarget(n)}))}initTarget(e){const t=[],n=e.model(ts);n&&(t.push(n.addEventListener(ns.ConsoleProfileStarted,this.consoleProfileStarted.bind(this,n))),t.push(n.addEventListener(ns.ConsoleProfileFinished,this.consoleProfileFinished.bind(this,n))));const r=e.model(jn);r&&e.parentTarget()?.type()!==_.Frame&&t.push(r.addEventListener(_n.PrimaryPageChanged,this.primaryPageChanged,this));const s=e.model(Cr);s&&(t.push(s.addEventListener(Rr.ExceptionThrown,this.exceptionThrown.bind(this,s))),t.push(s.addEventListener(Rr.ExceptionRevoked,this.exceptionRevoked.bind(this,s))),t.push(s.addEventListener(Rr.ConsoleAPICalled,this.consoleAPICalled.bind(this,s))),e.parentTarget()?.type()!==_.Frame&&t.push(s.debuggerModel().addEventListener(cr.GlobalObjectCleared,this.clearIfNecessary,this)),t.push(s.addEventListener(Rr.QueryObjectRequested,this.queryObjectRequested.bind(this,s)))),this.#ko.set(e,t)}targetRemoved(t){const n=t.model(Cr);n&&this.#fo.delete(n),e.EventTarget.removeEventListeners(this.#ko.get(t)||[])}async evaluateCommandInConsole(t,n,r,s){const a=await t.evaluate({expression:r,objectGroup:"console",includeCommandLineAPI:s,silent:!1,returnByValue:!1,generatePreview:!0,replMode:!0,allowUnsafeEvalBlockedByCSP:!1},e.Settings.Settings.instance().moduleSetting("consoleUserActivationEval").get(),!1);i.userMetrics.actionTaken(i.UserMetrics.Action.ConsoleEvaluated),"error"in a||(await e.Console.Console.instance().showPromise(),this.dispatchEventToListeners(hs.CommandEvaluated,{result:a.object,commandMessage:n,exceptionDetails:a.exceptionDetails}))}addCommandMessage(e,t){const n=new gs(e.runtimeModel,"javascript",null,t,{type:Qr.Command});return n.setExecutionContextId(e.id),this.addMessage(n),n}addMessage(e){e.setPageLoadSequenceNumber(this.#Io),e.source===Xr.ConsoleAPI&&"clear"===e.type&&this.clearIfNecessary(),this.#po.push(e),this.#mo.set(e.timestamp,e);const t=e.runtimeModel(),n=e.getExceptionId();if(n&&t){let r=this.#fo.get(t);r||(r=new Map,this.#fo.set(t,r)),r.set(n,e)}this.incrementErrorWarningCount(e),this.dispatchEventToListeners(hs.MessageAdded,e)}exceptionThrown(e,t){const n=t.data,r=function(e){if(!e)return;return{requestId:e.requestId||void 0,issueId:e.issueId||void 0}}(n.details.exceptionMetaData),s=gs.fromException(e,n.details,void 0,n.timestamp,void 0,r);s.setExceptionId(n.details.exceptionId),this.addMessage(s)}exceptionRevoked(e,t){const n=t.data,r=this.#fo.get(e),s=r?r.get(n):null;s&&(this.#yo--,s.level="verbose",this.dispatchEventToListeners(hs.MessageUpdated,s))}consoleAPICalled(e,t){const n=t.data;let r="info";"debug"===n.type?r="verbose":"error"===n.type||"assert"===n.type?r="error":"warning"===n.type?r="warning":"info"!==n.type&&"log"!==n.type||(r="info");let s="";n.args.length&&n.args[0].unserializableValue?s=n.args[0].unserializableValue:!n.args.length||"object"==typeof n.args[0].value&&null!==n.args[0].value?n.args.length&&n.args[0].description&&(s=n.args[0].description):s=String(n.args[0].value);const i=n.stackTrace&&n.stackTrace.callFrames.length?n.stackTrace.callFrames[0]:null,a={type:n.type,url:i?.url,line:i?.lineNumber,column:i?.columnNumber,parameters:n.args,stackTrace:n.stackTrace,timestamp:n.timestamp,executionContextId:n.executionContextId,context:n.context},o=new gs(e,Xr.ConsoleAPI,r,s,a);for(const e of this.#mo.get(o.timestamp).values())if(o.isEqual(e))return;this.addMessage(o)}queryObjectRequested(e,t){const{objects:n,executionContextId:r}=t.data,s={type:Qr.QueryObjectResult,parameters:[n],executionContextId:r},i=new gs(e,Xr.ConsoleAPI,"info","",s);this.addMessage(i)}clearIfNecessary(){e.Settings.Settings.instance().moduleSetting("preserveConsoleLog").get()||this.clear(),++this.#Io}primaryPageChanged(t){if(e.Settings.Settings.instance().moduleSetting("preserveConsoleLog").get()){const{frame:n}=t.data;n.backForwardCacheDetails.restoredFromCache?e.Console.Console.instance().log(ds(os.bfcacheNavigation,{PH1:n.url})):e.Console.Console.instance().log(ds(os.navigatedToS,{PH1:n.url}))}}consoleProfileStarted(e,t){const{data:n}=t;this.addConsoleProfileMessage(e,"profile",n.scriptLocation,ds(os.profileSStarted,{PH1:n.title}))}consoleProfileFinished(e,t){const{data:n}=t;this.addConsoleProfileMessage(e,"profileEnd",n.scriptLocation,ds(os.profileSFinished,{PH1:n.title}))}addConsoleProfileMessage(e,t,n,r){const s=n.script(),i=[{functionName:"",scriptId:n.scriptId,url:s?s.contentURL():"",lineNumber:n.lineNumber,columnNumber:n.columnNumber||0}];this.addMessage(new gs(e.runtimeModel(),Xr.ConsoleAPI,"info",r,{type:t,stackTrace:{callFrames:i}}))}incrementErrorWarningCount(e){if("violation"!==e.source)switch(e.level){case"warning":this.#bo++;break;case"error":this.#yo++}else this.#vo++}messages(){return this.#po}static allMessagesUnordered(){const e=[];for(const t of K.instance().targets()){const n=t.model(cs)?.messages()||[];e.push(...n)}return e}static requestClearMessages(){for(const e of K.instance().models(is))e.requestClear();for(const e of K.instance().models(Cr))e.discardConsoleEntries();for(const e of K.instance().targets())e.model(cs)?.clear()}clear(){this.#po=[],this.#mo.clear(),this.#fo.clear(),this.#yo=0,this.#bo=0,this.#vo=0,this.dispatchEventToListeners(hs.ConsoleCleared)}errors(){return this.#yo}static allErrors(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.errors()||0;return e}warnings(){return this.#bo}static allWarnings(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.warnings()||0;return e}violations(){return this.#vo}static allViolations(){let e=0;for(const t of K.instance().targets())e+=t.model(cs)?.violations()||0;return e}async saveToTempVariable(t,n){if(!n||!t)return void o(null);const r=t,s=await r.globalObject("",!1);if("error"in s||Boolean(s.exceptionDetails)||!s.object)return void o("object"in s&&s.object||null);const i=s.object,a=await i.callFunction((function(e){const t="temp";let n=1;for(;t+n in this;)++n;const r=t+n;return this[r]=e,r}),[Le.toCallArgument(n)]);if(i.release(),a.wasThrown||!a.object||"string"!==a.object.type)o(a.object||null);else{const e=a.object.value,t=this.addCommandMessage(r,e);this.evaluateCommandInConsole(r,t,e,!1)}function o(t){let n=ds(os.failedToSaveToTempVariable);t&&(n=n+" "+t.description),e.Console.Console.instance().error(n)}a.object&&a.object.release()}}var hs;function us(e,t){if(!e!=!t)return!1;if(!e||!t)return!0;const n=e.callFrames,r=t.callFrames;if(n.length!==r.length)return!1;for(let e=0,t=n.length;et.includes(e)));if(-1===n||n===e.length-1)return{callFrame:null,type:null};const r=e[n].url===br?"LOGPOINT":"CONDITIONAL_BREAKPOINT";return{callFrame:e[n+1],type:r}}}c.register(cs,{capabilities:z.JS,autostart:!0});const ps=new Map([["xml","xml"],["javascript","javascript"],["network","network"],[Xr.ConsoleAPI,"console-api"],["storage","storage"],["appcache","appcache"],["rendering","rendering"],[Xr.CSS,"css"],["security","security"],["deprecation","deprecation"],["worker","worker"],["violation","violation"],["intervention","intervention"],["recommendation","recommendation"],["other","other"]]);var ms=Object.freeze({__proto__:null,ConsoleModel:cs,get Events(){return hs},ConsoleMessage:gs,MessageSourceDisplayName:ps,get FrontendMessageSource(){return Xr},get FrontendMessageType(){return Qr}});class fs extends c{#Mo;#Po;constructor(e){super(e),this.#Mo=new Map,this.#Po=new Map}addBlockedCookie(e,t){const n=e.key(),r=this.#Mo.get(n);this.#Mo.set(n,e),t?this.#Po.set(e,t):this.#Po.delete(e),r&&this.#Po.delete(r)}getCookieToBlockedReasonsMap(){return this.#Po}async getCookies(e){const t=await this.target().networkAgent().invoke_getCookies({urls:e});if(t.getError())return[];return t.cookies.map(F.fromProtocolCookie).concat(Array.from(this.#Mo.values()))}async deleteCookie(e){await this.deleteCookies([e])}async clear(e,t){const n=await this.getCookiesForDomain(e||null);if(t){const e=n.filter((e=>e.matchesSecurityOrigin(t)));await this.deleteCookies(e)}else await this.deleteCookies(n)}async saveCookie(e){let t,n=e.domain();n.startsWith(".")||(n=""),e.expires()&&(t=Math.floor(Date.parse(`${e.expires()}`)/1e3));const r=o.Runtime.experiments.isEnabled("experimentalCookieFeatures"),s={name:e.name(),value:e.value(),url:e.url()||void 0,domain:n,path:e.path(),secure:e.secure(),httpOnly:e.httpOnly(),sameSite:e.sameSite(),expires:t,priority:e.priority(),partitionKey:e.partitionKey(),sourceScheme:r?e.sourceScheme():(i=e.sourceScheme(),"Unset"===i?i:void 0),sourcePort:r?e.sourcePort():void 0};var i;const a=await this.target().networkAgent().invoke_setCookie(s);return!(a.getError()||!a.success)&&a.success}getCookiesForDomain(t){const n=[];const r=this.target().model(jn);return r&&(r.mainFrame&&r.mainFrame.unreachableUrl()&&n.push(r.mainFrame.unreachableUrl()),r.forAllResources((function(r){const s=e.ParsedURL.ParsedURL.fromString(r.documentURL);return!s||t&&s.securityOrigin()!==t||n.push(r.url),!1}))),this.getCookies(n)}async deleteCookies(e){const t=this.target().networkAgent();this.#Mo.clear(),this.#Po.clear(),await Promise.all(e.map((e=>t.invoke_deleteCookies({name:e.name(),url:void 0,domain:e.domain(),path:e.path()}))))}}c.register(fs,{capabilities:z.Network,autostart:!1});var bs=Object.freeze({__proto__:null,CookieModel:fs});class ys extends A{id;self;positionTicks;deoptReason;constructor(e,t,n){super(e.callFrame||{functionName:e.functionName,scriptId:e.scriptId,url:e.url,lineNumber:e.lineNumber-1,columnNumber:e.columnNumber-1},n),this.id=e.id,this.self=(e.hitCount||0)*t,this.positionTicks=e.positionTicks,this.deoptReason=e.deoptReason&&"no reason"!==e.deoptReason?e.deoptReason:null}}var vs=Object.freeze({__proto__:null,CPUProfileNode:ys,CPUProfileDataModel:class extends O{profileStartTime;profileEndTime;timestamps;samples;lines;totalHitCount;profileHead;#Lo;gcNode;programNode;idleNode;#Eo;#Ao;constructor(e,t){super(t);Boolean(e.head)?(this.profileStartTime=1e3*e.startTime,this.profileEndTime=1e3*e.endTime,this.timestamps=e.timestamps,this.compatibilityConversionHeadToNodes(e)):(this.profileStartTime=e.startTime/1e3,this.profileEndTime=e.endTime/1e3,this.timestamps=this.convertTimeDeltas(e)),this.samples=e.samples,this.lines=e.lines,this.totalHitCount=0,this.profileHead=this.translateProfileTree(e.nodes),this.initialize(this.profileHead),this.extractMetaNodes(),this.samples&&(this.sortSamples(),this.normalizeTimestamps(),this.fixMissingSamples())}compatibilityConversionHeadToNodes(e){if(!e.head||e.nodes)return;const t=[];!function e(n){return t.push(n),n.children=n.children.map(e),n.id}(e.head),e.nodes=t,delete e.head}convertTimeDeltas(e){if(!e.timeDeltas)return[];let t=e.startTime;const n=new Array(e.timeDeltas.length);for(let r=0;re+(t.hitCount||0)),0);const r=(this.profileEndTime-this.profileStartTime)/this.totalHitCount,s=Boolean(e.Settings.Settings.instance().moduleSetting("showNativeFunctionsInJSProfile").get()),i=t[0],a=new Map([[i.id,i.id]]);this.#Lo=new Map;const o=new ys(i,r,this.target());if(this.#Lo.set(i.id,o),!i.children)throw new Error("Missing children for root");const l=i.children.map((()=>o)),d=i.children.map((e=>n.get(e)));for(;d.length;){let e=l.pop();const t=d.pop();if(!t||!e)continue;t.children||(t.children=[]);const i=new ys(t,r,this.target());s||!((c=t).callFrame?Boolean(c.callFrame.url)&&c.callFrame.url.startsWith("native "):Boolean(c.url)&&c.url.startsWith("native "))?(e.children.push(i),e=i):e.self+=i.self,a.set(t.id,e.id),l.push.apply(l,t.children.map((()=>e))),d.push.apply(d,t.children.map((e=>n.get(e)))),this.#Lo.set(t.id,i)}var c;return this.samples&&(this.samples=this.samples.map((e=>a.get(e)))),o}sortSamples(){if(!this.timestamps||!this.samples)return;const e=this.timestamps,t=this.samples,n=e.map(((e,t)=>t));n.sort(((t,n)=>e[t]-e[n])),this.timestamps=[],this.samples=[];for(let r=0;r=s));I++){const t=i[I];if(t===p)continue;v=o.get(t);let r=o.get(p);if(v!==l){if(r===l&&m){const e=b[h],t=g-e;y[h-1]+=t,n(m.depth+1,l,e,t,t-y[h]),--h,r=m,p=r.id,m=null}for(;v&&v.depth>r.depth;)u.push(v),v=v.parent;for(;r!==v;){const e=b[h],t=g-e;y[h-1]+=t,n(r.depth,r,e,t,t-y[h]),--h,v&&v.depth===r.depth&&(u.push(v),v=v.parent),r=r.parent}for(;u.length;){const t=u.pop();v=t,e(t.depth,t,g),b[++h]=g,y[h]=0}p=t}else m=r,e(m.depth+1,l,g),b[++h]=g,y[h]=0,p=t}if(g=a[I]||this.profileEndTime,m&&o.get(p)===l){const e=b[h],t=g-e;y[h-1]+=t,n(m.depth+1,v,e,t,t-y[h]),--h,p=m.id}for(let e=o.get(p);e&&e.parent;e=e.parent){const t=b[h],r=g-t;y[h-1]+=r,n(e.depth,e,t,r,r-y[h]),--h}}nodeByIndex(e){return this.samples&&this.#Lo.get(this.samples[e])||null}nodes(){return this.#Lo?[...this.#Lo.values()]:null}}});class Is extends c{#Oo;#No;#jr;#Fo;#Bo;#Do;#Uo;#Ho;#qo;#_o;constructor(t){super(t),this.#Oo=t.emulationAgent(),this.#No=t.deviceOrientationAgent(),this.#jr=t.model(en),this.#Fo=t.model(vn),this.#Fo&&this.#Fo.addEventListener(In.InspectModeWillBeToggled,(()=>{this.updateTouch()}),this);const n=e.Settings.Settings.instance().moduleSetting("javaScriptDisabled");n.addChangeListener((async()=>await this.#Oo.invoke_setScriptExecutionDisabled({value:n.get()}))),n.get()&&this.#Oo.invoke_setScriptExecutionDisabled({value:!0});const r=e.Settings.Settings.instance().moduleSetting("emulation.touch");r.addChangeListener((()=>{const e=r.get();this.overrideEmulateTouch("force"===e)}));const s=e.Settings.Settings.instance().moduleSetting("emulation.idleDetection");s.addChangeListener((async()=>{const e=s.get();if("none"===e)return void await this.clearIdleOverride();const t=JSON.parse(e);await this.setIdleOverride(t)}));const i=e.Settings.Settings.instance().moduleSetting("emulatedCSSMedia"),a=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeatureColorGamut"),o=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersColorScheme"),l=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeatureForcedColors"),d=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersContrast"),c=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersReducedData"),h=e.Settings.Settings.instance().moduleSetting("emulatedCSSMediaFeaturePrefersReducedMotion");this.#Bo=new Map([["type",i.get()],["color-gamut",a.get()],["prefers-color-scheme",o.get()],["forced-colors",l.get()],["prefers-contrast",d.get()],["prefers-reduced-data",c.get()],["prefers-reduced-motion",h.get()]]),i.addChangeListener((()=>{this.#Bo.set("type",i.get()),this.updateCssMedia()})),a.addChangeListener((()=>{this.#Bo.set("color-gamut",a.get()),this.updateCssMedia()})),o.addChangeListener((()=>{this.#Bo.set("prefers-color-scheme",o.get()),this.updateCssMedia()})),l.addChangeListener((()=>{this.#Bo.set("forced-colors",l.get()),this.updateCssMedia()})),d.addChangeListener((()=>{this.#Bo.set("prefers-contrast",d.get()),this.updateCssMedia()})),c.addChangeListener((()=>{this.#Bo.set("prefers-reduced-data",c.get()),this.updateCssMedia()})),h.addChangeListener((()=>{this.#Bo.set("prefers-reduced-motion",h.get()),this.updateCssMedia()})),this.updateCssMedia();const u=e.Settings.Settings.instance().moduleSetting("emulateAutoDarkMode");u.addChangeListener((()=>{const e=u.get();o.setDisabled(e),o.set(e?"dark":""),this.emulateAutoDarkMode(e)})),u.get()&&(o.setDisabled(!0),o.set("dark"),this.emulateAutoDarkMode(!0));const g=e.Settings.Settings.instance().moduleSetting("emulatedVisionDeficiency");g.addChangeListener((()=>this.emulateVisionDeficiency(g.get()))),g.get()&&this.emulateVisionDeficiency(g.get());const p=e.Settings.Settings.instance().moduleSetting("localFontsDisabled");p.addChangeListener((()=>this.setLocalFontsDisabled(p.get()))),p.get()&&this.setLocalFontsDisabled(p.get());const m=e.Settings.Settings.instance().moduleSetting("avifFormatDisabled"),f=e.Settings.Settings.instance().moduleSetting("webpFormatDisabled"),b=()=>{const e=[];m.get()&&e.push("avif"),f.get()&&e.push("webp"),this.setDisabledImageTypes(e)};m.addChangeListener(b),f.addChangeListener(b),(m.get()||f.get())&&b(),this.#Ho=!0,this.#Do=!1,this.#Uo=!1,this.#qo=!1,this.#_o={enabled:!1,configuration:"mobile"}}setTouchEmulationAllowed(e){this.#Ho=e}supportsDeviceEmulation(){return this.target().hasAllCapabilities(z.DeviceEmulation)}async resetPageScaleFactor(){await this.#Oo.invoke_resetPageScaleFactor()}async emulateDevice(e){e?await this.#Oo.invoke_setDeviceMetricsOverride(e):await this.#Oo.invoke_clearDeviceMetricsOverride()}overlayModel(){return this.#Fo}async emulateLocation(e){if(!e||e.error)await Promise.all([this.#Oo.invoke_clearGeolocationOverride(),this.#Oo.invoke_setTimezoneOverride({timezoneId:""}),this.#Oo.invoke_setLocaleOverride({locale:""}),this.#Oo.invoke_setUserAgentOverride({userAgent:ue.instance().currentUserAgent()})]);else{function t(e,t){const n=t.getError();return n?Promise.reject({type:e,message:n}):Promise.resolve()}await Promise.all([this.#Oo.invoke_setGeolocationOverride({latitude:e.latitude,longitude:e.longitude,accuracy:ks.defaultGeoMockAccuracy}).then((e=>t("emulation-set-location",e))),this.#Oo.invoke_setTimezoneOverride({timezoneId:e.timezoneId}).then((e=>t("emulation-set-timezone",e))),this.#Oo.invoke_setLocaleOverride({locale:e.locale}).then((e=>t("emulation-set-locale",e))),this.#Oo.invoke_setUserAgentOverride({userAgent:ue.instance().currentUserAgent(),acceptLanguage:e.locale}).then((e=>t("emulation-set-user-agent",e)))])}}async emulateDeviceOrientation(e){e?await this.#No.invoke_setDeviceOrientationOverride({alpha:e.alpha,beta:e.beta,gamma:e.gamma}):await this.#No.invoke_clearDeviceOrientationOverride()}async setIdleOverride(e){await this.#Oo.invoke_setIdleOverride(e)}async clearIdleOverride(){await this.#Oo.invoke_clearIdleOverride()}async emulateCSSMedia(e,t){await this.#Oo.invoke_setEmulatedMedia({media:e,features:t}),this.#jr&&this.#jr.mediaQueryResultChanged()}async emulateAutoDarkMode(e){e&&(this.#Bo.set("prefers-color-scheme","dark"),await this.updateCssMedia()),await this.#Oo.invoke_setAutoDarkModeOverride({enabled:e||void 0})}async emulateVisionDeficiency(e){await this.#Oo.invoke_setEmulatedVisionDeficiency({type:e})}setLocalFontsDisabled(e){this.#jr&&this.#jr.setLocalFontsEnabled(!e)}setDisabledImageTypes(e){this.#Oo.invoke_setDisabledImageTypes({imageTypes:e})}async setCPUThrottlingRate(e){await this.#Oo.invoke_setCPUThrottlingRate({rate:e})}async setHardwareConcurrency(e){if(e<1)throw new Error("hardwareConcurrency must be a positive value");await this.#Oo.invoke_setHardwareConcurrencyOverride({hardwareConcurrency:e})}async emulateTouch(e,t){this.#Do=e&&this.#Ho,this.#Uo=t&&this.#Ho,await this.updateTouch()}async overrideEmulateTouch(e){this.#qo=e&&this.#Ho,await this.updateTouch()}async updateTouch(){let e={enabled:this.#Do,configuration:this.#Uo?"mobile":"desktop"};this.#qo&&(e={enabled:!0,configuration:"mobile"}),this.#Fo&&this.#Fo.inspectModeEnabled()&&(e={enabled:!1,configuration:"mobile"}),(this.#_o.enabled||e.enabled)&&(this.#_o.enabled&&e.enabled&&this.#_o.configuration===e.configuration||(this.#_o=e,await this.#Oo.invoke_setTouchEmulationEnabled({enabled:e.enabled,maxTouchPoints:1}),await this.#Oo.invoke_setEmitTouchEventsForMouse({enabled:e.enabled,configuration:e.configuration})))}async updateCssMedia(){const e=this.#Bo.get("type")??"",t=[{name:"color-gamut",value:this.#Bo.get("color-gamut")??""},{name:"prefers-color-scheme",value:this.#Bo.get("prefers-color-scheme")??""},{name:"forced-colors",value:this.#Bo.get("forced-colors")??""},{name:"prefers-contrast",value:this.#Bo.get("prefers-contrast")??""},{name:"prefers-reduced-data",value:this.#Bo.get("prefers-reduced-data")??""},{name:"prefers-reduced-motion",value:this.#Bo.get("prefers-reduced-motion")??""}];return this.emulateCSSMedia(e,t)}}class ks{latitude;longitude;timezoneId;locale;error;constructor(e,t,n,r,s){this.latitude=e,this.longitude=t,this.timezoneId=n,this.locale=r,this.error=s}static parseSetting(e){if(e){const[t,n,r,s]=e.split(":"),[i,a]=t.split("@");return new ks(parseFloat(i),parseFloat(a),n,r,Boolean(s))}return new ks(0,0,"","",!1)}static parseUserInput(e,t,n,r){if(!e&&!t)return null;const{valid:s}=ks.latitudeValidator(e),{valid:i}=ks.longitudeValidator(t);if(!s&&!i)return null;const a=s?parseFloat(e):-1,o=i?parseFloat(t):-1;return new ks(a,o,n,r,!1)}static latitudeValidator(e){const t=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&t>=-90&&t<=90,errorMessage:void 0}}static longitudeValidator(e){const t=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&t>=-180&&t<=180,errorMessage:void 0}}static timezoneIdValidator(e){return{valid:""===e||/[a-zA-Z]/.test(e),errorMessage:void 0}}static localeValidator(e){return{valid:""===e||/[a-zA-Z]{2}/.test(e),errorMessage:void 0}}toSetting(){return`${this.latitude}@${this.longitude}:${this.timezoneId}:${this.locale}:${this.error||""}`}static defaultGeoMockAccuracy=150}class Ss{alpha;beta;gamma;constructor(e,t,n){this.alpha=e,this.beta=t,this.gamma=n}static parseSetting(e){if(e){const t=JSON.parse(e);return new Ss(t.alpha,t.beta,t.gamma)}return new Ss(0,0,0)}static parseUserInput(e,t,n){if(!e&&!t&&!n)return null;const{valid:r}=Ss.alphaAngleValidator(e),{valid:s}=Ss.betaAngleValidator(t),{valid:i}=Ss.gammaAngleValidator(n);if(!r&&!s&&!i)return null;const a=r?parseFloat(e):-1,o=s?parseFloat(t):-1,l=i?parseFloat(n):-1;return new Ss(a,o,l)}static angleRangeValidator(e,t){const n=parseFloat(e);return{valid:/^([+-]?[\d]+(\.\d+)?|[+-]?\.\d+)$/.test(e)&&n>=t.minimum&&n{this.#Wo=n=>{e(n),t(n)}}:e=>{this.#Wo=e});const n=await e.runtimeAgent().invoke_evaluate({expression:"navigator.hardwareConcurrency",returnByValue:!0,silent:!0,throwOnSideEffect:!0}),r=n.getError();if(r)throw new Error(r);const{result:s,exceptionDetails:i}=n;if(i)throw new Error(i.text);return s.value}modelAdded(e){if(this.#zo!==xs.NoThrottling&&e.setCPUThrottlingRate(this.#zo),void 0!==this.#jo&&e.setHardwareConcurrency(this.#jo),this.#Wo){const e=this.#Wo;this.#Wo=void 0,this.getHardwareConcurrency().then(e)}}modelRemoved(e){}}var Rs,xs;!function(e){e.RateChanged="RateChanged",e.HardwareConcurrencyChanged="HardwareConcurrencyChanged"}(Rs||(Rs={})),function(e){e[e.NoThrottling=1]="NoThrottling",e[e.MidTierMobile=4]="MidTierMobile",e[e.LowEndMobile=6]="LowEndMobile"}(xs||(xs={}));var Ms=Object.freeze({__proto__:null,CPUThrottlingManager:Ts,get Events(){return Rs},throttlingManager:function(){return Ts.instance()},get CPUThrottlingRates(){return xs}});const Ps=new Set(["inherit","initial","unset"]),Ls=/[\x20-\x7E]{4}/,Es=new RegExp(`(?:'(${Ls.source})')|(?:"(${Ls.source})")\\s+(${/[+-]?(?:\d*\.)?\d+(?:[eE]\d+)?/.source})`);const As=/^"(.+)"|'(.+)'$/;function Os(e){return e.split(",").map((e=>e.trim()))}function Ns(e){return e.replaceAll(/(\/\*(?:.|\s)*?\*\/)/g,"")}var Fs=Object.freeze({__proto__:null,parseFontVariationSettings:function(e){if(Ps.has(e.trim())||"normal"===e.trim())return[];const t=[];for(const n of Os(Ns(e))){const e=n.match(Es);e&&t.push({tag:e[1]||e[2],value:parseFloat(e[3])})}return t},parseFontFamily:function(e){if(Ps.has(e.trim()))return[];const t=[];for(const n of Os(Ns(e))){const e=n.match(As);e?t.push(e[1]||e[2]):t.push(n)}return t},splitByComma:Os,stripComments:Ns});const Bs={trustedTypeViolations:"Trusted Type Violations",sinkViolations:"Sink Violations",policyViolations:"Policy Violations",animation:"Animation",canvas:"Canvas",geolocation:"Geolocation",notification:"Notification",parse:"Parse",script:"Script",timer:"Timer",window:"Window",webaudio:"WebAudio",media:"Media",pictureinpicture:"Picture-in-Picture",clipboard:"Clipboard",control:"Control",device:"Device",domMutation:"DOM Mutation",dragDrop:"Drag / drop",keyboard:"Keyboard",load:"Load",mouse:"Mouse",pointer:"Pointer",touch:"Touch",xhr:"XHR",setTimeoutOrIntervalFired:"{PH1} fired",scriptFirstStatement:"Script First Statement",scriptBlockedByContentSecurity:"Script Blocked by Content Security Policy",requestAnimationFrame:"Request Animation Frame",cancelAnimationFrame:"Cancel Animation Frame",animationFrameFired:"Animation Frame Fired",webglErrorFired:"WebGL Error Fired",webglWarningFired:"WebGL Warning Fired",setInnerhtml:"Set `innerHTML`",createCanvasContext:"Create canvas context",createAudiocontext:"Create `AudioContext`",closeAudiocontext:"Close `AudioContext`",resumeAudiocontext:"Resume `AudioContext`",suspendAudiocontext:"Suspend `AudioContext`",webglErrorFiredS:"WebGL Error Fired ({PH1})",scriptBlockedDueToContent:"Script blocked due to Content Security Policy directive: {PH1}",worker:"Worker"},Ds=s.i18n.registerUIStrings("core/sdk/DOMDebuggerModel.ts",Bs),Us=s.i18n.getLocalizedString.bind(void 0,Ds);class Hs extends c{agent;#ba;#Mr;#Vo;#Go;suspended=!1;constructor(t){super(t),this.agent=t.domdebuggerAgent(),this.#ba=t.model(Cr),this.#Mr=t.model(Pn),this.#Mr.addEventListener(wn.DocumentUpdated,this.documentUpdated,this),this.#Mr.addEventListener(wn.NodeRemoved,this.nodeRemoved,this),this.#Vo=[],this.#Go=e.Settings.Settings.instance().createLocalSetting("domBreakpoints",[]),this.#Mr.existingDocument()&&this.documentUpdated()}runtimeModel(){return this.#ba}async suspendModel(){this.suspended=!0}async resumeModel(){this.suspended=!1}async eventListeners(e){if(console.assert(e.runtimeModel()===this.#ba),!e.objectId)return[];const t=await this.agent.invoke_getEventListeners({objectId:e.objectId}),n=[];for(const r of t.listeners||[]){const t=this.#ba.debuggerModel().createRawLocationByScriptId(r.scriptId,r.lineNumber,r.columnNumber);t&&n.push(new js(this,e,r.type,r.useCapture,r.passive,r.once,r.handler?this.#ba.createRemoteObject(r.handler):null,r.originalHandler?this.#ba.createRemoteObject(r.originalHandler):null,t,null))}return n}retrieveDOMBreakpoints(){this.#Mr.requestDocument()}domBreakpoints(){return this.#Vo.slice()}hasDOMBreakpoint(e,t){return this.#Vo.some((n=>n.node===e&&n.type===t))}setDOMBreakpoint(e,t){for(const n of this.#Vo)if(n.node===e&&n.type===t)return this.toggleDOMBreakpoint(n,!0),n;const n=new zs(this,e,t,!0);return this.#Vo.push(n),this.saveDOMBreakpoints(),this.enableDOMBreakpoint(n),this.dispatchEventToListeners(qs.DOMBreakpointAdded,n),n}removeDOMBreakpoint(e,t){this.removeDOMBreakpoints((n=>n.node===e&&n.type===t))}removeAllDOMBreakpoints(){this.removeDOMBreakpoints((e=>!0))}toggleDOMBreakpoint(e,t){t!==e.enabled&&(e.enabled=t,t?this.enableDOMBreakpoint(e):this.disableDOMBreakpoint(e),this.dispatchEventToListeners(qs.DOMBreakpointToggled,e))}enableDOMBreakpoint(e){e.node.id&&(this.agent.invoke_setDOMBreakpoint({nodeId:e.node.id,type:e.type}),e.node.setMarker(_s,!0))}disableDOMBreakpoint(e){e.node.id&&(this.agent.invoke_removeDOMBreakpoint({nodeId:e.node.id,type:e.type}),e.node.setMarker(_s,!!this.nodeHasBreakpoints(e.node)||null))}nodeHasBreakpoints(e){for(const t of this.#Vo)if(t.node===e&&t.enabled)return!0;return!1}resolveDOMBreakpointData(e){const t=e.type,n=this.#Mr.nodeForId(e.nodeId);if(!t||!n)return null;let r=null,s=!1;return"subtree-modified"===t&&(s=e.insertion||!1,r=this.#Mr.nodeForId(e.targetNodeId)),{type:t,node:n,targetNode:r,insertion:s}}currentURL(){const e=this.#Mr.existingDocument();return e?e.documentURL:t.DevToolsPath.EmptyUrlString}async documentUpdated(){if(this.suspended)return;const e=this.#Vo;this.#Vo=[],this.dispatchEventToListeners(qs.DOMBreakpointsRemoved,e);const n=await this.#Mr.requestDocument(),r=n?n.documentURL:t.DevToolsPath.EmptyUrlString;for(const e of this.#Go.get())e.url===r&&this.#Mr.pushNodeByPathToFrontend(e.path).then(s.bind(this,e));function s(e,t){const n=t?this.#Mr.nodeForId(t):null;if(!n)return;const r=new zs(this,n,e.type,e.enabled);this.#Vo.push(r),e.enabled&&this.enableDOMBreakpoint(r),this.dispatchEventToListeners(qs.DOMBreakpointAdded,r)}}removeDOMBreakpoints(e){const t=[],n=[];for(const r of this.#Vo)e(r)?(t.push(r),r.enabled&&(r.enabled=!1,this.disableDOMBreakpoint(r))):n.push(r);t.length&&(this.#Vo=n,this.saveDOMBreakpoints(),this.dispatchEventToListeners(qs.DOMBreakpointsRemoved,t))}nodeRemoved(e){if(this.suspended)return;const{node:t}=e.data,n=t.children()||[];this.removeDOMBreakpoints((e=>e.node===t||-1!==n.indexOf(e.node)))}saveDOMBreakpoints(){const e=this.currentURL(),t=this.#Go.get().filter((t=>t.url!==e));for(const n of this.#Vo)t.push({url:e,path:n.node.path(),type:n.type,enabled:n.enabled});this.#Go.set(t)}}var qs;!function(e){e.DOMBreakpointAdded="DOMBreakpointAdded",e.DOMBreakpointToggled="DOMBreakpointToggled",e.DOMBreakpointsRemoved="DOMBreakpointsRemoved"}(qs||(qs={}));const _s="breakpoint-marker";class zs{domDebuggerModel;node;type;enabled;constructor(e,t,n,r){this.domDebuggerModel=e,this.node=t,this.type=n,this.enabled=r}}class js{#Ko;#$o;#p;#Qo;#Xo;#Jo;#Yo;#Zo;#na;#el;#tl;#nl;constructor(e,n,r,s,i,a,o,l,d,c,h){this.#Ko=e,this.#$o=n,this.#p=r,this.#Qo=s,this.#Xo=i,this.#Jo=a,this.#Yo=o,this.#Zo=l||o,this.#na=d;const u=d.script();this.#el=u?u.contentURL():t.DevToolsPath.EmptyUrlString,this.#tl=c,this.#nl=h||js.Origin.Raw}domDebuggerModel(){return this.#Ko}type(){return this.#p}useCapture(){return this.#Qo}passive(){return this.#Xo}once(){return this.#Jo}handler(){return this.#Yo}location(){return this.#na}sourceURL(){return this.#el}originalHandler(){return this.#Zo}canRemove(){return Boolean(this.#tl)||this.#nl!==js.Origin.FrameworkUser}remove(){if(!this.canRemove())return Promise.resolve(void 0);if(this.#nl!==js.Origin.FrameworkUser){function e(e,t,n){this.removeEventListener(e,t,n),this["on"+e]&&(this["on"+e]=void 0)}return this.#$o.callFunction(e,[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo)]).then((()=>{}))}if(this.#tl){function e(e,t,n,r){this.call(null,e,t,n,r)}return this.#tl.callFunction(e,[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo),Le.toCallArgument(this.#Xo)]).then((()=>{}))}return Promise.resolve(void 0)}canTogglePassive(){return this.#nl!==js.Origin.FrameworkUser}togglePassive(){return this.#$o.callFunction((function(e,t,n,r){this.removeEventListener(e,t,{capture:n}),this.addEventListener(e,t,{capture:n,passive:!r})}),[Le.toCallArgument(this.#p),Le.toCallArgument(this.#Zo),Le.toCallArgument(this.#Qo),Le.toCallArgument(this.#Xo)]).then((()=>{}))}origin(){return this.#nl}markAsFramework(){this.#nl=js.Origin.Framework}isScrollBlockingType(){return"touchstart"===this.#p||"touchmove"===this.#p||"mousewheel"===this.#p||"wheel"===this.#p}}!function(e){let t;!function(e){e.Raw="Raw",e.Framework="Framework",e.FrameworkUser="FrameworkUser"}(t=e.Origin||(e.Origin={}))}(js||(js={}));class Ws extends Fr{#p;constructor(e,t,n){super(e,t),this.#p=n}type(){return this.#p}}class Vs extends Fr{instrumentationName;eventName;eventTargetNames;constructor(e,t,n,r,s){super(r,s),this.instrumentationName=e,this.eventName=t,this.eventTargetNames=n}setEnabled(e){if(this.enabled()!==e){super.setEnabled(e);for(const e of K.instance().models(Hs))this.updateOnModel(e)}}updateOnModel(e){if(this.instrumentationName)this.enabled()?e.agent.invoke_setInstrumentationBreakpoint({eventName:this.instrumentationName}):e.agent.invoke_removeInstrumentationBreakpoint({eventName:this.instrumentationName});else for(const t of this.eventTargetNames)this.enabled()?e.agent.invoke_setEventListenerBreakpoint({eventName:this.eventName,targetName:t}):e.agent.invoke_removeEventListenerBreakpoint({eventName:this.eventName,targetName:t})}static listener="listener:";static instrumentation="instrumentation:"}let Gs;class Ks{#rl;#sl;#il;#al;constructor(){this.#rl=e.Settings.Settings.instance().createLocalSetting("xhrBreakpoints",[]),this.#sl=new Map;for(const e of this.#rl.get())this.#sl.set(e.url,e.enabled);this.#il=[],this.#il.push(new Ws(Us(Bs.trustedTypeViolations),Us(Bs.sinkViolations),"trustedtype-sink-violation")),this.#il.push(new Ws(Us(Bs.trustedTypeViolations),Us(Bs.policyViolations),"trustedtype-policy-violation")),this.#al=[],this.createInstrumentationBreakpoints(Us(Bs.animation),["requestAnimationFrame","cancelAnimationFrame","requestAnimationFrame.callback"]),this.createInstrumentationBreakpoints(Us(Bs.canvas),["canvasContextCreated","webglErrorFired","webglWarningFired"]),this.createInstrumentationBreakpoints(Us(Bs.geolocation),["Geolocation.getCurrentPosition","Geolocation.watchPosition"]),this.createInstrumentationBreakpoints(Us(Bs.notification),["Notification.requestPermission"]),this.createInstrumentationBreakpoints(Us(Bs.parse),["Element.setInnerHTML","Document.write"]),this.createInstrumentationBreakpoints(Us(Bs.script),["scriptFirstStatement","scriptBlockedByCSP"]),this.createInstrumentationBreakpoints(Us(Bs.timer),["setTimeout","clearTimeout","setInterval","clearInterval","setTimeout.callback","setInterval.callback"]),this.createInstrumentationBreakpoints(Us(Bs.window),["DOMWindow.close"]),this.createInstrumentationBreakpoints(Us(Bs.webaudio),["audioContextCreated","audioContextClosed","audioContextResumed","audioContextSuspended"]),this.createEventListenerBreakpoints(Us(Bs.media),["play","pause","playing","canplay","canplaythrough","seeking","seeked","timeupdate","ended","ratechange","durationchange","volumechange","loadstart","progress","suspend","abort","error","emptied","stalled","loadedmetadata","loadeddata","waiting"],["audio","video"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["enterpictureinpicture","leavepictureinpicture"],["video"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["resize"],["PictureInPictureWindow"]),this.createEventListenerBreakpoints(Us(Bs.pictureinpicture),["enter"],["documentPictureInPicture"]),this.createEventListenerBreakpoints(Us(Bs.clipboard),["copy","cut","paste","beforecopy","beforecut","beforepaste"],["*"]),this.createEventListenerBreakpoints(Us(Bs.control),["resize","scroll","scrollend","zoom","focus","blur","select","change","submit","reset"],["*"]),this.createEventListenerBreakpoints(Us(Bs.device),["deviceorientation","devicemotion"],["*"]),this.createEventListenerBreakpoints(Us(Bs.domMutation),["DOMActivate","DOMFocusIn","DOMFocusOut","DOMAttrModified","DOMCharacterDataModified","DOMNodeInserted","DOMNodeInsertedIntoDocument","DOMNodeRemoved","DOMNodeRemovedFromDocument","DOMSubtreeModified","DOMContentLoaded"],["*"]),this.createEventListenerBreakpoints(Us(Bs.dragDrop),["drag","dragstart","dragend","dragenter","dragover","dragleave","drop"],["*"]),this.createEventListenerBreakpoints(Us(Bs.keyboard),["keydown","keyup","keypress","input"],["*"]),this.createEventListenerBreakpoints(Us(Bs.load),["load","beforeunload","unload","abort","error","hashchange","popstate","navigate","navigatesuccess","navigateerror","currentchange","navigateto","navigatefrom","finish","dispose"],["*"]),this.createEventListenerBreakpoints(Us(Bs.mouse),["auxclick","click","dblclick","mousedown","mouseup","mouseover","mousemove","mouseout","mouseenter","mouseleave","mousewheel","wheel","contextmenu"],["*"]),this.createEventListenerBreakpoints(Us(Bs.pointer),["pointerover","pointerout","pointerenter","pointerleave","pointerdown","pointerup","pointermove","pointercancel","gotpointercapture","lostpointercapture","pointerrawupdate"],["*"]),this.createEventListenerBreakpoints(Us(Bs.touch),["touchstart","touchmove","touchend","touchcancel"],["*"]),this.createEventListenerBreakpoints(Us(Bs.worker),["message","messageerror"],["*"]),this.createEventListenerBreakpoints(Us(Bs.xhr),["readystatechange","load","loadstart","loadend","abort","error","progress","timeout"],["xmlhttprequest","xmlhttprequestupload"]);for(const[e,t]of[["setTimeout.callback",Us(Bs.setTimeoutOrIntervalFired,{PH1:"setTimeout"})],["setInterval.callback",Us(Bs.setTimeoutOrIntervalFired,{PH1:"setInterval"})],["scriptFirstStatement",Us(Bs.scriptFirstStatement)],["scriptBlockedByCSP",Us(Bs.scriptBlockedByContentSecurity)],["requestAnimationFrame",Us(Bs.requestAnimationFrame)],["cancelAnimationFrame",Us(Bs.cancelAnimationFrame)],["requestAnimationFrame.callback",Us(Bs.animationFrameFired)],["webglErrorFired",Us(Bs.webglErrorFired)],["webglWarningFired",Us(Bs.webglWarningFired)],["Element.setInnerHTML",Us(Bs.setInnerhtml)],["canvasContextCreated",Us(Bs.createCanvasContext)],["Geolocation.getCurrentPosition","getCurrentPosition"],["Geolocation.watchPosition","watchPosition"],["Notification.requestPermission","requestPermission"],["DOMWindow.close","window.close"],["Document.write","document.write"],["audioContextCreated",Us(Bs.createAudiocontext)],["audioContextClosed",Us(Bs.closeAudiocontext)],["audioContextResumed",Us(Bs.resumeAudiocontext)],["audioContextSuspended",Us(Bs.suspendAudiocontext)]]){const n=this.resolveEventListenerBreakpointInternal("instrumentation:"+e);n&&n.setTitle(t)}K.instance().observeModels(Hs,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return Gs&&!t||(Gs=new Ks),Gs}cspViolationBreakpoints(){return this.#il.slice()}createInstrumentationBreakpoints(e,t){for(const n of t)this.#al.push(new Vs(n,"",[],e,n))}createEventListenerBreakpoints(e,t,n){for(const r of t)this.#al.push(new Vs("",r,n,e,r))}resolveEventListenerBreakpointInternal(e,t){const n="instrumentation:",r="listener:";let s="";if(e.startsWith(n))s=e.substring(n.length),e="";else{if(!e.startsWith(r))return null;e=e.substring(r.length)}t=(t||"*").toLowerCase();let i=null;for(const n of this.#al)s&&n.instrumentationName===s&&(i=n),e&&n.eventName===e&&-1!==n.eventTargetNames.indexOf(t)&&(i=n),!i&&e&&n.eventName===e&&-1!==n.eventTargetNames.indexOf("*")&&(i=n);return i}eventListenerBreakpoints(){return this.#al.slice()}resolveEventListenerBreakpointTitle(e){const t=e.eventName;if("instrumentation:webglErrorFired"===t&&e.webglErrorName){let t=e.webglErrorName;return t=t.replace(/^.*(0x[0-9a-f]+).*$/i,"$1"),Us(Bs.webglErrorFiredS,{PH1:t})}if("instrumentation:scriptBlockedByCSP"===t&&e.directiveText)return Us(Bs.scriptBlockedDueToContent,{PH1:e.directiveText});const n=this.resolveEventListenerBreakpointInternal(t,e.targetName);return n?e.targetName?e.targetName+"."+n.title():n.title():""}resolveEventListenerBreakpoint(e){return this.resolveEventListenerBreakpointInternal(e.eventName,e.targetName)}updateCSPViolationBreakpoints(){const e=this.#il.filter((e=>e.enabled())).map((e=>e.type()));for(const t of K.instance().models(Hs))this.updateCSPViolationBreakpointsForModel(t,e)}updateCSPViolationBreakpointsForModel(e,t){e.agent.invoke_setBreakOnCSPViolation({violationTypes:t})}xhrBreakpoints(){return this.#sl}saveXHRBreakpoints(){const e=[];for(const t of this.#sl.keys())e.push({url:t,enabled:this.#sl.get(t)||!1});this.#rl.set(e)}addXHRBreakpoint(e,t){if(this.#sl.set(e,t),t)for(const t of K.instance().models(Hs))t.agent.invoke_setXHRBreakpoint({url:e});this.saveXHRBreakpoints()}removeXHRBreakpoint(e){const t=this.#sl.get(e);if(this.#sl.delete(e),t)for(const t of K.instance().models(Hs))t.agent.invoke_removeXHRBreakpoint({url:e});this.saveXHRBreakpoints()}toggleXHRBreakpoint(e,t){this.#sl.set(e,t);for(const n of K.instance().models(Hs))t?n.agent.invoke_setXHRBreakpoint({url:e}):n.agent.invoke_removeXHRBreakpoint({url:e});this.saveXHRBreakpoints()}modelAdded(e){for(const t of this.#sl.keys())this.#sl.get(t)&&e.agent.invoke_setXHRBreakpoint({url:t});for(const t of this.#al)t.enabled()&&t.updateOnModel(e);const t=this.#il.filter((e=>e.enabled())).map((e=>e.type()));this.updateCSPViolationBreakpointsForModel(e,t)}modelRemoved(e){}}c.register(Hs,{capabilities:z.DOM,autostart:!1});var $s=Object.freeze({__proto__:null,DOMDebuggerModel:Hs,get Events(){return qs},DOMBreakpoint:zs,get EventListener(){return js},CSPViolationBreakpoint:Ws,DOMEventListenerBreakpoint:Vs,DOMDebuggerManager:Ks});const Qs={auctionWorklet:"Ad Auction Worklet",beforeBidderWorkletBiddingStart:"Bidder Bidding Phase Start",beforeBidderWorkletReportingStart:"Bidder Reporting Phase Start",beforeSellerWorkletScoringStart:"Seller Scoring Phase Start",beforeSellerWorkletReportingStart:"Seller Reporting Phase Start"},Xs=s.i18n.registerUIStrings("core/sdk/EventBreakpointsModel.ts",Qs),Js=s.i18n.getLocalizedString.bind(void 0,Xs);class Ys extends c{agent;constructor(e){super(e),this.agent=e.eventBreakpointsAgent()}}class Zs extends Fr{instrumentationName;constructor(e,t){super(t,function(e){switch(e){case"beforeBidderWorkletBiddingStart":return Js(Qs.beforeBidderWorkletBiddingStart);case"beforeBidderWorkletReportingStart":return Js(Qs.beforeBidderWorkletReportingStart);case"beforeSellerWorkletScoringStart":return Js(Qs.beforeSellerWorkletScoringStart);case"beforeSellerWorkletReportingStart":return Js(Qs.beforeSellerWorkletReportingStart)}}(e)),this.instrumentationName=e}setEnabled(e){if(this.enabled()!==e){super.setEnabled(e);for(const e of K.instance().models(Ys))this.updateOnModel(e)}}updateOnModel(e){this.enabled()?e.agent.invoke_setInstrumentationBreakpoint({eventName:this.instrumentationName}):e.agent.invoke_removeInstrumentationBreakpoint({eventName:this.instrumentationName})}static instrumentationPrefix="instrumentation:"}let ei;class ti{#al=[];constructor(){this.createInstrumentationBreakpoints(Js(Qs.auctionWorklet),["beforeBidderWorkletBiddingStart","beforeBidderWorkletReportingStart","beforeSellerWorkletScoringStart","beforeSellerWorkletReportingStart"]),K.instance().observeModels(Ys,this)}static instance(e={forceNew:null}){const{forceNew:t}=e;return ei&&!t||(ei=new ti),ei}createInstrumentationBreakpoints(e,t){for(const n of t)this.#al.push(new Zs(n,e))}eventListenerBreakpoints(){return this.#al.slice()}resolveEventListenerBreakpointTitle(e){const t=this.resolveEventListenerBreakpoint(e);return t?t.title():null}resolveEventListenerBreakpoint(e){const t=e.eventName;if(!t.startsWith(Zs.instrumentationPrefix))return null;const n=t.substring(Zs.instrumentationPrefix.length);return this.#al.find((e=>e.instrumentationName===n))||null}modelAdded(e){for(const t of this.#al)t.enabled()&&t.updateOnModel(e)}modelRemoved(e){}}c.register(Ys,{capabilities:z.EventBreakpoints,autostart:!1});var ni=Object.freeze({__proto__:null,EventBreakpointsModel:Ys,EventBreakpointsManager:ti});class ri{#ol;#ll;#dl;#cl;#hl;#ul;#gl;#pl;#ml;#fl;#bl;#yl;#vl=[];constructor(e){this.#ol=e,this.#ll=new Map,this.#dl=new Map,this.#cl=Number(1/0),this.#hl=Number(-1/0),this.#ul=[],this.#gl=[],this.#pl=new Map,this.#ml=new Map,this.#fl=new Map,this.#bl=new Map,this.#yl=new Map}static isTopLevelEvent(e){return vi(e,li)&&"RunTask"===e.name||vi(e,ai)||vi(e,oi)&&"Program"===e.name}static extractId(e){const t=e.scope||"";if(void 0===e.id2)return t&&e.id?`${t}@${e.id}`:e.id;const n=e.id2;if("object"==typeof n&&"global"in n!="local"in n)return void 0!==n.global?`:${t}:${n.global}`:`:${t}:${e.pid}:${n.local}`;console.error(`Unexpected id2 field at ${e.ts/1e3}, one and only one of 'local' and 'global' should be present.`)}static browserMainThread(t){const n=t.sortedProcesses();if(!n.length)return null;const r="CrBrowserMain",s=[],i=[];for(const e of n)e.name().toLowerCase().endsWith("browser")&&s.push(e),i.push(...e.sortedThreads().filter((e=>e.name()===r)));if(1===i.length)return i[0];if(1===s.length)return s[0].threadByName(r);const a=t.devToolsMetadataEvents().filter((e=>"TracingStartedInBrowser"===e.name));return 1===a.length?a[0].thread:(e.Console.Console.instance().error("Failed to find browser main thread in trace, some timeline features may be unavailable"),null)}allRawEvents(){return this.#vl}devToolsMetadataEvents(){return this.#ul}addEvents(e){for(let t=0;te.#kl!==t.#kl?e.#kl-t.#kl:e.name().localeCompare(t.name())))}setName(e){this.#u=e}name(){return this.#u}id(){return this.idInternal}setSortIndex(e){this.#kl=e}getModel(){return this.model}}class fi extends mi{threads;#Sl;constructor(e,t){super(e,t),this.threads=new Map,this.#Sl=new Map}threadById(e){let t=this.threads.get(e);return t||(t=new bi(this,e),this.threads.set(e,t)),t}threadByName(e){return this.#Sl.get(e)||null}setThreadByName(e,t){this.#Sl.set(e,t)}addEvent(e){return this.threadById(e.tid).addEvent(e)}sortedThreads(){return mi.sort([...this.threads.values()])}}class bi extends mi{#wl;#Cl;#Tl;#Rl;constructor(e,t){super(e.getModel(),t),this.#wl=e,this.#Cl=[],this.#Tl=[],this.#Rl=null}#xl(e,t){return e.phase===t}tracingComplete(){this.#Tl.sort(di.compareStartTime),this.#Cl.sort(di.compareStartTime);const e=[],t=new Set;for(let n=0;n!t.has(n)))}addEvent(e){const t="O"===e.ph?ui.fromPayload(e,this):hi.fromPayload(e,this);if(ri.isTopLevelEvent(t)){const e=this.#Rl;if(e&&(e.endTime||0)>t.startTime)return null;this.#Rl=t}return this.#Cl.push(t),t}addAsyncEvent(e){this.#Tl.push(e)}setName(e){super.setName(e),this.#wl.setThreadByName(e,this)}process(){return this.#wl}events(){return this.#Cl}asyncEvents(){return this.#Tl}removeEventsByName(e){const t=[];return this.#Cl=this.#Cl.filter((n=>!!n&&(n.name!==e||(t.push(n),!1)))),t}}const yi=new Map;function vi(e,t){if(e instanceof di)return e.hasCategory(t);let n=yi.get(e.cat);return n||(n=new Set(e.cat.split(",")||[])),n.has(t)}var Ii=Object.freeze({__proto__:null,TracingModel:ri,eventPhasesOfInterestForTraceBounds:si,MetadataEvent:ii,LegacyTopLevelEventCategory:ai,DevToolsMetadataEventCategory:oi,DevToolsTimelineEventCategory:li,eventHasPayload:function(e){return"rawPayload"in e},Event:di,ConstructedEvent:ci,PayloadEvent:hi,ObjectSnapshot:ui,AsyncEvent:gi,Process:fi,Thread:bi,timesForEventInMilliseconds:function(e){if(e instanceof di)return{startTime:l.Types.Timing.MilliSeconds(e.startTime),endTime:e.endTime?l.Types.Timing.MilliSeconds(e.endTime):void 0,duration:l.Types.Timing.MilliSeconds(e.duration||0),selfTime:l.Types.Timing.MilliSeconds(e.selfTime)};const t=e.dur?l.Helpers.Timing.microSecondsToMilliseconds(e.dur):l.Types.Timing.MilliSeconds(0);return{startTime:l.Helpers.Timing.microSecondsToMilliseconds(e.ts),endTime:l.Helpers.Timing.microSecondsToMilliseconds(l.Types.Timing.MicroSeconds(e.ts+(e.dur||0))),duration:e.dur?l.Helpers.Timing.microSecondsToMilliseconds(e.dur):l.Types.Timing.MilliSeconds(0),selfTime:t}},eventHasCategory:vi,phaseForEvent:function(e){return e instanceof di?e.phase:e.ph},threadIDForEvent:function(e){return e instanceof di?e.thread.idInternal:e.tid},eventIsFromNewEngine:function(e){return null!==e&&!(e instanceof di)}});const ki="disabled-by-default-devtools.screenshot",Si={Screenshot:"Screenshot"};class wi{#Ml;timestamp;index;#Pl;#Ll;constructor(e,t,n){this.#Ml=e,this.timestamp=t,this.index=n,this.#Ll=null,this.#Pl=null}static fromSnapshot(e,t,n){const r=new wi(e,t.startTime,n);return r.#Pl=t,r}static fromTraceEvent(e,t,n){const r=l.Helpers.Timing.microSecondsToMilliseconds(t.ts),s=new wi(e,r,n);return s.#Ll=t,s}model(){return this.#Ml}imageDataPromise(){return this.#Ll?Promise.resolve(this.#Ll.args.snapshot):this.#Pl?Promise.resolve(this.#Pl.getSnapshot()):Promise.resolve(null)}}var Ci=Object.freeze({__proto__:null,FilmStripModel:class{#Ve;#El;#Al;constructor(e,t){this.#Ve=[],this.#El=0,this.#Al=0,this.reset(e,t)}hasFrames(){return this.#Ve.length>0}reset(e,t){this.#El=t||e.minimumRecordTime(),this.#Al=e.maximumRecordTime()-this.#El,this.#Ve=[];const n=ri.browserMainThread(e);if(!n)return;const r=n.events();for(let e=0;et.timestampe.update()))),await new Promise((e=>window.setTimeout(e,Pi)))}}var Mi;(Mi||(Mi={})).MemoryChanged="MemoryChanged";const Pi=2e3;class Li{#E;modelsInternal;#Bl;#Dl;constructor(e){this.#E=e,this.modelsInternal=new Set,this.#Bl=0;const t=12e4/Pi;this.#Dl=new Ei(t)}id(){return this.#E}models(){return this.modelsInternal}runtimeModel(){return this.modelsInternal.values().next().value||null}heapProfilerModel(){const e=this.runtimeModel();return e&&e.heapProfilerModel()}async update(){const e=this.runtimeModel(),t=e&&await e.heapUsage();t&&(this.#Bl=t.usedSize,this.#Dl.add(this.#Bl),xi.instance().dispatchEventToListeners(Mi.MemoryChanged,this))}samplesCount(){return this.#Dl.count()}usedHeapSize(){return this.#Bl}usedHeapSizeGrowRate(){return this.#Dl.fitSlope()}isMainThread(){const e=this.runtimeModel();return!!e&&"main"===e.target().id()}}class Ei{#Ul;#Hl;#Kr;#ql;#_l;#zl;#jl;#Wl;#Vl;constructor(e){this.#Ul=0|e,this.reset()}reset(){this.#Hl=Date.now(),this.#Kr=0,this.#ql=[],this.#_l=[],this.#zl=0,this.#jl=0,this.#Wl=0,this.#Vl=0}count(){return this.#ql.length}add(e,t){const n="number"==typeof t?t:Date.now()-this.#Hl,r=e;if(this.#ql.length===this.#Ul){const e=this.#ql[this.#Kr],t=this.#_l[this.#Kr];this.#zl-=e,this.#jl-=t,this.#Wl-=e*e,this.#Vl-=e*t}this.#zl+=n,this.#jl+=r,this.#Wl+=n*n,this.#Vl+=n*r,this.#ql[this.#Kr]=n,this.#_l[this.#Kr]=r,this.#Kr=(this.#Kr+1)%this.#Ul}fitSlope(){const e=this.count();return e<2?0:(this.#Vl-this.#zl*this.#jl/e)/(this.#Wl-this.#zl*this.#zl/e)}}var Ai=Object.freeze({__proto__:null,IsolateManager:xi,get Events(){return Mi},MemoryTrendWindowMs:12e4,Isolate:Li,MemoryTrend:Ei});class Oi extends c{#Gl=!1;#ma=!1;constructor(e){super(e),this.ensureEnabled()}async ensureEnabled(){if(this.#ma)return;this.#ma=!0,this.target().registerAuditsDispatcher(this);const e=this.target().auditsAgent();await e.invoke_enable()}issueAdded(e){this.dispatchEventToListeners("IssueAdded",{issuesModel:this,inspectorIssue:e.issue})}dispose(){super.dispose(),this.#Gl=!0}getTargetIfNotDisposed(){return this.#Gl?null:this.target()}}c.register(Oi,{capabilities:z.Audits,autostart:!0});var Ni,Fi=Object.freeze({__proto__:null,IssuesModel:Oi});!function(e){let t;!function(e){e.NonFastScrollable="NonFastScrollable",e.TouchEventHandler="TouchEventHandler",e.WheelEventHandler="WheelEventHandler",e.RepaintsOnScroll="RepaintsOnScroll",e.MainThreadScrollingReason="MainThreadScrollingReason"}(t=e.ScrollRectType||(e.ScrollRectType={}))}(Ni||(Ni={}));var Bi=Object.freeze({__proto__:null,get Layer(){return Ni},StickyPositionConstraint:class{#Kl;#$l;#Ql;#Xl;constructor(e,t){this.#Kl=t.stickyBoxRect,this.#$l=t.containingBlockRect,this.#Ql=null,e&&t.nearestLayerShiftingStickyBox&&(this.#Ql=e.layerById(t.nearestLayerShiftingStickyBox)),this.#Xl=null,e&&t.nearestLayerShiftingContainingBlock&&(this.#Xl=e.layerById(t.nearestLayerShiftingContainingBlock))}stickyBoxRect(){return this.#Kl}containingBlockRect(){return this.#$l}nearestLayerShiftingStickyBox(){return this.#Ql}nearestLayerShiftingContainingBlock(){return this.#Xl}},LayerTreeBase:class{#e;#Mr;layersById;#Jl;#Yl;#Zl;#ed;constructor(e){this.#e=e,this.#Mr=e?e.model(Pn):null,this.layersById=new Map,this.#Jl=null,this.#Yl=null,this.#Zl=new Map}target(){return this.#e}root(){return this.#Jl}setRoot(e){this.#Jl=e}contentRoot(){return this.#Yl}setContentRoot(e){this.#Yl=e}forEachLayer(e,t){return!(!t&&!(t=this.root()))&&(e(t)||t.children().some(this.forEachLayer.bind(this,e)))}layerById(e){return this.layersById.get(e)||null}async resolveBackendNodeIds(e){if(!e.size||!this.#Mr)return;const t=await this.#Mr.pushNodesByBackendIdsToFrontend(e);if(t)for(const e of t.keys())this.#Zl.set(e,t.get(e)||null)}backendNodeIdToNode(){return this.#Zl}setViewportSize(e){this.#ed=e}viewportSize(){return this.#ed}nodeForId(e){return this.#Mr?this.#Mr.nodeForId(e):null}}});class Di{id;url;startTime;loadTime;contentLoadTime;mainRequest;constructor(e){this.id=++Di.lastIdentifier,this.url=e.url(),this.startTime=e.startTime,this.mainRequest=e}static forRequest(e){return Ui.get(e)||null}bindRequest(e){Ui.set(e,this)}static lastIdentifier=0}const Ui=new WeakMap;var Hi=Object.freeze({__proto__:null,PageLoad:Di});class qi extends c{layerTreeAgent;constructor(e){super(e),this.layerTreeAgent=e.layerTreeAgent()}async loadSnapshotFromFragments(e){const{snapshotId:t}=await this.layerTreeAgent.invoke_loadSnapshot({tiles:e});return t?new _i(this,t):null}loadSnapshot(e){const t={x:0,y:0,picture:e};return this.loadSnapshotFromFragments([t])}async makeSnapshot(e){const{snapshotId:t}=await this.layerTreeAgent.invoke_makeSnapshot({layerId:e});return t?new _i(this,t):null}}class _i{#td;#nd;#rd;constructor(e,t){this.#td=e,this.#nd=t,this.#rd=1}release(){console.assert(this.#rd>0,"release is already called on the object"),--this.#rd||this.#td.layerTreeAgent.invoke_releaseSnapshot({snapshotId:this.#nd})}addReference(){++this.#rd,console.assert(this.#rd>0,"Referencing a dead object")}async replay(e,t,n){return(await this.#td.layerTreeAgent.invoke_replaySnapshot({snapshotId:this.#nd,fromStep:t,toStep:n,scale:e||1})).dataURL}async profile(e){return(await this.#td.layerTreeAgent.invoke_profileSnapshot({snapshotId:this.#nd,minRepeatCount:5,minDuration:1,clipRect:e||void 0})).timings}async commandLog(){const e=await this.#td.layerTreeAgent.invoke_snapshotCommandLog({snapshotId:this.#nd});return e.commandLog?e.commandLog.map(((e,t)=>new zi(e,t))):null}}class zi{method;params;commandIndex;constructor(e,t){this.method=e.method,this.params=e.params,this.commandIndex=t}}c.register(qi,{capabilities:z.DOM,autostart:!1});var ji=Object.freeze({__proto__:null,PaintProfilerModel:qi,PaintProfilerSnapshot:_i,PaintProfilerLogItem:zi});class Wi extends c{#Ts;#sd;#id;constructor(e){super(e),this.#Ts=e.performanceAgent(),this.#sd=new Map([["TaskDuration","CumulativeTime"],["ScriptDuration","CumulativeTime"],["LayoutDuration","CumulativeTime"],["RecalcStyleDuration","CumulativeTime"],["LayoutCount","CumulativeCount"],["RecalcStyleCount","CumulativeCount"]]),this.#id=new Map}enable(){return this.#Ts.invoke_enable({})}disable(){return this.#Ts.invoke_disable()}async requestMetrics(){const e=await this.#Ts.invoke_getMetrics()||[],n=new Map,r=performance.now();for(const s of e.metrics){let e,i=this.#id.get(s.name);switch(i||(i={lastValue:void 0,lastTimestamp:void 0},this.#id.set(s.name,i)),this.#sd.get(s.name)){case"CumulativeTime":e=i.lastTimestamp&&i.lastValue?t.NumberUtilities.clamp(1e3*(s.value-i.lastValue)/(r-i.lastTimestamp),0,1):0,i.lastValue=s.value,i.lastTimestamp=r;break;case"CumulativeCount":e=i.lastTimestamp&&i.lastValue?Math.max(0,1e3*(s.value-i.lastValue)/(r-i.lastTimestamp)):0,i.lastValue=s.value,i.lastTimestamp=r;break;default:e=s.value}n.set(s.name,e)}return{metrics:n,timestamp:r}}}c.register(Wi,{capabilities:z.DOM,autostart:!1});var Vi,Gi=Object.freeze({__proto__:null,PerformanceMetricsModel:Wi});class Ki extends c{agent;loaderIds=[];targetJustAttached=!0;lastPrimaryPageModel=null;documents=new Map;getFeatureFlagsPromise;constructor(e){super(e),e.registerPreloadDispatcher(new $i(this)),this.agent=e.preloadAgent(),this.agent.invoke_enable(),this.getFeatureFlagsPromise=this.getFeatureFlags();const t=e.targetInfo();void 0!==t&&"prerender"===t.subtype&&(this.lastPrimaryPageModel=K.instance().primaryPageTarget()?.model(Ki)||null),K.instance().addModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this)}dispose(){super.dispose(),K.instance().removeModelListener(jn,_n.PrimaryPageChanged,this.onPrimaryPageChanged,this),this.agent.invoke_disable()}ensureDocumentPreloadingData(e){void 0===this.documents.get(e)&&this.documents.set(e,new Qi)}currentLoaderId(){if(this.targetJustAttached)return null;if(0===this.loaderIds.length)throw new Error("unreachable");return this.loaderIds[this.loaderIds.length-1]}currentDocument(){const e=this.currentLoaderId();return null===e?null:this.documents.get(e)||null}getRuleSetById(e){return this.currentDocument()?.ruleSets.getById(e)||null}getAllRuleSets(){return this.currentDocument()?.ruleSets.getAll()||[]}getPreloadingAttemptById(e){const t=this.currentDocument();return null===t?null:t.preloadingAttempts.getById(e,t.sources)||null}getPreloadingAttempts(e){const t=this.currentDocument();return null===t?[]:t.preloadingAttempts.getAll(e,t.sources)}getPreloadingAttemptsOfPreviousPage(){if(this.loaderIds.length<=1)return[];const e=this.documents.get(this.loaderIds[this.loaderIds.length-2]);return void 0===e?[]:e.preloadingAttempts.getAll(null,e.sources)}onPrimaryPageChanged(e){const{frame:t,type:n}=e.data;if(null===this.lastPrimaryPageModel&&"Activation"===n)return;if(null!==this.lastPrimaryPageModel&&"Activation"!==n)return;if(null!==this.lastPrimaryPageModel&&"Activation"===n){this.loaderIds=this.lastPrimaryPageModel.loaderIds;for(const[e,t]of this.lastPrimaryPageModel.documents.entries())this.ensureDocumentPreloadingData(e),this.documents.get(e)?.mergePrevious(t)}this.lastPrimaryPageModel=null;const r=t.loaderId;this.loaderIds.push(r),this.loaderIds=this.loaderIds.slice(-2),this.ensureDocumentPreloadingData(r);for(const e of this.documents.keys())this.loaderIds.includes(e)||this.documents.delete(e);this.dispatchEventToListeners(Vi.ModelUpdated)}onRuleSetUpdated(e){const t=e.ruleSet,n=t.loaderId;null===this.currentLoaderId()&&(this.loaderIds=[n],this.targetJustAttached=!1),this.ensureDocumentPreloadingData(n),this.documents.get(n)?.ruleSets.upsert(t),this.dispatchEventToListeners(Vi.ModelUpdated)}onRuleSetRemoved(e){const t=e.id;for(const e of this.documents.values())e.ruleSets.delete(t);this.dispatchEventToListeners(Vi.ModelUpdated)}onPreloadingAttemptSourcesUpdated(e){const t=e.loaderId;this.ensureDocumentPreloadingData(t);const n=this.documents.get(t);void 0!==n&&(n.sources.update(e.preloadingAttemptSources),n.preloadingAttempts.maybeRegisterNotTriggered(n.sources),this.dispatchEventToListeners(Vi.ModelUpdated))}onPrefetchStatusUpdated(e){const t=e.key.loaderId;this.ensureDocumentPreloadingData(t);const n={action:"Prefetch",key:e.key,status:Ji(e.status),prefetchStatus:e.prefetchStatus||null};this.documents.get(t)?.preloadingAttempts.upsert(n),this.dispatchEventToListeners(Vi.ModelUpdated)}onPrerenderStatusUpdated(e){const t=e.key.loaderId;this.ensureDocumentPreloadingData(t);const n={action:"Prerender",key:e.key,status:Ji(e.status),prerenderStatus:e.prerenderStatus||null};this.documents.get(t)?.preloadingAttempts.upsert(n),this.dispatchEventToListeners(Vi.ModelUpdated)}async getFeatureFlags(){const e=this.target().systemInfo().invoke_getFeatureState({featureState:"PreloadingHoldback"}),t=this.target().systemInfo().invoke_getFeatureState({featureState:"PrerenderHoldback"});return{preloadingHoldback:(await e).featureEnabled,prerender2Holdback:(await t).featureEnabled}}async onPreloadEnabledStateUpdated(e){const t=await this.getFeatureFlagsPromise,n={featureFlagPreloadingHoldback:t.preloadingHoldback,featureFlagPrerender2Holdback:t.prerender2Holdback,...e};this.dispatchEventToListeners(Vi.WarningsUpdated,n)}}c.register(Ki,{capabilities:z.DOM,autostart:!1}),function(e){e.ModelUpdated="ModelUpdated",e.WarningsUpdated="WarningsUpdated"}(Vi||(Vi={}));class $i{model;constructor(e){this.model=e}ruleSetUpdated(e){this.model.onRuleSetUpdated(e)}ruleSetRemoved(e){this.model.onRuleSetRemoved(e)}preloadingAttemptSourcesUpdated(e){this.model.onPreloadingAttemptSourcesUpdated(e)}prefetchStatusUpdated(e){this.model.onPrefetchStatusUpdated(e)}prerenderAttemptCompleted(e){}prerenderStatusUpdated(e){this.model.onPrerenderStatusUpdated(e)}preloadEnabledStateUpdated(e){this.model.onPreloadEnabledStateUpdated(e)}}class Qi{ruleSets=new Xi;preloadingAttempts=new Zi;sources=new ea;mergePrevious(e){if(!this.ruleSets.isEmpty()||!this.sources.isEmpty())throw new Error("unreachable");this.ruleSets=e.ruleSets,this.preloadingAttempts.mergePrevious(e.preloadingAttempts),this.sources=e.sources}}class Xi{map=new Map;isEmpty(){return 0===this.map.size}getById(e){return this.map.get(e)||null}getAll(){return Array.from(this.map.entries()).map((([e,t])=>({id:e,value:t})))}upsert(e){this.map.set(e.id,e)}delete(e){this.map.delete(e)}}function Ji(e){switch(e){case"Pending":return"Pending";case"Running":return"Running";case"Ready":return"Ready";case"Success":return"Success";case"Failure":return"Failure";case"NotSupported":return"NotSupported"}throw new Error("unreachable")}function Yi(e){let t,n;switch(e.action){case"Prefetch":t="Prefetch";break;case"Prerender":t="Prerender"}switch(e.targetHint){case void 0:n="undefined";break;case"Blank":n="Blank";break;case"Self":n="Self"}return`${e.loaderId}:${t}:${e.url}:${n}`}class Zi{map=new Map;enrich(e,t){let n=[],r=[];return null!==t&&(n=t.ruleSetIds,r=t.nodeIds),{...e,ruleSetIds:n,nodeIds:r}}getById(e,t){const n=this.map.get(e)||null;return null===n?null:this.enrich(n,t.getById(e))}getAll(e,t){return[...this.map.entries()].map((([e,n])=>({id:e,value:this.enrich(n,t.getById(e))}))).filter((({value:t})=>!e||t.ruleSetIds.includes(e)))}upsert(e){const t=Yi(e.key);this.map.set(t,e)}maybeRegisterNotTriggered(e){for(const[t,{key:n}]of e.entries()){if(void 0!==this.map.get(t))continue;let e;switch(n.action){case"Prefetch":e={action:"Prefetch",key:n,status:"NotTriggered",prefetchStatus:null};break;case"Prerender":e={action:"Prerender",key:n,status:"NotTriggered",prerenderStatus:null}}this.map.set(t,e)}}mergePrevious(e){for(const[t,n]of this.map.entries())e.map.set(t,n);this.map=e.map}}class ea{map=new Map;entries(){return this.map.entries()}isEmpty(){return 0===this.map.size}getById(e){return this.map.get(e)||null}update(e){this.map=new Map(e.map((e=>[Yi(e.key),e])))}}var ta=Object.freeze({__proto__:null,PreloadingModel:Ki,get Events(){return Vi}});class na extends c{#Ts;#ad;#od;constructor(e){super(e),this.#Ts=e.pageAgent(),this.#ad=null,this.#od=null,e.registerPageDispatcher(this)}startScreencast(e,t,n,r,s,i,a){this.#ad=i,this.#od=a,this.#Ts.invoke_startScreencast({format:e,quality:t,maxWidth:n,maxHeight:r,everyNthFrame:s})}stopScreencast(){this.#ad=null,this.#od=null,this.#Ts.invoke_stopScreencast()}async captureScreenshot(e,t,n,r){const s={format:e,quality:t,fromSurface:!0};switch(n){case"fromClip":s.captureBeyondViewport=!0,s.clip=r;break;case"fullpage":s.captureBeyondViewport=!0;break;case"fromViewport":s.captureBeyondViewport=!1;break;default:throw new Error("Unexpected or unspecified screnshotMode")}await vn.muteHighlight();const i=await this.#Ts.invoke_captureScreenshot(s);return await vn.unmuteHighlight(),i.data}async fetchLayoutMetrics(){const e=await this.#Ts.invoke_getLayoutMetrics();return e.getError()?null:{viewportX:e.cssVisualViewport.pageX,viewportY:e.cssVisualViewport.pageY,viewportScale:e.cssVisualViewport.scale,contentWidth:e.cssContentSize.width,contentHeight:e.cssContentSize.height}}screencastFrame({data:e,metadata:t,sessionId:n}){this.#Ts.invoke_screencastFrameAck({sessionId:n}),this.#ad&&this.#ad.call(null,e,t)}screencastVisibilityChanged({visible:e}){this.#od&&this.#od.call(null,e)}backForwardCacheNotUsed(e){}domContentEventFired(e){}loadEventFired(e){}lifecycleEvent(e){}navigatedWithinDocument(e){}frameAttached(e){}frameNavigated(e){}documentOpened(e){}frameDetached(e){}frameStartedLoading(e){}frameStoppedLoading(e){}frameRequestedNavigation(e){}frameScheduledNavigation(e){}frameClearedScheduledNavigation(e){}frameResized(){}javascriptDialogOpening(e){}javascriptDialogClosed(e){}interstitialShown(){}interstitialHidden(){}windowOpen(e){}fileChooserOpened(e){}compilationCacheProduced(e){}downloadWillBegin(e){}downloadProgress(){}prerenderAttemptCompleted(e){}prefetchStatusUpdated(e){}prerenderStatusUpdated(e){}}c.register(na,{capabilities:z.ScreenCapture,autostart:!1});var ra=Object.freeze({__proto__:null,ScreenCaptureModel:na});class sa extends c{enabled=!1;storageAgent;storageKeyManager;bucketsById=new Map;trackedStorageKeys=new Set;constructor(e){super(e),e.registerStorageDispatcher(this),this.storageAgent=e.storageAgent(),this.storageKeyManager=e.model(qn)}getBuckets(){return new Set(this.bucketsById.values())}getBucketsForStorageKey(e){const t=[...this.bucketsById.values()];return new Set(t.filter((({bucket:t})=>t.storageKey===e)))}getDefaultBucketForStorageKey(e){return[...this.bucketsById.values()].find((({bucket:t})=>t.storageKey===e&&void 0===t.name))??null}getBucketById(e){return this.bucketsById.get(e)??null}getBucketByName(e,t){if(!t)return this.getDefaultBucketForStorageKey(e);return[...this.bucketsById.values()].find((({bucket:n})=>n.storageKey===e&&n.name===t))??null}deleteBucket(e){this.storageAgent.invoke_deleteStorageBucket({bucket:e})}enable(){if(!this.enabled){if(this.storageKeyManager){this.storageKeyManager.addEventListener(Un.StorageKeyAdded,this.storageKeyAdded,this),this.storageKeyManager.addEventListener(Un.StorageKeyRemoved,this.storageKeyRemoved,this);for(const e of this.storageKeyManager.storageKeys())this.addStorageKey(e)}this.enabled=!0}}storageKeyAdded(e){this.addStorageKey(e.data)}storageKeyRemoved(e){this.removeStorageKey(e.data)}addStorageKey(e){if(this.trackedStorageKeys.has(e))throw new Error("Can't call addStorageKey for a storage key if it has already been added.");this.trackedStorageKeys.add(e),this.storageAgent.invoke_setStorageBucketTracking({storageKey:e,enable:!0})}removeStorageKey(e){if(!this.trackedStorageKeys.has(e))throw new Error("Can't call removeStorageKey for a storage key if it hasn't already been added.");const t=this.getBucketsForStorageKey(e);for(const e of t)this.bucketRemoved(e);this.trackedStorageKeys.delete(e),this.storageAgent.invoke_setStorageBucketTracking({storageKey:e,enable:!1})}bucketAdded(e){this.bucketsById.set(e.id,e),this.dispatchEventToListeners("BucketAdded",{model:this,bucketInfo:e})}bucketRemoved(e){this.bucketsById.delete(e.id),this.dispatchEventToListeners("BucketRemoved",{model:this,bucketInfo:e})}bucketChanged(e){this.dispatchEventToListeners("BucketChanged",{model:this,bucketInfo:e})}bucketInfosAreEqual(e,t){return e.bucket.storageKey===t.bucket.storageKey&&e.id===t.id&&e.bucket.name===t.bucket.name&&e.expiration===t.expiration&&e.quota===t.quota&&e.persistent===t.persistent&&e.durability===t.durability}storageBucketCreatedOrUpdated({bucketInfo:e}){const t=this.getBucketById(e.id);t?this.bucketInfosAreEqual(t,e)||this.bucketChanged(e):this.bucketAdded(e)}storageBucketDeleted({bucketId:e}){const t=this.getBucketById(e);if(!t)throw new Error(`Received an event that Storage Bucket '${e}' was deleted, but it wasn't in the StorageBucketsModel.`);this.bucketRemoved(t)}interestGroupAccessed(e){}indexedDBListUpdated(e){}indexedDBContentUpdated(e){}cacheStorageListUpdated(e){}cacheStorageContentUpdated(e){}sharedStorageAccessed(e){}}c.register(sa,{capabilities:z.Storage,autostart:!1});var ia=Object.freeze({__proto__:null,StorageBucketsModel:sa});const aa={serviceworkercacheagentError:"`ServiceWorkerCacheAgent` error deleting cache entry {PH1} in cache: {PH2}"},oa=s.i18n.registerUIStrings("core/sdk/ServiceWorkerCacheModel.ts",aa),la=s.i18n.getLocalizedString.bind(void 0,oa);class da extends c{cacheAgent;#ld;#dd;#cd=new Map;#hd=new Set;#ud=new Set;#gd=new e.Throttler.Throttler(2e3);#ma=!1;#pd=!1;constructor(e){super(e),e.registerStorageDispatcher(this),this.cacheAgent=e.cacheStorageAgent(),this.#ld=e.storageAgent(),this.#dd=e.model(sa)}enable(){if(!this.#ma){this.#dd.addEventListener("BucketAdded",this.storageBucketAdded,this),this.#dd.addEventListener("BucketRemoved",this.storageBucketRemoved,this);for(const e of this.#dd.getBuckets())this.addStorageBucket(e.bucket);this.#ma=!0}}clearForStorageKey(e){for(const[t,n]of this.#cd.entries())n.storageKey===e&&(this.#cd.delete(t),this.cacheRemoved(n));for(const t of this.#dd.getBucketsForStorageKey(e))this.loadCacheNames(t.bucket)}refreshCacheNames(){for(const e of this.#cd.values())this.cacheRemoved(e);this.#cd.clear();const e=this.#dd.getBuckets();for(const t of e)this.loadCacheNames(t.bucket)}async deleteCache(e){const t=await this.cacheAgent.invoke_deleteCache({cacheId:e.cacheId});t.getError()?console.error(`ServiceWorkerCacheAgent error deleting cache ${e.toString()}: ${t.getError()}`):(this.#cd.delete(e.cacheId),this.cacheRemoved(e))}async deleteCacheEntry(t,n){const r=await this.cacheAgent.invoke_deleteEntry({cacheId:t.cacheId,request:n});r.getError()&&e.Console.Console.instance().error(la(aa.serviceworkercacheagentError,{PH1:t.toString(),PH2:String(r.getError())}))}loadCacheData(e,t,n,r,s){this.requestEntries(e,t,n,r,s)}loadAllCacheData(e,t,n){this.requestAllEntries(e,t,n)}caches(){const e=new Array;for(const t of this.#cd.values())e.push(t);return e}dispose(){for(const e of this.#cd.values())this.cacheRemoved(e);this.#cd.clear(),this.#ma&&(this.#dd.removeEventListener("BucketAdded",this.storageBucketAdded,this),this.#dd.removeEventListener("BucketRemoved",this.storageBucketRemoved,this))}addStorageBucket(e){this.loadCacheNames(e),this.#hd.has(e.storageKey)||(this.#hd.add(e.storageKey),this.#ld.invoke_trackCacheStorageForStorageKey({storageKey:e.storageKey}))}removeStorageBucket(e){let t=0;for(const[n,r]of this.#cd.entries())e.storageKey===r.storageKey&&t++,r.inBucket(e)&&(t--,this.#cd.delete(n),this.cacheRemoved(r));0===t&&(this.#hd.delete(e.storageKey),this.#ld.invoke_untrackCacheStorageForStorageKey({storageKey:e.storageKey}))}async loadCacheNames(e){const t=await this.cacheAgent.invoke_requestCacheNames({storageBucket:e});t.getError()||this.updateCacheNames(e,t.caches)}updateCacheNames(e,t){const n=new Set,r=new Map,s=new Map;for(const e of t){const t=e.storageBucket??this.#dd.getDefaultBucketForStorageKey(e.storageKey)?.bucket;if(!t)continue;const s=new ha(this,t,e.cacheName,e.cacheId);n.add(s.cacheId),this.#cd.has(s.cacheId)||(r.set(s.cacheId,s),this.#cd.set(s.cacheId,s))}this.#cd.forEach((function(t){t.inBucket(e)&&!n.has(t.cacheId)&&(s.set(t.cacheId,t),this.#cd.delete(t.cacheId))}),this),r.forEach(this.cacheAdded,this),s.forEach(this.cacheRemoved,this)}storageBucketAdded({data:{bucketInfo:{bucket:e}}}){this.addStorageBucket(e)}storageBucketRemoved({data:{bucketInfo:{bucket:e}}}){this.removeStorageBucket(e)}cacheAdded(e){this.dispatchEventToListeners(ca.CacheAdded,{model:this,cache:e})}cacheRemoved(e){this.dispatchEventToListeners(ca.CacheRemoved,{model:this,cache:e})}async requestEntries(e,t,n,r,s){const i=await this.cacheAgent.invoke_requestEntries({cacheId:e.cacheId,skipCount:t,pageSize:n,pathFilter:r});i.getError()?console.error("ServiceWorkerCacheAgent error while requesting entries: ",i.getError()):s(i.cacheDataEntries,i.returnCount)}async requestAllEntries(e,t,n){const r=await this.cacheAgent.invoke_requestEntries({cacheId:e.cacheId,pathFilter:t});r.getError()?console.error("ServiceWorkerCacheAgent error while requesting entries: ",r.getError()):n(r.cacheDataEntries,r.returnCount)}cacheStorageListUpdated({bucketId:e}){const t=this.#dd.getBucketById(e)?.bucket;t&&(this.#ud.add(t),this.#gd.schedule((()=>{const e=Array.from(this.#ud,(e=>this.loadCacheNames(e)));return this.#ud.clear(),Promise.all(e)}),this.#pd))}cacheStorageContentUpdated({bucketId:e,cacheName:t}){const n=this.#dd.getBucketById(e)?.bucket;n&&this.dispatchEventToListeners(ca.CacheStorageContentUpdated,{storageBucket:n,cacheName:t})}indexedDBListUpdated(e){}indexedDBContentUpdated(e){}interestGroupAccessed(e){}sharedStorageAccessed(e){}storageBucketCreatedOrUpdated(e){}storageBucketDeleted(e){}setThrottlerSchedulesAsSoonAsPossibleForTest(){this.#pd=!0}}var ca;!function(e){e.CacheAdded="CacheAdded",e.CacheRemoved="CacheRemoved",e.CacheStorageContentUpdated="CacheStorageContentUpdated"}(ca||(ca={}));class ha{#$r;storageKey;storageBucket;cacheName;cacheId;constructor(e,t,n,r){this.#$r=e,this.storageBucket=t,this.storageKey=t.storageKey,this.cacheName=n,this.cacheId=r}inBucket(e){return this.storageKey===e.storageKey&&this.storageBucket.name===e.name}equals(e){return this.cacheId===e.cacheId}toString(){return this.storageKey+this.cacheName}async requestCachedResponse(e,t){const n=await this.#$r.cacheAgent.invoke_requestCachedResponse({cacheId:this.cacheId,requestURL:e,requestHeaders:t});return n.getError()?null:n.response}}c.register(da,{capabilities:z.Storage,autostart:!1});var ua=Object.freeze({__proto__:null,ServiceWorkerCacheModel:da,get Events(){return ca},Cache:ha});const ga={running:"running",starting:"starting",stopped:"stopped",stopping:"stopping",activated:"activated",activating:"activating",installed:"installed",installing:"installing",new:"new",redundant:"redundant",sSS:"{PH1} #{PH2} ({PH3})"},pa=s.i18n.registerUIStrings("core/sdk/ServiceWorkerManager.ts",ga),ma=s.i18n.getLocalizedString.bind(void 0,pa),fa=s.i18n.getLazilyComputedLocalizedString.bind(void 0,pa);class ba extends c{#Ts;#md;#ma;#fd;serviceWorkerNetworkRequestsPanelStatus;constructor(t){super(t),t.registerServiceWorkerDispatcher(new va(this)),this.#Ts=t.serviceWorkerAgent(),this.#md=new Map,this.#ma=!1,this.enable(),this.#fd=e.Settings.Settings.instance().createSetting("serviceWorkerUpdateOnReload",!1),this.#fd.get()&&this.forceUpdateSettingChanged(),this.#fd.addChangeListener(this.forceUpdateSettingChanged,this),new wa(t,this),this.serviceWorkerNetworkRequestsPanelStatus={isOpen:!1,openedAt:0}}async enable(){this.#ma||(this.#ma=!0,await this.#Ts.invoke_enable())}async disable(){this.#ma&&(this.#ma=!1,this.#md.clear(),await this.#Ts.invoke_enable())}registrations(){return this.#md}hasRegistrationForURLs(e){for(const t of this.#md.values())if(e.filter((e=>e&&e.startsWith(t.scopeURL))).length===e.length)return!0;return!1}findVersion(e){for(const t of this.registrations().values()){const n=t.versions.get(e);if(n)return n}return null}deleteRegistration(e){const t=this.#md.get(e);if(t){if(t.isRedundant())return this.#md.delete(e),void this.dispatchEventToListeners(ya.RegistrationDeleted,t);t.deleting=!0;for(const e of t.versions.values())this.stopWorker(e.id);this.unregister(t.scopeURL)}}async updateRegistration(e){const t=this.#md.get(e);t&&await this.#Ts.invoke_updateRegistration({scopeURL:t.scopeURL})}async deliverPushMessage(t,n){const r=this.#md.get(t);if(!r)return;const s=e.ParsedURL.ParsedURL.extractOrigin(r.scopeURL);await this.#Ts.invoke_deliverPushMessage({origin:s,registrationId:t,data:n})}async dispatchSyncEvent(t,n,r){const s=this.#md.get(t);if(!s)return;const i=e.ParsedURL.ParsedURL.extractOrigin(s.scopeURL);await this.#Ts.invoke_dispatchSyncEvent({origin:i,registrationId:t,tag:n,lastChance:r})}async dispatchPeriodicSyncEvent(t,n){const r=this.#md.get(t);if(!r)return;const s=e.ParsedURL.ParsedURL.extractOrigin(r.scopeURL);await this.#Ts.invoke_dispatchPeriodicSyncEvent({origin:s,registrationId:t,tag:n})}async unregister(e){await this.#Ts.invoke_unregister({scopeURL:e})}async startWorker(e){await this.#Ts.invoke_startWorker({scopeURL:e})}async skipWaiting(e){await this.#Ts.invoke_skipWaiting({scopeURL:e})}async stopWorker(e){await this.#Ts.invoke_stopWorker({versionId:e})}async inspectWorker(e){await this.#Ts.invoke_inspectWorker({versionId:e})}workerRegistrationUpdated(e){for(const t of e){let e=this.#md.get(t.registrationId);e?(e.update(t),e.shouldBeRemoved()?(this.#md.delete(e.id),this.dispatchEventToListeners(ya.RegistrationDeleted,e)):this.dispatchEventToListeners(ya.RegistrationUpdated,e)):(e=new Sa(t),this.#md.set(t.registrationId,e),this.dispatchEventToListeners(ya.RegistrationUpdated,e))}}workerVersionUpdated(e){const t=new Set;for(const n of e){const e=this.#md.get(n.registrationId);e&&(e.updateVersion(n),t.add(e))}for(const e of t)e.shouldBeRemoved()?(this.#md.delete(e.id),this.dispatchEventToListeners(ya.RegistrationDeleted,e)):this.dispatchEventToListeners(ya.RegistrationUpdated,e)}workerErrorReported(e){const t=this.#md.get(e.registrationId);t&&(t.errors.push(e),this.dispatchEventToListeners(ya.RegistrationErrorAdded,{registration:t,error:e}))}forceUpdateOnReloadSetting(){return this.#fd}forceUpdateSettingChanged(){const e=this.#fd.get();this.#Ts.invoke_setForceUpdateOnPageLoad({forceUpdateOnPageLoad:e})}}var ya;!function(e){e.RegistrationUpdated="RegistrationUpdated",e.RegistrationErrorAdded="RegistrationErrorAdded",e.RegistrationDeleted="RegistrationDeleted"}(ya||(ya={}));class va{#$;constructor(e){this.#$=e}workerRegistrationUpdated({registrations:e}){this.#$.workerRegistrationUpdated(e)}workerVersionUpdated({versions:e}){this.#$.workerVersionUpdated(e)}workerErrorReported({errorMessage:e}){this.#$.workerErrorReported(e)}}class Ia{runningStatus;status;last_updated_timestamp;previousState;constructor(e,t,n,r){this.runningStatus=e,this.status=t,this.last_updated_timestamp=r,this.previousState=n}}class ka{id;scriptURL;parsedURL;securityOrigin;scriptLastModified;scriptResponseTime;controlledClients;targetId;currentState;registration;constructor(e,t){this.registration=e,this.update(t)}update(t){this.id=t.versionId,this.scriptURL=t.scriptURL;const n=new e.ParsedURL.ParsedURL(t.scriptURL);this.securityOrigin=n.securityOrigin(),this.currentState=new Ia(t.runningStatus,t.status,this.currentState,Date.now()),this.scriptLastModified=t.scriptLastModified,this.scriptResponseTime=t.scriptResponseTime,t.controlledClients?this.controlledClients=t.controlledClients.slice():this.controlledClients=[],this.targetId=t.targetId||null}isStartable(){return!this.registration.isDeleted&&this.isActivated()&&this.isStopped()}isStoppedAndRedundant(){return"stopped"===this.runningStatus&&"redundant"===this.status}isStopped(){return"stopped"===this.runningStatus}isStarting(){return"starting"===this.runningStatus}isRunning(){return"running"===this.runningStatus}isStopping(){return"stopping"===this.runningStatus}isNew(){return"new"===this.status}isInstalling(){return"installing"===this.status}isInstalled(){return"installed"===this.status}isActivating(){return"activating"===this.status}isActivated(){return"activated"===this.status}isRedundant(){return"redundant"===this.status}get status(){return this.currentState.status}get runningStatus(){return this.currentState.runningStatus}mode(){return this.isNew()||this.isInstalling()?ka.Modes.Installing:this.isInstalled()?ka.Modes.Waiting:this.isActivating()||this.isActivated()?ka.Modes.Active:ka.Modes.Redundant}}!function(e){let t;e.RunningStatus={running:fa(ga.running),starting:fa(ga.starting),stopped:fa(ga.stopped),stopping:fa(ga.stopping)},e.Status={activated:fa(ga.activated),activating:fa(ga.activating),installed:fa(ga.installed),installing:fa(ga.installing),new:fa(ga.new),redundant:fa(ga.redundant)},function(e){e.Installing="installing",e.Waiting="waiting",e.Active="active",e.Redundant="redundant"}(t=e.Modes||(e.Modes={}))}(ka||(ka={}));class Sa{#bd;id;scopeURL;securityOrigin;isDeleted;versions;deleting;errors;constructor(e){this.update(e),this.versions=new Map,this.deleting=!1,this.errors=[]}update(t){this.#bd=Symbol("fingerprint"),this.id=t.registrationId,this.scopeURL=t.scopeURL;const n=new e.ParsedURL.ParsedURL(t.scopeURL);this.securityOrigin=n.securityOrigin(),this.isDeleted=t.isDeleted}fingerprint(){return this.#bd}versionsByMode(){const e=new Map;for(const t of this.versions.values())e.set(t.mode(),t);return e}updateVersion(e){this.#bd=Symbol("fingerprint");let t=this.versions.get(e.versionId);return t?(t.update(e),t):(t=new ka(this,e),this.versions.set(e.versionId,t),t)}isRedundant(){for(const e of this.versions.values())if(!e.isStoppedAndRedundant())return!1;return!0}shouldBeRemoved(){return this.isRedundant()&&(!this.errors.length||this.deleting)}canBeRemoved(){return this.isDeleted||this.deleting}clearErrors(){this.#bd=Symbol("fingerprint"),this.errors=[]}}class wa{#h;#yd;#vd;constructor(e,t){this.#h=e,this.#yd=t,this.#vd=new Map,t.addEventListener(ya.RegistrationUpdated,this.registrationsUpdated,this),t.addEventListener(ya.RegistrationDeleted,this.registrationsUpdated,this),K.instance().addModelListener(Cr,Rr.ExecutionContextCreated,this.executionContextCreated,this)}registrationsUpdated(){this.#vd.clear();const e=this.#yd.registrations().values();for(const t of e)for(const e of t.versions.values())e.targetId&&this.#vd.set(e.targetId,e);this.updateAllContextLabels()}executionContextCreated(e){const t=e.data,n=this.serviceWorkerTargetId(t.target());n&&this.updateContextLabel(t,this.#vd.get(n)||null)}serviceWorkerTargetId(e){return e.parentTarget()!==this.#h||e.type()!==_.ServiceWorker?null:e.id()}updateAllContextLabels(){for(const e of K.instance().targets()){const t=this.serviceWorkerTargetId(e);if(!t)continue;const n=this.#vd.get(t)||null,r=e.model(Cr),s=r?r.executionContexts():[];for(const e of s)this.updateContextLabel(e,n)}}updateContextLabel(t,n){if(!n)return void t.setLabel("");const r=e.ParsedURL.ParsedURL.fromString(t.origin),s=r?r.lastPathComponentWithFragment():t.name,i=ka.Status[n.status];t.setLabel(ma(ga.sSS,{PH1:s,PH2:n.id,PH3:i()}))}}c.register(ba,{capabilities:z.ServiceWorker,autostart:!0});var Ca=Object.freeze({__proto__:null,ServiceWorkerManager:ba,get Events(){return ya},ServiceWorkerVersionState:Ia,get ServiceWorkerVersion(){return ka},ServiceWorkerRegistration:Sa});const Ta=new Map,Ra=new Map;async function xa(e,t){const n=Ta.get(e)?.get(t);if(void 0!==n)return n;const r=K.instance().primaryPageTarget()?.model(Pn);if(!r)return null;const s=(await r.pushNodesByBackendIdsToFrontend(new Set([t])))?.get(t)||null,i=Ta.get(e)||new Map;return i.set(t,s),Ta.set(e,i),s}const Ma=new Map,Pa=new Map;var La=Object.freeze({__proto__:null,_TEST_clearCache:function(){Ta.clear(),Ra.clear(),Ma.clear(),Pa.clear()},domNodeForBackendNodeID:xa,domNodesForMultipleBackendNodeIds:async function(e,t){const n=Ra.get(e)?.get(t);if(n)return n;const r=K.instance().primaryPageTarget()?.model(Pn);if(!r)return new Map;const s=await r.pushNodesByBackendIdsToFrontend(t)||new Map,i=Ra.get(e)||new Map;return i.set(t,s),Ra.set(e,i),s},sourcesForLayoutShift:async function(e,t){const n=Ma.get(e)?.get(t);if(n)return n;const r=t.args.data?.impacted_nodes;if(!r)return[];const s=[];await Promise.all(r.map((async t=>{const n=await xa(e,t.node_id);n&&s.push({previousRect:new DOMRect(t.old_rect[0],t.old_rect[1],t.old_rect[2],t.old_rect[3]),currentRect:new DOMRect(t.new_rect[0],t.new_rect[1],t.new_rect[2],t.new_rect[3]),node:n})})));const i=Ma.get(e)||new Map;return i.set(t,s),Ma.set(e,i),s},normalizedImpactedNodesForLayoutShift:async function(e,t){const n=Pa.get(e)?.get(t);if(n)return n;const r=t.args?.data?.impacted_nodes;if(!r)return[];let s=null;const i=K.instance().primaryPageTarget(),a=await(i?.runtimeAgent().invoke_evaluate({expression:"window.devicePixelRatio"}));if("number"===a?.result.type&&(s=a?.result.value??null),!s)return r;const o=[];for(const e of r){const t={...e};for(let n=0;n{setTimeout((()=>e(void 0)),1e3)}))]):void 0,n=Ts.instance().cpuThrottlingRate(),r=ue.instance().networkConditions(),s="function"==typeof r.title?r.title():r.title;return{source:"DevTools",startTime:e?new Date(e).toJSON():void 0,cpuThrottling:n,networkThrottling:s,hardwareConcurrency:t}}catch{return}}});class Ea extends c{#Id;#kd;#Sd;#wd;#Cd;constructor(e){super(e),this.#Id=e.tracingAgent(),e.registerTracingDispatcher(new Aa(this)),this.#kd=null,this.#Sd=0,this.#wd=0}bufferUsage(e,t,n){this.#Sd=void 0===t?null:t,this.#kd&&this.#kd.tracingBufferUsage(e||n||0)}eventsCollected(e){this.#kd&&(this.#kd.traceEventsCollected(e),this.#wd+=e.length,this.#Sd?(this.#wd>this.#Sd&&(this.#wd=this.#Sd),this.#kd.eventsRetrievalProgress(this.#wd/this.#Sd)):this.#kd.eventsRetrievalProgress(0))}tracingComplete(){this.#Sd=0,this.#wd=0,this.#kd&&(this.#kd.tracingComplete(),this.#kd=null),this.#Cd=!1}async start(e,t,n){if(this.#kd)throw new Error("Tracing is already started");this.#kd=e;const r={bufferUsageReportingInterval:500,categories:t,options:n,transferMode:"ReportEvents"},s=await this.#Id.invoke_start(r);return s.getError()&&(this.#kd=null),s}stop(){if(!this.#kd)throw new Error("Tracing is not started");if(this.#Cd)throw new Error("Tracing is already being stopped");this.#Cd=!0,this.#Id.invoke_end()}}class Aa{#Td;constructor(e){this.#Td=e}bufferUsage({value:e,eventCount:t,percentFull:n}){this.#Td.bufferUsage(e,t,n)}dataCollected({value:e}){this.#Td.eventsCollected(e)}tracingComplete(){this.#Td.tracingComplete()}}c.register(Ea,{capabilities:z.Tracing,autostart:!1});var Oa=Object.freeze({__proto__:null,TracingManager:Ea});class Na extends c{#Ts;constructor(e){super(e),this.#Ts=e.webAuthnAgent(),e.registerWebAuthnDispatcher(new Fa(this))}setVirtualAuthEnvEnabled(e){return e?this.#Ts.invoke_enable({enableUI:!0}):this.#Ts.invoke_disable()}async addAuthenticator(e){return(await this.#Ts.invoke_addVirtualAuthenticator({options:e})).authenticatorId}async removeAuthenticator(e){await this.#Ts.invoke_removeVirtualAuthenticator({authenticatorId:e})}async setAutomaticPresenceSimulation(e,t){await this.#Ts.invoke_setAutomaticPresenceSimulation({authenticatorId:e,enabled:t})}async getCredentials(e){return(await this.#Ts.invoke_getCredentials({authenticatorId:e})).credentials}async removeCredential(e,t){await this.#Ts.invoke_removeCredential({authenticatorId:e,credentialId:t})}credentialAdded(e){this.dispatchEventToListeners("CredentialAdded",e)}credentialAsserted(e){this.dispatchEventToListeners("CredentialAsserted",e)}}class Fa{#$r;constructor(e){this.#$r=e}credentialAdded(e){this.#$r.credentialAdded(e)}credentialAsserted(e){this.#$r.credentialAsserted(e)}}c.register(Na,{capabilities:z.WebAuthn,autostart:!1});var Ba=Object.freeze({__proto__:null,WebAuthnModel:Na});export{Nr as AccessibilityModel,vs as CPUProfileDataModel,ss as CPUProfilerModel,Ms as CPUThrottlingManager,Qe as CSSContainerQuery,ze as CSSFontFace,Je as CSSLayer,wt as CSSMatchedStyles,tt as CSSMedia,E as CSSMetadata,hn as CSSModel,lt as CSSProperty,Fs as CSSPropertyParser,We as CSSQuery,yt as CSSRule,rt as CSSScope,ct as CSSStyleDeclaration,Mt as CSSStyleSheetHeader,it as CSSSupports,Br as CategorizedBreakpoint,Vr as ChildTargetManager,Jr as CompilerSourceMappingContentProvider,jr as Connections,ms as ConsoleModel,U as Cookie,bs as CookieModel,j as CookieParser,$s as DOMDebuggerModel,On as DOMModel,Ir as DebuggerModel,ws as EmulationModel,ni as EventBreakpointsModel,Ci as FilmStripModel,Ti as FrameAssociated,At as FrameManager,wr as HeapProfilerModel,Nt as IOModel,Ai as IsolateManager,Fi as IssuesModel,Bi as LayerTreeBase,as as LogModel,me as NetworkManager,Pe as NetworkRequest,gn as OverlayColorGenerator,Cn as OverlayModel,mn as OverlayPersistentHighlighter,Hi as PageLoad,zt as PageResourceLoader,ji as PaintProfiler,Gi as PerformanceMetricsModel,ta as PreloadingModel,N as ProfileTreeModel,qe as RemoteObject,Bn as Resource,Kn as ResourceTreeModel,Er as RuntimeModel,h as SDKModel,ra as ScreenCaptureModel,tr as Script,Hn as SecurityOriginManager,Ie as ServerTiming,ua as ServiceWorkerCacheModel,Ca as ServiceWorkerManager,Xt as SourceMap,Zt as SourceMapManager,ia as StorageBucketsModel,zn as StorageKeyManager,V as Target,Q as TargetManager,La as TraceSDKServices,Oa as TracingManager,Ii as TracingModel,Ba as WebAuthnModel}; From 451fffbb59ceafdb84d7345592db65689a03256e Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 26 Feb 2024 05:33:18 -0800 Subject: [PATCH 004/361] Use host-relative WebSocket URLs when launching new debugger Summary: Changelog: [Internal] Uses the capability introduced in https://github.com/facebookexperimental/rn-chrome-devtools-frontend/pull/4 to avoid repeating the dev server's host:port in the `ws` / `wss` parameter we pass to the Chrome DevTools frontend. This gives us more flexibility to handle port forwarding and redirects outside of `dev-middleware`. This is mostly useful in Meta's internal VS Code remoting setup, but this particular change should work equally well in open source. Reviewed By: huntie Differential Revision: D54107316 fbshipit-source-id: 68d4dbf4849ca431274bfb0dc8a4e05981bdd5b5 --- .../__tests__/getDevToolsFrontendUrl-test.js | 94 +++++++++++-------- .../src/middleware/openDebuggerMiddleware.js | 4 +- .../src/utils/getDevToolsFrontendUrl.js | 44 +++++++-- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/packages/dev-middleware/src/__tests__/getDevToolsFrontendUrl-test.js b/packages/dev-middleware/src/__tests__/getDevToolsFrontendUrl-test.js index 3d0818efc25760..a6fe45b710bf8a 100644 --- a/packages/dev-middleware/src/__tests__/getDevToolsFrontendUrl-test.js +++ b/packages/dev-middleware/src/__tests__/getDevToolsFrontendUrl-test.js @@ -14,16 +14,16 @@ import getDevToolsFrontendUrl from '../utils/getDevToolsFrontendUrl'; describe('getDevToolsFrontendUrl', () => { const webSocketDebuggerUrl = 'ws://localhost:8081/inspector/debug?device=1a9372c&page=-1'; + const devServerUrl = 'http://localhost:8081'; - describe('given an absolute devServerUrl', () => { - const devServerUrl = 'http://localhost:8081'; + const experiments = { + enableNetworkInspector: false, + enableNewDebugger: false, + enableOpenDebuggerRedirect: false, + }; - it('should return a valid url for all experiments off', async () => { - const experiments = { - enableNetworkInspector: false, - enableNewDebugger: false, - enableOpenDebuggerRedirect: false, - }; + describe('relative: false (default)', () => { + test('should return a valid url for all experiments off', async () => { const actual = getDevToolsFrontendUrl( experiments, webSocketDebuggerUrl, @@ -33,18 +33,13 @@ describe('getDevToolsFrontendUrl', () => { expect(url.host).toBe('localhost:8081'); expect(url.pathname).toBe('/debugger-frontend/rn_inspector.html'); expect(url.searchParams.get('ws')).toBe( - 'localhost:8081/inspector/debug?device=1a9372c&page=-1', + '/inspector/debug?device=1a9372c&page=-1', ); }); - it('should return a valid url for enableNetworkInspector experiment on', async () => { - const experiments = { - enableNetworkInspector: true, - enableNewDebugger: true, - enableOpenDebuggerRedirect: false, - }; + test('should return a valid url for enableNetworkInspector experiment on', async () => { const actual = getDevToolsFrontendUrl( - experiments, + {...experiments, enableNetworkInspector: true, enableNewDebugger: true}, webSocketDebuggerUrl, devServerUrl, ); @@ -53,14 +48,26 @@ describe('getDevToolsFrontendUrl', () => { expect(url.pathname).toBe('/debugger-frontend/rn_inspector.html'); expect(url.searchParams.get('unstable_enableNetworkPanel')).toBe('true'); expect(url.searchParams.get('ws')).toBe( - 'localhost:8081/inspector/debug?device=1a9372c&page=-1', + '/inspector/debug?device=1a9372c&page=-1', ); }); - }); - describe('given a relative devServerUrl', () => { - const relativeDevServerUrl = ''; + test('should return a full WS URL if on a different host than the dev server', () => { + const otherWebSocketDebuggerUrl = + 'ws://localhost:9000/inspector/debug?device=1a9372c&page=-1'; + const actual = getDevToolsFrontendUrl( + experiments, + otherWebSocketDebuggerUrl, + devServerUrl, + ); + const url = new URL(actual); + expect(url.searchParams.get('ws')).toBe( + 'localhost:9000/inspector/debug?device=1a9372c&page=-1', + ); + }); + }); + describe('relative: true', () => { function assertValidRelativeURL(relativeURL: string): URL { const anyBaseURL = new URL('https://www.example.com'); try { @@ -71,40 +78,53 @@ describe('getDevToolsFrontendUrl', () => { } } - it('should return a valid url for all experiments off', async () => { - const experiments = { - enableNetworkInspector: false, - enableNewDebugger: false, - enableOpenDebuggerRedirect: false, - }; + test('should return a valid url for all experiments off', async () => { const actual = getDevToolsFrontendUrl( experiments, webSocketDebuggerUrl, - relativeDevServerUrl, + devServerUrl, + { + relative: true, + }, ); const url = assertValidRelativeURL(actual); expect(url.pathname).toBe('/debugger-frontend/rn_inspector.html'); expect(url.searchParams.get('ws')).toBe( - 'localhost:8081/inspector/debug?device=1a9372c&page=-1', + '/inspector/debug?device=1a9372c&page=-1', ); }); - it('should return a valid url for enableNetworkInspector experiment on', async () => { - const experiments = { - enableNetworkInspector: true, - enableNewDebugger: true, - enableOpenDebuggerRedirect: false, - }; + test('should return a valid url for enableNetworkInspector experiment on', async () => { const actual = getDevToolsFrontendUrl( - experiments, + {...experiments, enableNetworkInspector: true, enableNewDebugger: true}, webSocketDebuggerUrl, - relativeDevServerUrl, + devServerUrl, + { + relative: true, + }, ); const url = assertValidRelativeURL(actual); expect(url.pathname).toBe('/debugger-frontend/rn_inspector.html'); expect(url.searchParams.get('unstable_enableNetworkPanel')).toBe('true'); expect(url.searchParams.get('ws')).toBe( - 'localhost:8081/inspector/debug?device=1a9372c&page=-1', + '/inspector/debug?device=1a9372c&page=-1', + ); + }); + + test('should return a full WS URL if on a different host than the dev server', () => { + const otherWebSocketDebuggerUrl = + 'ws://localhost:8082/inspector/debug?device=1a9372c&page=-1'; + const actual = getDevToolsFrontendUrl( + experiments, + otherWebSocketDebuggerUrl, + devServerUrl, + { + relative: true, + }, + ); + const url = assertValidRelativeURL(actual); + expect(url.searchParams.get('ws')).toBe( + 'localhost:8082/inspector/debug?device=1a9372c&page=-1', ); }); }); diff --git a/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js b/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js index 1f3b4d74358521..6b571f7aa026cd 100644 --- a/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js +++ b/packages/dev-middleware/src/middleware/openDebuggerMiddleware.js @@ -132,8 +132,8 @@ export default function openDebuggerMiddleware({ Location: getDevToolsFrontendUrl( experiments, target.webSocketDebuggerUrl, - // Use a relative URL. - '', + serverBaseUrl, + {relative: true}, ), }); res.end(); diff --git a/packages/dev-middleware/src/utils/getDevToolsFrontendUrl.js b/packages/dev-middleware/src/utils/getDevToolsFrontendUrl.js index 4623616292fea5..7dd33dfd9d08a3 100644 --- a/packages/dev-middleware/src/utils/getDevToolsFrontendUrl.js +++ b/packages/dev-middleware/src/utils/getDevToolsFrontendUrl.js @@ -18,16 +18,21 @@ export default function getDevToolsFrontendUrl( experiments: Experiments, webSocketDebuggerUrl: string, devServerUrl: string, + options?: $ReadOnly<{ + relative?: boolean, + }>, ): string { - const scheme = new URL(webSocketDebuggerUrl).protocol.slice(0, -1); - const webSocketUrlWithoutProtocol = webSocketDebuggerUrl.replace( - /^wss?:\/\//, - '', - ); - const appUrl = `${devServerUrl}/debugger-frontend/rn_inspector.html`; + const wsParam = getWsParam({ + webSocketDebuggerUrl, + devServerUrl, + }); + + const appUrl = + (options?.relative === true ? '' : devServerUrl) + + '/debugger-frontend/rn_inspector.html'; const searchParams = new URLSearchParams([ - [scheme, webSocketUrlWithoutProtocol], + [wsParam.key, wsParam.value], ['sources.hide_add_folder', 'true'], ]); if (experiments.enableNetworkInspector) { @@ -36,3 +41,28 @@ export default function getDevToolsFrontendUrl( return appUrl + '?' + searchParams.toString(); } + +function getWsParam({ + webSocketDebuggerUrl, + devServerUrl, +}: $ReadOnly<{ + webSocketDebuggerUrl: string, + devServerUrl: string, +}>): { + key: string, + value: string, +} { + const wsUrl = new URL(webSocketDebuggerUrl); + const serverHost = new URL(devServerUrl).host; + let value; + if (wsUrl.host === serverHost) { + // Use a path-absolute (host-relative) URL + // Depends on https://github.com/facebookexperimental/rn-chrome-devtools-frontend/pull/4 + value = wsUrl.pathname + wsUrl.search + wsUrl.hash; + } else { + // Standard URL format accepted by the DevTools frontend + value = wsUrl.host + wsUrl.pathname + wsUrl.search + wsUrl.hash; + } + const key = wsUrl.protocol.slice(0, -1); + return {key, value}; +} From f0363f5cf0645c59b928f6b94b75d5cd733cfb2e Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Mon, 26 Feb 2024 07:06:02 -0800 Subject: [PATCH 005/361] Enable varying feature flags in ReactInstanceIntegrationTest, use modern CDP registry by default (#43101) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43101 Extends `ReactInstanceIntegrationTest` to allow varying feature flags in tests, using gtest's parameterised tests. Exercise this in `ConsoleLogTest` to test against the modern CDP registry, for which we also needed to modify some initialisation logic to account for the fact that under the modern registry, the page is added by the host, rather than by Hermes `DecoratedRuntime`. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D53919148 fbshipit-source-id: 4eb87abf548f30b5483b819a2dadd444d1d5c80d --- .../jsinspector-modern/InspectorFlags.cpp | 4 + .../jsinspector-modern/InspectorFlags.h | 12 +- .../tests/ReactInstanceIntegrationTest.cpp | 144 +++++++++++++++--- .../tests/ReactInstanceIntegrationTest.h | 26 +++- 4 files changed, 161 insertions(+), 25 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp index b0e3b4fb17b549..4a2c9df723a6d5 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp @@ -37,6 +37,10 @@ bool InspectorFlags::getEnableCxxInspectorPackagerConnection() const { enableModernCDPRegistry_; } +void InspectorFlags::dangerouslyResetFlags() { + *this = InspectorFlags{}; +} + void InspectorFlags::assertFlagsMatchUpstream() const { if (inconsistentFlagsStateLogged_) { return; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h index 605fad31723ad8..74ec341be42f10 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h @@ -30,14 +30,20 @@ class InspectorFlags { */ bool getEnableCxxInspectorPackagerConnection() const; + /** + * Reset flags to their upstream values. The caller must ensure any resources + * that have read previous flag values have been cleaned up. + */ + void dangerouslyResetFlags(); + private: InspectorFlags(); InspectorFlags(const InspectorFlags&) = delete; - InspectorFlags& operator=(const InspectorFlags&) = delete; + InspectorFlags& operator=(const InspectorFlags&) = default; ~InspectorFlags() = default; - const bool enableModernCDPRegistry_; - const bool enableCxxInspectorPackagerConnection_; + bool enableModernCDPRegistry_; + bool enableCxxInspectorPackagerConnection_; mutable bool inconsistentFlagsStateLogged_; void assertFlagsMatchUpstream() const; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp index 9a1b07c207a0eb..e305713edbaff6 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp @@ -12,19 +12,53 @@ #include #include +#include +#include +#include #include namespace facebook::react::jsinspector_modern { using namespace ::testing; +class ReactInstanceIntegrationTestFeatureFlagsProvider + : public ReactNativeFeatureFlagsDefaults { + private: + FeatureFlags flags_; + + public: + explicit ReactInstanceIntegrationTestFeatureFlagsProvider( + FeatureFlags featureFlags) + : flags_(featureFlags) {} + + bool inspectorEnableModernCDPRegistry() override { + return flags_.enableModernCDPRegistry; + } + bool inspectorEnableCxxInspectorPackagerConnection() override { + return flags_.enableCxxInspectorPackagerConnection; + } +}; + ReactInstanceIntegrationTest::ReactInstanceIntegrationTest() : runtime(nullptr), instance(nullptr), messageQueueThread(std::make_shared()), - errorHandler(std::make_shared()) {} + errorHandler(std::make_shared()), + featureFlags(std::make_unique()) {} void ReactInstanceIntegrationTest::SetUp() { + ReactNativeFeatureFlags::override( + std::make_unique( + *featureFlags)); + // Reset InspectorFlags to overridden upstream values before creating objects + // that may access them. + InspectorFlags::getInstance().dangerouslyResetFlags(); + + // Double check that a flag matches our overrides. + ASSERT_EQ( + InspectorFlags::getInstance().getEnableModernCDPRegistry(), + featureFlags->enableModernCDPRegistry); + auto mockRegistry = std::make_unique(); auto timerManager = std::make_shared(std::move(mockRegistry)); @@ -47,11 +81,24 @@ void ReactInstanceIntegrationTest::SetUp() { "ErrorUtils", jsi::Object::createFromHostObject(*jsiRuntime, errorHandler)); + std::shared_ptr hostTargetIfModernCDP = nullptr; + + if (featureFlags->enableModernCDPRegistry) { + VoidExecutor inspectorExecutor = [this](auto callback) { + immediateExecutor_.add(callback); + }; + MockHostTargetDelegate hostTargetDelegate; + hostTargetIfModernCDP = + HostTarget::create(hostTargetDelegate, inspectorExecutor); + } + instance = std::make_unique( std::move(runtime_), messageQueueThread, timerManager, - std::move(jsErrorHandlingFunc)); + std::move(jsErrorHandlingFunc), + hostTargetIfModernCDP == nullptr ? nullptr : hostTargetIfModernCDP.get()); + timerManager->setRuntimeExecutor(instance->getBufferedRuntimeExecutor()); // JS Environment: @@ -59,18 +106,53 @@ void ReactInstanceIntegrationTest::SetUp() { // Inspector: auto& inspector = getInspectorInstance(); - auto pages = inspector.getPages(); - // We should now have at least a single page once the above runtime has been - // initialized. - assert(pages.size() > 0); - size_t pageId = pages.back().id; + if (hostTargetIfModernCDP != nullptr) { + // Under modern CDP, the React host is responsible for adding itself as + // the root target on startup. + pageId_ = inspector.addPage( + "mock-title", + "mock-vm", + [hostTargetIfModernCDP](std::unique_ptr remote) + -> std::unique_ptr { + auto localConnection = hostTargetIfModernCDP->connect( + std::move(remote), + { + .integrationName = "ReactInstanceIntegrationTest", + }); + return localConnection; + }, + // TODO: Allow customisation of InspectorTargetCapabilities + {}); + } else { + // Under legacy CDP, Hermes' DecoratedRuntime adds its page automatically + // within ConnectionDemux.enableDebugging. + auto pages = inspector.getPages(); + ASSERT_GT(pages.size(), 0); + pageId_ = pages.back().id; + } - clientToVM_ = inspector.connect(pageId, mockRemoteConnections_.make_unique()); + clientToVM_ = + inspector.connect(pageId_.value(), mockRemoteConnections_.make_unique()); + + ASSERT_NE(clientToVM_, nullptr); } void ReactInstanceIntegrationTest::TearDown() { clientToVM_->disconnect(); + // Destroy the local connection. + clientToVM_.reset(); + + if (pageId_.has_value() && featureFlags->enableModernCDPRegistry) { + // Under modern CDP, clean up the page we added in SetUp and destroy + // resources owned by HostTarget. + getInspectorInstance().removePage(pageId_.value()); + } + pageId_.reset(); + + // Expect the remote connection to have been destroyed. + EXPECT_EQ(mockRemoteConnections_[0], nullptr); + ReactNativeFeatureFlags::dangerouslyReset(); } void ReactInstanceIntegrationTest::initializeRuntime(std::string_view script) { @@ -84,8 +166,6 @@ void ReactInstanceIntegrationTest::initializeRuntime(std::string_view script) { std::string init(script); // JS calls no longer buffered after calling loadScript instance->loadScript(std::make_unique(init), ""); - - messageQueueThread->flush(); } void ReactInstanceIntegrationTest::send( @@ -134,18 +214,28 @@ TEST_F(ReactInstanceIntegrationTest, RuntimeEvalTest) { EXPECT_EQ(val.asNumber(), 3); } -TEST_F(ReactInstanceIntegrationTest, ConsoleLogTest) { - InSequence s; - - EXPECT_CALL(getRemoteConnection(), onMessage(_)) - .Times(2) - .RetiresOnSaturation(); - +TEST_P(ReactInstanceIntegrationTestWithFlags, ConsoleLog) { EXPECT_CALL( getRemoteConnection(), - onMessage(JsonParsed(AllOf( - AtJsonPtr("/params/args/0/value", Eq("Hello, World!")), - AtJsonPtr("/method", Eq("Runtime.consoleAPICalled")))))); + onMessage(JsonParsed( + AtJsonPtr("/method", Eq("Runtime.executionContextCreated"))))); + + EXPECT_CALL( + getRemoteConnection(), onMessage(JsonParsed(AtJsonPtr("/id", Eq(1))))); + + InSequence s; + + // Hermes console.* interception is currently explicitly disabled under the + // modern registry, and the runtime does not yet fire these events. When the + // implementation is more complete we should be able to remove this + // condition. + if (!featureFlags->enableModernCDPRegistry) { + EXPECT_CALL( + getRemoteConnection(), + onMessage(JsonParsed(AllOf( + AtJsonPtr("/params/args/0/value", Eq("Hello, World!")), + AtJsonPtr("/method", Eq("Runtime.consoleAPICalled")))))); + } EXPECT_CALL(getRemoteConnection(), onDisconnect()); @@ -153,4 +243,18 @@ TEST_F(ReactInstanceIntegrationTest, ConsoleLogTest) { run("console.log('Hello, World!');"); } +INSTANTIATE_TEST_SUITE_P( + ReactInstanceVaryingInspectorFlags, + ReactInstanceIntegrationTestWithFlags, + ::testing::Values( + FeatureFlags{ + .enableCxxInspectorPackagerConnection = true, + .enableModernCDPRegistry = true}, + FeatureFlags{ + .enableCxxInspectorPackagerConnection = false, + .enableModernCDPRegistry = false}, + FeatureFlags{ + .enableCxxInspectorPackagerConnection = true, + .enableModernCDPRegistry = false})); + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h index d21144bdbcbc53..b95500f609c382 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -18,7 +19,14 @@ namespace facebook::react::jsinspector_modern { -class ReactInstanceIntegrationTest : public ::testing::Test { +using namespace ::testing; + +struct FeatureFlags { + const bool enableCxxInspectorPackagerConnection = true; + const bool enableModernCDPRegistry = true; +}; + +class ReactInstanceIntegrationTest : public Test { protected: ReactInstanceIntegrationTest(); void SetUp() override; @@ -36,9 +44,13 @@ class ReactInstanceIntegrationTest : public ::testing::Test { std::unique_ptr instance; std::shared_ptr messageQueueThread; std::shared_ptr errorHandler; + std::unique_ptr featureFlags; MockRemoteConnection& getRemoteConnection() { - return *mockRemoteConnections_[0]; + EXPECT_EQ(mockRemoteConnections_.objectsVended(), 1); + auto rawPtr = mockRemoteConnections_[0]; + ASSERT(rawPtr != nullptr); + return *rawPtr; } private: @@ -46,8 +58,18 @@ class ReactInstanceIntegrationTest : public ::testing::Test { size_t id_ = 1; bool verbose_ = false; + std::optional pageId_; UniquePtrFactory mockRemoteConnections_; std::unique_ptr clientToVM_; + folly::QueuedImmediateExecutor immediateExecutor_; }; +class ReactInstanceIntegrationTestWithFlags + : public ReactInstanceIntegrationTest, + public ::testing::WithParamInterface { + void SetUp() override { + featureFlags = std::make_unique(GetParam()); + ReactInstanceIntegrationTest::SetUp(); + } +}; } // namespace facebook::react::jsinspector_modern From 8003189bd9a0cfc8d186784fd2fd07d30e3d03fa Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Mon, 26 Feb 2024 08:05:06 -0800 Subject: [PATCH 006/361] Deploy 0.229.2 to xplat Summary: Changelog: [Internal] Reviewed By: GijsWeterings Differential Revision: D54166486 fbshipit-source-id: 204102267edb9d975b166ecd27b17650f554d24a --- .flowconfig | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.flowconfig b/.flowconfig index 70cf15c600bda7..a5708732741628 100644 --- a/.flowconfig +++ b/.flowconfig @@ -85,4 +85,4 @@ untyped-import untyped-type-import [version] -^0.229.0 +^0.229.2 diff --git a/package.json b/package.json index 74a103918b5972..edd4f2cfd6945d 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", "flow-api-translator": "0.19.2", - "flow-bin": "^0.229.0", + "flow-bin": "^0.229.2", "glob": "^7.1.1", "hermes-eslint": "0.19.2", "hermes-transform": "0.19.2", diff --git a/yarn.lock b/yarn.lock index 4c32801bac4f09..156bb1dc8b2949 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5150,10 +5150,10 @@ flow-api-translator@0.19.2: hermes-parser "0.19.2" hermes-transform "0.19.2" -flow-bin@^0.229.0: - version "0.229.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.229.0.tgz#c129de6ab1a8578de78ed764f17d57e454df963b" - integrity sha512-tDdFj7HYSf9nDgrop8S2yw3B8nsaFLcdML4L7zWeT2FSvNapPkImkZmf0HkNLitf9EGp98iGEwRZ6naYS1nZww== +flow-bin@^0.229.2: + version "0.229.2" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.229.2.tgz#6ce5575c8d6fe93390430f9e13da4c06a9a250f4" + integrity sha512-4hjnaApj/BUhosbStw9Tqk0Muf3WCxAnauPOEHvxIfvHWBHJH3wPCCWryPkLPoifjvvcRYYEKPNWHrYF3PkErA== flow-enums-runtime@^0.0.6: version "0.0.6" From fcabb2ad21b2c17f4e0d40b0637c22ba84568038 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Mon, 26 Feb 2024 11:34:05 -0800 Subject: [PATCH 007/361] Rename PopupMenuAndroidNativeComponent.js to PopupMenuAndroidNativeComponent.android.js to fix CI Summary: This change renames `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js`. The reason is that, without the suffix, Codegen was reading the NativeComponent spec also for iOS, generating some invalid specs and making RNTester fail. ## Changelog: [Android][Changed] - Rename `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js` Reviewed By: cortinico, dmytrorykun Differential Revision: D54199736 fbshipit-source-id: 7fd67c4d38a69fe3a84c800c8ee5dcbd8c4f9a6c --- .../js/PopupMenuAndroid.android.js | 2 +- ...eComponent.js => PopupMenuAndroidNativeComponent.android.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename packages/react-native-popup-menu-android/js/{PopupMenuAndroidNativeComponent.js => PopupMenuAndroidNativeComponent.android.js} (100%) diff --git a/packages/react-native-popup-menu-android/js/PopupMenuAndroid.android.js b/packages/react-native-popup-menu-android/js/PopupMenuAndroid.android.js index b7ab6e0bf2b933..b97d45cb5a476d 100644 --- a/packages/react-native-popup-menu-android/js/PopupMenuAndroid.android.js +++ b/packages/react-native-popup-menu-android/js/PopupMenuAndroid.android.js @@ -14,7 +14,7 @@ import type {SyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes'; import PopupMenuAndroidNativeComponent, { Commands, -} from './PopupMenuAndroidNativeComponent'; +} from './PopupMenuAndroidNativeComponent.android'; import nullthrows from 'nullthrows'; import * as React from 'react'; import {useCallback, useImperativeHandle, useRef} from 'react'; diff --git a/packages/react-native-popup-menu-android/js/PopupMenuAndroidNativeComponent.js b/packages/react-native-popup-menu-android/js/PopupMenuAndroidNativeComponent.android.js similarity index 100% rename from packages/react-native-popup-menu-android/js/PopupMenuAndroidNativeComponent.js rename to packages/react-native-popup-menu-android/js/PopupMenuAndroidNativeComponent.android.js From cb2b265c20f0622dec37c8b95c0380f78cb0877b Mon Sep 17 00:00:00 2001 From: Kacper Rozniata <56474758+krozniata@users.noreply.github.com> Date: Mon, 26 Feb 2024 13:17:53 -0800 Subject: [PATCH 008/361] fix(rn-tester): prevent alert example from crashing (#43084) Summary: This small PR fixes issue causing `AlertExample` to crash on `login-password` prompt example, as it was trying to render object in `` ## Changelog: [INTERNAL] [FIXED] - Prevent alert example from crashing Pull Request resolved: https://github.com/facebook/react-native/pull/43084 Test Plan: `login-password` prompt example in `AlertExample` doesn't crash when pressing `OK` Reviewed By: cipolleschi Differential Revision: D53964494 Pulled By: lunaleaps fbshipit-source-id: 16a0364d3d65a33956c21a68b121e6c26b41d123 --- packages/rn-tester/js/examples/Alert/AlertExample.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/rn-tester/js/examples/Alert/AlertExample.js b/packages/rn-tester/js/examples/Alert/AlertExample.js index 22d058e2c99b41..895c9529faddbd 100644 --- a/packages/rn-tester/js/examples/Alert/AlertExample.js +++ b/packages/rn-tester/js/examples/Alert/AlertExample.js @@ -227,7 +227,9 @@ const AlertWithStylesPreferred = () => { }; const PromptOptions = () => { - const [promptValue, setPromptValue] = React.useState(''); + const [promptValue, setPromptValue] = React.useState< + string | {login: string, password: string}, + >(''); const customButtons = [ { @@ -243,7 +245,8 @@ const PromptOptions = () => { return ( - Prompt value: {promptValue} + Prompt value: + {JSON.stringify(promptValue, null, 2)} Date: Mon, 26 Feb 2024 14:23:21 -0800 Subject: [PATCH 009/361] Better error message for invalid response blob (#43069) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43069 Changelog: [General][Changed] - Add info to invalid blob response error Reviewed By: christophpurrer Differential Revision: D53829400 fbshipit-source-id: 17b1dbb3cacf8368098b0b639e8d10aa9bd28d03 --- packages/react-native/Libraries/Network/XMLHttpRequest.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Network/XMLHttpRequest.js b/packages/react-native/Libraries/Network/XMLHttpRequest.js index e6191b10f7b560..70a2aeea5009c4 100644 --- a/packages/react-native/Libraries/Network/XMLHttpRequest.js +++ b/packages/react-native/Libraries/Network/XMLHttpRequest.js @@ -248,7 +248,10 @@ class XMLHttpRequest extends (EventTarget(...XHR_EVENTS): any) { } else if (this._response === '') { this._cachedResponse = BlobManager.createFromParts([]); } else { - throw new Error(`Invalid response for blob: ${this._response}`); + throw new Error( + 'Invalid response for blob - expecting object, was ' + + `${typeof this._response}: ${this._response}`, + ); } break; From 2c1bcbac81dc4506196c000d72d52b7e9c1c1ec1 Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Tue, 27 Feb 2024 01:54:30 -0800 Subject: [PATCH 010/361] feature: Update `Image.getSize/getSizeWithHeaders ` methods to return a promise (#42895) Summary: `Image.getSize/getSizeWithHeaders` are still working in old fashioned "callback" way ```tsx Image.getSize(uri, function success(width,height) { }, function failure(){ } ); // undefined Image.getSizeWithHeaders(uri, headers, function success(width,height) { }, function failure(){ } ); // undefined ``` But in 2024 more developers prefer use async/await syntax for asynchronous operations So, in this PR I added support for Promise API with **backward compatibility**, modern way: ```tsx Image.getSize(uri).then(({width,height}) => { }); // Promise Image.getSizeWithHeaders(uri, headers).then(({width,height}) => { }); // Promise ``` bypass-github-export-checks ## Changelog: [GENERAL] [ADDED] - `Image.getSize/getSizeWithHeaders` method returns a promise if you don't pass a `success` callback Pull Request resolved: https://github.com/facebook/react-native/pull/42895 Test Plan: 1. ts: New test cases added in typescript tests 2. runtime: you can create a new project and put code from this PR into the next files a. `node_modules/react-native/Libraries/Image/Image.android.js` b. `node_modules/react-native/Libraries/Image/Image.ios.js` Reviewed By: javache Differential Revision: D53919431 Pulled By: cipolleschi fbshipit-source-id: 508b201e17e0ffda2e67aa5292bf9906b88d09c5 --- .eslintrc.js | 1 + .../Libraries/Image/Image.android.js | 32 +++++++++++-------- .../react-native/Libraries/Image/Image.d.ts | 15 +++++++-- .../react-native/Libraries/Image/Image.ios.js | 32 ++++++++++++------- .../Libraries/Image/ImageTypes.flow.js | 9 ++++-- .../__snapshots__/public-api-test.js.snap | 9 ++++-- .../types/__typetests__/index.tsx | 6 ++++ 7 files changed, 74 insertions(+), 30 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index b0410b566e3456..c1e8f5e0e9bad3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -113,6 +113,7 @@ module.exports = { files: ['**/*.d.ts'], plugins: ['redundant-undefined'], rules: { + 'no-dupe-class-members': 'off', 'redundant-undefined/redundant-undefined': [ 'error', {followExactOptionalPropertyTypes: true}, diff --git a/packages/react-native/Libraries/Image/Image.android.js b/packages/react-native/Libraries/Image/Image.android.js index c113d24f2bc9cb..111abb665acd94 100644 --- a/packages/react-native/Libraries/Image/Image.android.js +++ b/packages/react-native/Libraries/Image/Image.android.js @@ -23,7 +23,9 @@ import { import {getImageSourcesFromImageProps} from './ImageSourceUtils'; import {convertObjectFitToResizeMode} from './ImageUtils'; import ImageViewNativeComponent from './ImageViewNativeComponent'; -import NativeImageLoaderAndroid from './NativeImageLoaderAndroid'; +import NativeImageLoaderAndroid, { + type ImageSize, +} from './NativeImageLoaderAndroid'; import resolveAssetSource from './resolveAssetSource'; import TextInlineImageNativeComponent from './TextInlineImageNativeComponent'; import * as React from 'react'; @@ -40,13 +42,15 @@ function generateRequestId() { */ function getSize( url: string, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderAndroid.getSize(url) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderAndroid.getSize(url); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { @@ -64,13 +68,15 @@ function getSize( function getSizeWithHeaders( url: string, headers: {[string]: string, ...}, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderAndroid.getSizeWithHeaders(url, headers) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderAndroid.getSizeWithHeaders(url, headers); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { diff --git a/packages/react-native/Libraries/Image/Image.d.ts b/packages/react-native/Libraries/Image/Image.d.ts index c9e0195ba9604c..a8725c419f5c29 100644 --- a/packages/react-native/Libraries/Image/Image.d.ts +++ b/packages/react-native/Libraries/Image/Image.d.ts @@ -325,20 +325,31 @@ export interface ImageProps extends ImagePropsBase { style?: StyleProp | undefined; } +export interface ImageSize { + width: number; + height: number; +} + declare class ImageComponent extends React.Component {} declare const ImageBase: Constructor & typeof ImageComponent; export class Image extends ImageBase { + static getSize(uri: string): Promise; static getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: any) => void, - ): any; + ): void; + + static getSizeWithHeaders( + uri: string, + headers: {[index: string]: string}, + ): Promise; static getSizeWithHeaders( uri: string, headers: {[index: string]: string}, success: (width: number, height: number) => void, failure?: (error: any) => void, - ): any; + ): void; static prefetch(url: string): Promise; static prefetchWithMetadata( url: string, diff --git a/packages/react-native/Libraries/Image/Image.ios.js b/packages/react-native/Libraries/Image/Image.ios.js index 9ba060e16a9c6a..4b7353e2547f91 100644 --- a/packages/react-native/Libraries/Image/Image.ios.js +++ b/packages/react-native/Libraries/Image/Image.ios.js @@ -11,6 +11,7 @@ import type {ImageStyle, ImageStyleProp} from '../StyleSheet/StyleSheet'; import type {RootTag} from '../Types/RootTagTypes'; import type {AbstractImageIOS, ImageIOS} from './ImageTypes.flow'; +import type {ImageSize} from './NativeImageLoaderAndroid'; import {createRootTag} from '../ReactNative/RootTag'; import flattenStyle from '../StyleSheet/flattenStyle'; @@ -29,15 +30,22 @@ import * as React from 'react'; function getSize( uri: string, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderIOS.getSize(uri) - .then(([width, height]) => success(width, height)) +): void | Promise { + const promise = NativeImageLoaderIOS.getSize(uri).then(([width, height]) => ({ + width, + height, + })); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { - console.warn('Failed to get size for image ' + uri); + console.warn('Failed to get size for image: ' + uri); }, ); } @@ -45,13 +53,15 @@ function getSize( function getSizeWithHeaders( uri: string, headers: {[string]: string, ...}, - success: (width: number, height: number) => void, + success?: (width: number, height: number) => void, failure?: (error: mixed) => void, -): void { - NativeImageLoaderIOS.getSizeWithHeaders(uri, headers) - .then(function (sizes) { - success(sizes.width, sizes.height); - }) +): void | Promise { + const promise = NativeImageLoaderIOS.getSizeWithHeaders(uri, headers); + if (typeof success !== 'function') { + return promise; + } + promise + .then(sizes => success(sizes.width, sizes.height)) .catch( failure || function () { diff --git a/packages/react-native/Libraries/Image/ImageTypes.flow.js b/packages/react-native/Libraries/Image/ImageTypes.flow.js index 4200a776987f52..7ea0f71a5707ef 100644 --- a/packages/react-native/Libraries/Image/ImageTypes.flow.js +++ b/packages/react-native/Libraries/Image/ImageTypes.flow.js @@ -18,12 +18,17 @@ import typeof TextInlineImageNativeComponent from './TextInlineImageNativeCompon import * as React from 'react'; type ImageComponentStaticsIOS = $ReadOnly<{ - getSize: ( + getSize(uri: string): Promise<{width: number, height: number}>, + getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: mixed) => void, - ) => void, + ): void, + getSizeWithHeaders( + uri: string, + headers: {[string]: string, ...}, + ): Promise<{width: number, height: number}>, getSizeWithHeaders( uri: string, headers: {[string]: string, ...}, diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index bf6a0a0b61f928..591a451b02b748 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -4484,11 +4484,16 @@ exports[`public API should not change unintentionally Libraries/Image/ImageSourc exports[`public API should not change unintentionally Libraries/Image/ImageTypes.flow.js 1`] = ` "type ImageComponentStaticsIOS = $ReadOnly<{ - getSize: ( + getSize(uri: string): Promise<{ width: number, height: number }>, + getSize( uri: string, success: (width: number, height: number) => void, failure?: (error: mixed) => void - ) => void, + ): void, + getSizeWithHeaders( + uri: string, + headers: { [string]: string, ... } + ): Promise<{ width: number, height: number }>, getSizeWithHeaders( uri: string, headers: { [string]: string, ... }, diff --git a/packages/react-native/types/__typetests__/index.tsx b/packages/react-native/types/__typetests__/index.tsx index a7f8250e25d0ab..33a3a2bba745b4 100644 --- a/packages/react-native/types/__typetests__/index.tsx +++ b/packages/react-native/types/__typetests__/index.tsx @@ -1267,12 +1267,18 @@ export class ImageTest extends React.Component { } }); + const promise1: Promise = Image.getSize(uri).then(({width, height}) => + console.log(width, height), + ); Image.getSize(uri, (width, height) => console.log(width, height)); Image.getSize( uri, (width, height) => console.log(width, height), error => console.error(error), ); + const promise2: Promise = Image.getSizeWithHeaders(uri, headers).then( + ({width, height}) => console.log(width, height), + ); Image.getSizeWithHeaders(uri, headers, (width, height) => console.log(width, height), ); From 3b93f0e3c11e3e50d79f0b92316dcd7aee0950fb Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 27 Feb 2024 02:09:11 -0800 Subject: [PATCH 011/361] Correctly initialize default transformOrigin prop value to "center" Summary: ## Changelog: [Internal] - `view.transformOrigin` prop should be initialized to "center", since this is default [per documentaion](https://reactnative.dev/docs/next/transforms#transform-origin), and it should be treated this way even if the prop is not explicitly set from JS. Reviewed By: christophpurrer Differential Revision: D54229772 fbshipit-source-id: 5212792c8dc5db6f4c17d1b2980ac2564c986cd8 --- .../react/renderer/components/view/BaseViewProps.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index b7bdd9afc7eb55..5bacae92232f3d 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -54,7 +54,14 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { // Transform Transform transform{}; - TransformOrigin transformOrigin{}; + TransformOrigin transformOrigin{ + { + ValueUnit{50.0f, UnitType::Percent}, + ValueUnit{50.0f, UnitType::Percent}, + }, + 0.0f, + + }; BackfaceVisibility backfaceVisibility{}; bool shouldRasterize{}; std::optional zIndex{}; From a40bd8e34a4de61e9f7690f808fe978fab1df11c Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Tue, 27 Feb 2024 05:16:34 -0800 Subject: [PATCH 012/361] Add basic DisplayP3 color support (#42830) Summary: This adds initial support for wide gamut (DisplayP3) colors to React Native iOS per the [RFC](https://github.com/react-native-community/discussions-and-proposals/pull/738). It provides the ability to set the default color space to sRGB or DisplayP3 and provides the native code necessary to support `color()` function syntax per the [W3C CSS Color Module Level 4](https://www.w3.org/TR/css-color-4/#color-function) spec. It does _not_ yet support animations and requires additional JS code before fully supporting the `color()` function syntax. bypass-github-export-checks ## Changelog: [IOS] [ADDED] - Add basic DisplayP3 color support Pull Request resolved: https://github.com/facebook/react-native/pull/42830 Test Plan: ![Screenshot_20240131-100112](https://github.com/facebook/react-native/assets/1944151/bbd011b1-dab0-47d6-b341-74fa8fac6757) Follow test steps from https://github.com/facebook/react-native/issues/42831 to test support for `color()` function syntax. To globally change the default color space to DisplayP3 make the following changes to RNTester AppDelegate.mm: ```diff + #import - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // ... + RCTSetDefaultColorSpace(RCTColorSpaceDisplayP3); return [super application:application didFinishLaunchingWithOptions:launchOptions]; } ``` Reviewed By: javache Differential Revision: D53380407 Pulled By: cipolleschi fbshipit-source-id: 938523958f9021e8d98bdb1d4e254047e3ecdad7 --- .../Libraries/AppDelegate/RCTAppDelegate.h | 6 ++ .../Libraries/AppDelegate/RCTAppDelegate.mm | 8 +++ packages/react-native/React/Base/RCTConvert.h | 16 +++++ .../react-native/React/Base/RCTConvert.mm | 62 +++++++++++++++++-- .../React/Fabric/Utils/RCTColorSpaceUtils.h | 16 +++++ .../React/Fabric/Utils/RCTColorSpaceUtils.mm | 23 +++++++ .../renderer/graphics/ColorComponents.cpp | 23 +++++++ .../react/renderer/graphics/ColorComponents.h | 6 ++ .../renderer/graphics/React-graphics.podspec | 3 +- .../renderer/graphics/fromRawValueShared.h | 18 ++++++ .../renderer/graphics/HostPlatformColor.mm | 6 ++ 11 files changed, 180 insertions(+), 7 deletions(-) create mode 100644 packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.h create mode 100644 packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.mm create mode 100644 packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.cpp diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index dd234fb7b1616d..d6954f6dbc2ef7 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -6,6 +6,7 @@ */ #import +#import #import @class RCTBridge; @@ -131,6 +132,11 @@ NS_ASSUME_NONNULL_BEGIN /// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`. - (BOOL)runtimeSchedulerEnabled; +/** + * The default `RCTColorSpace` for the app. It defaults to `RCTColorSpaceSRGB`. + */ +@property (nonatomic, readonly) RCTColorSpace defaultColorSpace; + @property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; /// This method returns a map of Component Descriptors and Components classes that needs to be registered in the diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 702c4ab2888ad9..fc186499b8e3bc 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -6,11 +6,13 @@ */ #import "RCTAppDelegate.h" +#import #import #import #import #import #import +#import #import #import "RCTAppDelegate+Protected.h" #import "RCTAppSetupUtils.h" @@ -75,6 +77,7 @@ - (instancetype)init - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RCTSetNewArchEnabled([self newArchEnabled]); + [RCTColorSpaceUtils applyDefaultColorSpace:self.defaultColorSpace]; BOOL enableTM = self.turboModuleEnabled; BOOL fabricEnabled = self.fabricEnabled; BOOL enableBridgeless = self.bridgelessEnabled; @@ -225,6 +228,11 @@ - (void)windowScene:(UIWindowScene *)windowScene } } +- (RCTColorSpace)defaultColorSpace +{ + return RCTColorSpaceSRGB; +} + #pragma mark - New Arch Enabled settings - (BOOL)newArchEnabled diff --git a/packages/react-native/React/Base/RCTConvert.h b/packages/react-native/React/Base/RCTConvert.h index 2d55e7c99acf12..e8db7a07623fa3 100644 --- a/packages/react-native/React/Base/RCTConvert.h +++ b/packages/react-native/React/Base/RCTConvert.h @@ -17,6 +17,15 @@ #import #import +typedef NS_ENUM(NSInteger, RCTColorSpace) { + RCTColorSpaceSRGB, + RCTColorSpaceDisplayP3, +}; + +// Change the default color space +RCTColorSpace RCTGetDefaultColorSpace(void); +RCT_EXTERN void RCTSetDefaultColorSpace(RCTColorSpace colorSpace); + /** * This class provides a collection of conversion functions for mapping * JSON objects to native types and classes. These are useful when writing @@ -91,6 +100,13 @@ typedef NSURL RCTFileURL; + (CGAffineTransform)CGAffineTransform:(id)json; ++ (UIColor *)UIColorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha; ++ (UIColor *)UIColorWithRed:(CGFloat)red + green:(CGFloat)green + blue:(CGFloat)blue + alpha:(CGFloat)alpha + andColorSpace:(RCTColorSpace)colorSpace; ++ (RCTColorSpace)RCTColorSpaceFromString:(NSString *)colorSpace; + (UIColor *)UIColor:(id)json; + (CGColorRef)CGColor:(id)json CF_RETURNS_NOT_RETAINED; diff --git a/packages/react-native/React/Base/RCTConvert.mm b/packages/react-native/React/Base/RCTConvert.mm index 1367d93a873291..2d2775f50f39bf 100644 --- a/packages/react-native/React/Base/RCTConvert.mm +++ b/packages/react-native/React/Base/RCTConvert.mm @@ -879,6 +879,48 @@ + (UIEdgeInsets)UIEdgeInsets:(id)json return names; } +// The iOS side is kept in synch with the C++ side by using the +// RCTAppDelegate which, at startup, sets the default color space. +// The usage of dispatch_once and of once_flag ensoure that those are +// set only once when the app starts and that they can't change while +// the app is running. +static RCTColorSpace _defaultColorSpace = RCTColorSpaceSRGB; +RCTColorSpace RCTGetDefaultColorSpace(void) +{ + return _defaultColorSpace; +} +void RCTSetDefaultColorSpace(RCTColorSpace colorSpace) +{ + _defaultColorSpace = colorSpace; +} + ++ (UIColor *)UIColorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha +{ + RCTColorSpace space = RCTGetDefaultColorSpace(); + return [self UIColorWithRed:red green:green blue:blue alpha:alpha andColorSpace:space]; +} ++ (UIColor *)UIColorWithRed:(CGFloat)red + green:(CGFloat)green + blue:(CGFloat)blue + alpha:(CGFloat)alpha + andColorSpace:(RCTColorSpace)colorSpace +{ + if (colorSpace == RCTColorSpaceDisplayP3) { + return [UIColor colorWithDisplayP3Red:red green:green blue:blue alpha:alpha]; + } + return [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; +} + ++ (RCTColorSpace)RCTColorSpaceFromString:(NSString *)colorSpace +{ + if ([colorSpace isEqualToString:@"display-p3"]) { + return RCTColorSpaceDisplayP3; + } else if ([colorSpace isEqualToString:@"srgb"]) { + return RCTColorSpaceSRGB; + } + return RCTGetDefaultColorSpace(); +} + + (UIColor *)UIColor:(id)json { if (!json) { @@ -887,21 +929,29 @@ + (UIColor *)UIColor:(id)json if ([json isKindOfClass:[NSArray class]]) { NSArray *components = [self NSNumberArray:json]; CGFloat alpha = components.count > 3 ? [self CGFloat:components[3]] : 1.0; - return [UIColor colorWithRed:[self CGFloat:components[0]] - green:[self CGFloat:components[1]] - blue:[self CGFloat:components[2]] - alpha:alpha]; + return [self UIColorWithRed:[self CGFloat:components[0]] + green:[self CGFloat:components[1]] + blue:[self CGFloat:components[2]] + alpha:alpha]; } else if ([json isKindOfClass:[NSNumber class]]) { NSUInteger argb = [self NSUInteger:json]; CGFloat a = ((argb >> 24) & 0xFF) / 255.0; CGFloat r = ((argb >> 16) & 0xFF) / 255.0; CGFloat g = ((argb >> 8) & 0xFF) / 255.0; CGFloat b = (argb & 0xFF) / 255.0; - return [UIColor colorWithRed:r green:g blue:b alpha:a]; + return [self UIColorWithRed:r green:g blue:b alpha:a]; } else if ([json isKindOfClass:[NSDictionary class]]) { NSDictionary *dictionary = json; id value = nil; - if ((value = [dictionary objectForKey:@"semantic"])) { + NSString *rawColorSpace = [dictionary objectForKey:@"space"]; + if ([rawColorSpace isEqualToString:@"display-p3"] || [rawColorSpace isEqualToString:@"srgb"]) { + CGFloat r = [[dictionary objectForKey:@"r"] floatValue]; + CGFloat g = [[dictionary objectForKey:@"g"] floatValue]; + CGFloat b = [[dictionary objectForKey:@"b"] floatValue]; + CGFloat a = [[dictionary objectForKey:@"a"] floatValue]; + RCTColorSpace colorSpace = [self RCTColorSpaceFromString:rawColorSpace]; + return [self UIColorWithRed:r green:g blue:b alpha:a andColorSpace:colorSpace]; + } else if ((value = [dictionary objectForKey:@"semantic"])) { if ([value isKindOfClass:[NSString class]]) { NSString *semanticName = value; UIColor *color = [UIColor colorNamed:semanticName]; diff --git a/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.h b/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.h new file mode 100644 index 00000000000000..68456babda3ba8 --- /dev/null +++ b/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#import + +@interface RCTColorSpaceUtils : NSObject + ++ (void)applyDefaultColorSpace:(RCTColorSpace)colorSpace; + +@end diff --git a/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.mm b/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.mm new file mode 100644 index 00000000000000..051547ecf595c4 --- /dev/null +++ b/packages/react-native/React/Fabric/Utils/RCTColorSpaceUtils.mm @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTColorSpaceUtils.h" + +#import + +@implementation RCTColorSpaceUtils + ++ (void)applyDefaultColorSpace:(RCTColorSpace)colorSpace +{ + facebook::react::ColorSpace cxxColorSpace = + colorSpace == RCTColorSpaceSRGB ? facebook::react::ColorSpace::sRGB : facebook::react::ColorSpace::DisplayP3; + + RCTSetDefaultColorSpace(colorSpace); + facebook::react::setDefaultColorSpace(cxxColorSpace); +} + +@end diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.cpp b/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.cpp new file mode 100644 index 00000000000000..428747a31948c1 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.cpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "ColorComponents.h" +#include + +namespace facebook::react { + +static ColorSpace defaultColorSpace = ColorSpace::sRGB; + +ColorSpace getDefaultColorSpace() { + return defaultColorSpace; +} + +void setDefaultColorSpace(ColorSpace newColorSpace) { + defaultColorSpace = newColorSpace; +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.h b/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.h index 0a3887a3caeb7e..ce60f7a4074f4a 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/ColorComponents.h @@ -9,11 +9,17 @@ namespace facebook::react { +enum class ColorSpace { sRGB, DisplayP3 }; + +ColorSpace getDefaultColorSpace(); +void setDefaultColorSpace(ColorSpace newColorSpace); + struct ColorComponents { float red{0}; float green{0}; float blue{0}; float alpha{0}; + ColorSpace colorSpace{getDefaultColorSpace()}; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec index b5faee3286fc0e..94743610da2fe2 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec +++ b/packages/react-native/ReactCommon/react/renderer/graphics/React-graphics.podspec @@ -61,7 +61,8 @@ Pod::Spec.new do |s| s.dependency "glog" s.dependency "RCT-Folly/Fabric", folly_version - s.dependency "React-Core/Default", version + s.dependency "React-jsi" + s.dependency "React-jsiexecutor" s.dependency "React-utils" s.dependency "DoubleConversion" s.dependency "fmt", "9.1.0" diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h b/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h index fbc07288fa318b..87b8fcab8c6f31 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h +++ b/packages/react-native/ReactCommon/react/renderer/graphics/fromRawValueShared.h @@ -44,6 +44,24 @@ inline void fromRawValueShared( result = colorFromComponents(colorComponents); } else { + if (value.hasType>()) { + const auto& items = (std::unordered_map)value; + if (items.find("space") != items.end()) { + colorComponents.red = (float)items.at("r"); + colorComponents.green = (float)items.at("g"); + colorComponents.blue = (float)items.at("b"); + colorComponents.alpha = (float)items.at("a"); + colorComponents.colorSpace = getDefaultColorSpace(); + std::string space = (std::string)items.at("space"); + if (space == "display-p3") { + colorComponents.colorSpace = ColorSpace::DisplayP3; + } else if (space == "srgb") { + colorComponents.colorSpace = ColorSpace::sRGB; + } + result = colorFromComponents(colorComponents); + return; + } + } result = parsePlatformColor(contextContainer, surfaceId, value); } } diff --git a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm index 36cd4ac08f7b75..3d1040f1542569 100644 --- a/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm +++ b/packages/react-native/ReactCommon/react/renderer/graphics/platform/ios/react/renderer/graphics/HostPlatformColor.mm @@ -87,6 +87,12 @@ int32_t ColorFromUIColor(const std::shared_ptr &uiColor) UIColor *_Nullable UIColorFromComponentsColor(const facebook::react::ColorComponents &components) { + if (components.colorSpace == ColorSpace::DisplayP3) { + return [UIColor colorWithDisplayP3Red:components.red + green:components.green + blue:components.blue + alpha:components.alpha]; + } return [UIColor colorWithRed:components.red green:components.green blue:components.blue alpha:components.alpha]; } } // anonymous namespace From f5d5d9d284fae2bce42c9202bbfcf948e6a9ed37 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Tue, 27 Feb 2024 05:44:08 -0800 Subject: [PATCH 013/361] Fix findLibrariesFromReactNativeConfig Summary: This diff removes extra argument from the `extractLibrariesFromJSON` call inside `findLibrariesFromReactNativeConfig`. This should fix the iOS failurte discribed in https://github.com/facebook/react-native/issues/43204 Changelog: [iOS][Fixed] - Codegen correctly handles react-native.config.js. Reviewed By: cipolleschi Differential Revision: D54248400 fbshipit-source-id: 2ae5d0d29f49725877559a5b0edd7d59f8bdefaa --- .../scripts/codegen/generate-artifacts-executor.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 92434047d5a6a5..c150b1956a648e 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -283,11 +283,7 @@ function findLibrariesFromReactNativeConfig(projectRoot) { return []; } - return extractLibrariesFromJSON( - configFile, - configFile.name, - codegenConfigFileDir, - ); + return extractLibrariesFromJSON(configFile, codegenConfigFileDir); }); } From 15f0895b857bdd452381ff340a7a04ff93a37b97 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 27 Feb 2024 05:52:51 -0800 Subject: [PATCH 014/361] Optimize RCTUIManager to avoid too many calls to viewForReactTag Summary: This change fixes a couple of issues within the RCTUIManager: * it calls the right method in the `super` branches (although they should neve be executed) * it invert the call order between the `_registry` and the `uiManager` to avoid extra calls into the `viewForReactTag`. ## Changelog: [Internal] - Use the right method in super and invert the order of where we search for views. ## Facebook: See S397861 and T180527210 for more information. Reviewed By: javache Differential Revision: D54246220 fbshipit-source-id: 1c7503ad3e80cf50ecc016a984ca180a19b73cc0 --- packages/react-native/React/Modules/RCTUIManager.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/react-native/React/Modules/RCTUIManager.m b/packages/react-native/React/Modules/RCTUIManager.m index f5e5c7c7a82aca..1fb21d07338e64 100644 --- a/packages/react-native/React/Modules/RCTUIManager.m +++ b/packages/react-native/React/Modules/RCTUIManager.m @@ -1674,8 +1674,8 @@ - (instancetype)initWithUIManager:(RCTUIManager *)uiManager andRegistry:(NSDicti { self = [super init]; if (self) { - self->_uiManager = uiManager; - self->_registry = registry; + _uiManager = uiManager; + _registry = registry; } return self; } @@ -1683,19 +1683,19 @@ - (instancetype)initWithUIManager:(RCTUIManager *)uiManager andRegistry:(NSDicti - (id)objectForKey:(id)key { if (![key isKindOfClass:[NSNumber class]]) { - return [super objectForKeyedSubscript:key]; + return [super objectForKey:key]; } NSNumber *index = (NSNumber *)key; - UIView *view = [_uiManager viewForReactTag:index]; + UIView *view = _registry[index]; if (view) { return [RCTUIManager paperViewOrCurrentView:view]; } - view = _registry[index]; + view = [_uiManager viewForReactTag:index]; if (view) { return [RCTUIManager paperViewOrCurrentView:view]; } - return [super objectForKeyedSubscript:key]; + return [super objectForKey:key]; } - (void)removeObjectForKey:(id)key From 3eaf9658a43d1ad97aefad2067ff596deaefb493 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Tue, 27 Feb 2024 09:01:12 -0800 Subject: [PATCH 015/361] Add changelog for 0.74.0-rc.1 Summary: Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D54261247 fbshipit-source-id: 5f34372c8ccd2132f59c8369a820a5e877b2ec08 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc5ce296107c10..2ed7209fa548ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## v0.74.0-rc.1 + +### Added + +- Warn with future command when using `npx react-native init` ([a6397afb7f](https://github.com/facebook/react-native/commit/a6397afb7f4279e70afa025fe6f9fa0b8e3de3fd) by [@byCedric](https://github.com/byCedric)) + +### Fixed + +- Fix undefined props crash in FlatList ([e33767a36d](https://github.com/facebook/react-native/commit/e33767a36daf7901cb46854b6612dd52b0dbdeec) by [@dieguezz](https://github.com/dieguezz)) + +#### Android specific + +- Do not crash on onJSBundleLoadedFromServer when fast-refreshing on bridgeless mode ([44e5bc9e2c](https://github.com/facebook/react-native/commit/44e5bc9e2c73235ba5d8bf0f5323181948e74197) by [@cortinico](https://github.com/cortinico)) + ## 0.74.0-rc0 ### Breaking From fadcf7bf8349818b2ca91cf360820306961924d1 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Tue, 27 Feb 2024 09:09:50 -0800 Subject: [PATCH 016/361] set to public access by default Summary: Changelog: [Internal] - Specify `access` flag in publishing nightlies Reviewed By: cipolleschi Differential Revision: D54230208 fbshipit-source-id: 7711eee62e8e01a12d6604831754d36a5cd5dc13 --- scripts/npm-utils.js | 16 +++++++++++---- .../releases-ci/__tests__/publish-npm-test.js | 20 +++++++++++++++---- scripts/releases-ci/publish-npm.js | 3 +-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/scripts/npm-utils.js b/scripts/npm-utils.js index b127448c6856b0..fe3a7e5cce4d2a 100644 --- a/scripts/npm-utils.js +++ b/scripts/npm-utils.js @@ -34,8 +34,9 @@ type PackageJSON = { ... } type NpmPackageOptions = { - tags: ?Array, + tags: ?Array | ?Array, otp: ?string, + access?: ?('public' | 'restricted') } */ @@ -131,14 +132,21 @@ function publishPackage( packageOptions /*: NpmPackageOptions */, execOptions /*: ?ExecOptsSync */, ) /*: ShellString */ { - const {otp, tags} = packageOptions; - const tagsFlag = tags != null ? tags.map(t => ` --tag ${t}`).join('') : ''; + const {otp, tags, access} = packageOptions; + const tagsFlag = + tags != null + ? tags + .filter(Boolean) + .map(t => ` --tag ${t}`) + .join('') + : ''; const otpFlag = otp != null ? ` --otp ${otp}` : ''; + const accessFlag = access != null ? ` --access ${access}` : ''; const options = execOptions ? {...execOptions, cwd: packagePath} : {cwd: packagePath}; - return exec(`npm publish${tagsFlag}${otpFlag}`, options); + return exec(`npm publish${tagsFlag}${otpFlag}${accessFlag}`, options); } function diffPackages( diff --git a/scripts/releases-ci/__tests__/publish-npm-test.js b/scripts/releases-ci/__tests__/publish-npm-test.js index 3dd4230b14f168..00a4a25ee530f1 100644 --- a/scripts/releases-ci/__tests__/publish-npm-test.js +++ b/scripts/releases-ci/__tests__/publish-npm-test.js @@ -160,8 +160,14 @@ describe('publish-npm', () => { expect(setVersionMock).toBeCalledWith(expectedVersion); expect(generateAndroidArtifactsMock).toHaveBeenCalled(); expect(publishPackageMock.mock.calls).toEqual([ - ['path/to/monorepo/pkg-a', {otp: undefined, tags: ['nightly']}], - ['path/to/monorepo/pkg-b', {otp: undefined, tags: ['nightly']}], + [ + 'path/to/monorepo/pkg-a', + {otp: undefined, tags: ['nightly'], access: 'public'}, + ], + [ + 'path/to/monorepo/pkg-b', + {otp: undefined, tags: ['nightly'], access: 'public'}, + ], [ path.join(REPO_ROOT, 'packages', 'react-native'), {otp: undefined, tags: ['nightly']}, @@ -249,8 +255,14 @@ describe('publish-npm', () => { // Note that we don't call `publishPackage` for react-native, or monorepo/pkg-c expect(publishPackageMock.mock.calls).toEqual([ - ['path/to/monorepo/pkg-a', {otp: undefined, tags: ['nightly']}], - ['path/to/monorepo/pkg-b', {otp: undefined, tags: ['nightly']}], + [ + 'path/to/monorepo/pkg-a', + {otp: undefined, tags: ['nightly'], access: 'public'}, + ], + [ + 'path/to/monorepo/pkg-b', + {otp: undefined, tags: ['nightly'], access: 'public'}, + ], ]); expect(consoleLogMock.mock.calls).toEqual([ diff --git a/scripts/releases-ci/publish-npm.js b/scripts/releases-ci/publish-npm.js index 26933699cb900d..7d2d47d02cfdee 100755 --- a/scripts/releases-ci/publish-npm.js +++ b/scripts/releases-ci/publish-npm.js @@ -75,9 +75,9 @@ async function publishMonorepoPackages(tag /*: ?string */) { for (const packageInfo of Object.values(projectInfo)) { console.log(`Publishing ${packageInfo.name}...`); const result = publishPackage(packageInfo.path, { - // $FlowFixMe[incompatible-call] tags: [tag], otp: process.env.NPM_CONFIG_OTP, + access: 'public', }); const spec = `${packageInfo.name}@${packageInfo.packageJson.version}`; @@ -122,7 +122,6 @@ async function publishNpm(buildType /*: BuildType */) /*: Promise */ { const packagePath = path.join(REPO_ROOT, 'packages', 'react-native'); const result = publishPackage(packagePath, { - // $FlowFixMe[incompatible-call] tags: [tag], otp: process.env.NPM_CONFIG_OTP, }); From abbc6eb02251d8c510b3fb5415796a8f05388c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 27 Feb 2024 09:29:53 -0800 Subject: [PATCH 017/361] Modify codegen to throw JS errors instead of crashing when passing non-number arguments where RootTags are expected Summary: Changelog: [General][Fixed] Fixed crash when passing non-numeric values where RootTag is expected to methods in native modules using codegen ## Context Right now, if you have a native module using the codegen with a method like this: ``` someMethod(value: RootTag): void; ``` And you call it like this: ``` NativeModule.someMethod(''); ``` The app crashes. This happens because we cast the JS value to a C++ value using the method that asserts (`toNumber`) instead of the one that throws a JS error (`asNumber`). ## Changes This fixes the crash by using `asNumber` instead of `toNumber`. Reviewed By: RSNara Differential Revision: D54206288 fbshipit-source-id: 9398112667e0f26edaf4f8f3b32e79fa8aafde62 --- .../__snapshots__/GenerateModuleCpp-test.js.snap | 16 ++++++++-------- .../src/generators/modules/GenerateModuleCpp.js | 2 +- .../__snapshots__/GenerateModuleCpp-test.js.snap | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap index 21946d6459940c..bd464a984f3d17 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap @@ -349,7 +349,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getAlias(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].getNumber() + args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -550,7 +550,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getAl static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -656,7 +656,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSp static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -756,7 +756,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getAl static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -1170,7 +1170,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getAlias(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].getNumber() + args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -1371,7 +1371,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getAl static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -1477,7 +1477,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSp static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -1577,7 +1577,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getAl static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].getNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index e435945e5c7f0d..2a9ec5c40d8128 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -147,7 +147,7 @@ function serializeArg( case 'ReservedTypeAnnotation': switch (realTypeAnnotation.name) { case 'RootTag': - return wrap(val => `${val}.getNumber()`); + return wrap(val => `${val}.asNumber()`); default: (realTypeAnnotation.name: empty); throw new Error( diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index cef33f44c2ef3f..593ac20e70a3b9 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -559,7 +559,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].getNumber() + args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { From 179b684e7636361f7acd782cdf028c7c30b7b9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 27 Feb 2024 09:29:53 -0800 Subject: [PATCH 018/361] Modify native module codegen to throw JS errors instead of crashing when not passing required parameters Summary: Changelog: [General][Fixed] Fixed crash when passing fewer arguments than expected in native modules using codegen ## Context Right now, if you have a native module using the codegen with a method like this: ``` someMethod(value: number): void; ``` And you call it like this: ``` NativeModule.someMethod(); ``` The app crashes. This happens because the codegen tries to cast the value to the expected type without checking if the argument is within the bounds of the arguments array. ## Changes This fixes that issue with a change in the codegen to guard against this in the generated code (see changes in the snapshot tests). Reviewed By: RSNara Differential Revision: D54206287 fbshipit-source-id: 575af462725515928f8634fccc7a9cb51ca0ce4f --- .../GenerateModuleCpp-test.js.snap | 296 +++++++++--------- .../generators/modules/GenerateModuleCpp.js | 17 +- .../GenerateModuleCpp-test.js.snap | 118 +++---- 3 files changed, 215 insertions(+), 216 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap index bd464a984f3d17..1fbcaf5a6e5e05 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap @@ -17,20 +17,20 @@ namespace facebook::react { static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getReadOnlyArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getReadOnlyArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getArrayWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArrayWithAlias( rt, - args[0].asObject(rt).asArray(rt), - args[1].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt) ); } @@ -43,13 +43,13 @@ NativeArrayTurboModuleCxxSpecJSI::NativeArrayTurboModuleCxxSpecJSI(std::shared_p static jsi::Value __hostFunction_NativeBooleanTurboModuleCxxSpecJSI_getBoolean(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBoolean( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeBooleanTurboModuleCxxSpecJSI_getBooleanWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBooleanWithAlias( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } @@ -61,14 +61,14 @@ NativeBooleanTurboModuleCxxSpecJSI::NativeBooleanTurboModuleCxxSpecJSI(std::shar static jsi::Value __hostFunction_NativeCallbackTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeCallbackTurboModuleCxxSpecJSI_getValueWithCallbackWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallbackWithAlias( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } @@ -81,40 +81,40 @@ NativeCallbackTurboModuleCxxSpecJSI::NativeCallbackTurboModuleCxxSpecJSI(std::sh static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusRegular(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusRegular( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusStr(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusStr( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusNum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusNum( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusFraction(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusFraction( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStateType(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStateType( rt, - args[0].asString(rt), - args[1].asString(rt), - args[2].asNumber(), - args[3].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber(), + count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asNumber() ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStateTypeWithEnums(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStateTypeWithEnums( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } @@ -130,35 +130,35 @@ NativeEnumTurboModuleCxxSpecJSI::NativeEnumTurboModuleCxxSpecJSI(std::shared_ptr static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getBool( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getNumber( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getString( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getArray( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObject( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -181,13 +181,13 @@ NativeNullableTurboModuleCxxSpecJSI::NativeNullableTurboModuleCxxSpecJSI(std::sh static jsi::Value __hostFunction_NativeNumberTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeNumberTurboModuleCxxSpecJSI_getNumberWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumberWithAlias( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } @@ -199,25 +199,25 @@ NativeNumberTurboModuleCxxSpecJSI::NativeNumberTurboModuleCxxSpecJSI(std::shared static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObjectReadOnly(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObjectReadOnly( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObjectWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObjectWithAlias( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_difficultObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->difficultObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -257,14 +257,14 @@ static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_ge static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_getSomeObjFromPartialSomeObj(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getSomeObjFromPartialSomeObj( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_getPartialPartial(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getPartialPartial( rt, - args[0].asObject(rt), - args[1].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt) ); } @@ -278,13 +278,13 @@ NativePartialAnnotationTurboModuleCxxSpecJSI::NativePartialAnnotationTurboModule static jsi::Value __hostFunction_NativePromiseTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativePromiseTurboModuleCxxSpecJSI_getValueWithPromiseWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromiseWithAlias( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } @@ -307,70 +307,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asNumber(), - args[1].asString(rt), - args[2].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } @@ -404,70 +404,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_voidFun static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asObject(rt).asArray(rt), - args[1].asObject(rt).asArray(rt), - args[2].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } @@ -501,79 +501,79 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_voidF static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getBool( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getNumber( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getString( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getArray( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObject( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObjectShape( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getAlias( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getValue( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), - args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), - args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), + count <= 1 || args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), + count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getValueWithPromise( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -800,13 +800,13 @@ NativeSampleTurboModuleOptionalCxxSpecJSI::NativeSampleTurboModuleOptionalCxxSpe static jsi::Value __hostFunction_NativeStringTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeStringTurboModuleCxxSpecJSI_getStringWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStringWithAlias( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } @@ -838,20 +838,20 @@ namespace facebook::react { static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getReadOnlyArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getReadOnlyArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeArrayTurboModuleCxxSpecJSI_getArrayWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArrayWithAlias( rt, - args[0].asObject(rt).asArray(rt), - args[1].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt) ); } @@ -864,13 +864,13 @@ NativeArrayTurboModuleCxxSpecJSI::NativeArrayTurboModuleCxxSpecJSI(std::shared_p static jsi::Value __hostFunction_NativeBooleanTurboModuleCxxSpecJSI_getBoolean(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBoolean( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeBooleanTurboModuleCxxSpecJSI_getBooleanWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBooleanWithAlias( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } @@ -882,14 +882,14 @@ NativeBooleanTurboModuleCxxSpecJSI::NativeBooleanTurboModuleCxxSpecJSI(std::shar static jsi::Value __hostFunction_NativeCallbackTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeCallbackTurboModuleCxxSpecJSI_getValueWithCallbackWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallbackWithAlias( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } @@ -902,40 +902,40 @@ NativeCallbackTurboModuleCxxSpecJSI::NativeCallbackTurboModuleCxxSpecJSI(std::sh static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusRegular(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusRegular( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusStr(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusStr( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusNum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusNum( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStatusFraction(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStatusFraction( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStateType(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStateType( rt, - args[0].asString(rt), - args[1].asString(rt), - args[2].asNumber(), - args[3].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber(), + count <= 3 ? throw jsi::JSError(rt, \\"Expected argument in position 3 to be passed\\") : args[3].asNumber() ); } static jsi::Value __hostFunction_NativeEnumTurboModuleCxxSpecJSI_getStateTypeWithEnums(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStateTypeWithEnums( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } @@ -951,35 +951,35 @@ NativeEnumTurboModuleCxxSpecJSI::NativeEnumTurboModuleCxxSpecJSI(std::shared_ptr static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getBool( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getNumber( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getString( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getArray( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeNullableTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObject( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -1002,13 +1002,13 @@ NativeNullableTurboModuleCxxSpecJSI::NativeNullableTurboModuleCxxSpecJSI(std::sh static jsi::Value __hostFunction_NativeNumberTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeNumberTurboModuleCxxSpecJSI_getNumberWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumberWithAlias( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } @@ -1020,25 +1020,25 @@ NativeNumberTurboModuleCxxSpecJSI::NativeNumberTurboModuleCxxSpecJSI(std::shared static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObjectReadOnly(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObjectReadOnly( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getGenericObjectWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGenericObjectWithAlias( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_difficultObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->difficultObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeObjectTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -1078,14 +1078,14 @@ static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_ge static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_getSomeObjFromPartialSomeObj(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getSomeObjFromPartialSomeObj( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativePartialAnnotationTurboModuleCxxSpecJSI_getPartialPartial(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getPartialPartial( rt, - args[0].asObject(rt), - args[1].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt) ); } @@ -1099,13 +1099,13 @@ NativePartialAnnotationTurboModuleCxxSpecJSI::NativePartialAnnotationTurboModule static jsi::Value __hostFunction_NativePromiseTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativePromiseTurboModuleCxxSpecJSI_getValueWithPromiseWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromiseWithAlias( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } @@ -1128,70 +1128,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asNumber(), - args[1].asString(rt), - args[2].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } @@ -1225,70 +1225,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_voidFun static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asObject(rt).asArray(rt), - args[1].asObject(rt).asArray(rt), - args[2].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleArraysCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } @@ -1322,79 +1322,79 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_voidF static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getBool( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getNumber( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getString( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getArray( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObject( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getObjectShape( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getAlias( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getRootTag( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getValue( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), - args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), - args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), + count <= 1 || args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), + count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getValueWithPromise( rt, - args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -1621,13 +1621,13 @@ NativeSampleTurboModuleOptionalCxxSpecJSI::NativeSampleTurboModuleOptionalCxxSpe static jsi::Value __hostFunction_NativeStringTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeStringTurboModuleCxxSpecJSI_getStringWithAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStringWithAlias( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index 2a9ec5c40d8128..2fa915d1943010 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -122,7 +122,6 @@ function serializeArg( const {typeAnnotation: nullableTypeAnnotation, optional} = arg; const [typeAnnotation, nullable] = unwrapNullable(nullableTypeAnnotation); - const isRequired = !optional && !nullable; let realTypeAnnotation = typeAnnotation; if (realTypeAnnotation.type === 'TypeAliasTypeAnnotation') { @@ -132,15 +131,15 @@ function serializeArg( function wrap(callback: (val: string) => string) { const val = `args[${index}]`; const expression = callback(val); - if (isRequired) { - return expression; - } else { - let condition = `${val}.isNull() || ${val}.isUndefined()`; - if (optional) { - condition = `count <= ${index} || ${condition}`; - } - return `${condition} ? std::nullopt : std::make_optional(${expression})`; + + // param: ?T + // param?: ?T + if (nullable || optional) { + return `count <= ${index} || ${val}.isNull() || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`; } + + // param: T + return `count <= ${index} ? throw jsi::JSError(rt, "Expected argument in position ${index} to be passed") : ${expression}`; } switch (realTypeAnnotation.type) { diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index 593ac20e70a3b9..7be9050fc36d06 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -46,21 +46,21 @@ namespace facebook::react { static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_difficult(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->difficult( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionals(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->optionals( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMethod(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->optionalMethod( rt, - args[0].asObject(rt), - args[1].asObject(rt).asFunction(rt), + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asFunction(rt), count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt).asArray(rt)) ); return jsi::Value::undefined(); @@ -68,7 +68,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMetho static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArrays(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getArrays( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); return jsi::Value::undefined(); } @@ -126,13 +126,13 @@ namespace facebook::react { static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -143,7 +143,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getConstants( static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getCustomEnum( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomHostObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -154,90 +154,90 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getCustomHost static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_consumeCustomHostObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->consumeCustomHostObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBinaryTreeNode(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBinaryTreeNode( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getGraphNode(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getGraphNode( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumEnum( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getStrEnum(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getStrEnum( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getMap(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getMap( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getSet(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getSet( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getUnion(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getUnion( rt, - args[0].asNumber(), - args[1].asString(rt), - args[2].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asNumber(), - args[1].asString(rt), - args[2].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getWithWithOptionalArgs(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -256,14 +256,14 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_setMenu(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->setMenu( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_emitCustomDeviceEvent(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->emitCustomDeviceEvent( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); return jsi::Value::undefined(); } @@ -276,7 +276,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncThrow static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectThrows(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectThrows( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncAssert(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -288,7 +288,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFuncAsser static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObjectAssert(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectAssert( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } @@ -380,7 +380,7 @@ static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_getConstants(jsi::Ru static jsi::Value __hostFunction_AliasTurboModuleCxxSpecJSI_cropImage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->cropImage( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); return jsi::Value::undefined(); } @@ -420,20 +420,20 @@ static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_getConstants( static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_getPhotos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getPhotos( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_saveToCameraRoll(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->saveToCameraRoll( rt, - args[0].asString(rt), - args[1].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt) ); } static jsi::Value __hostFunction_NativeCameraRollManagerCxxSpecJSI_deletePhotos(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->deletePhotos( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } @@ -447,34 +447,34 @@ NativeCameraRollManagerCxxSpecJSI::NativeCameraRollManagerCxxSpecJSI(std::shared static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportFatalException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->reportFatalException( rt, - args[0].asString(rt), - args[1].asObject(rt).asArray(rt), - args[2].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber() ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportSoftException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->reportSoftException( rt, - args[0].asString(rt), - args[1].asObject(rt).asArray(rt), - args[2].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber() ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_reportException(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->reportException( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeExceptionsManagerCxxSpecJSI_updateExceptionMessage(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->updateExceptionMessage( rt, - args[0].asString(rt), - args[1].asObject(rt).asArray(rt), - args[2].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asArray(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asNumber() ); return jsi::Value::undefined(); } @@ -529,45 +529,45 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_voidFunc(jsi: static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - args[0].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asString(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - args[0].asObject(rt).asArray(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asArray(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - args[0].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - args[0].asNumber() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - args[0].asNumber(), - args[1].asString(rt), - args[2].asObject(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asString(rt), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asObject(rt) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -578,14 +578,14 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnumReturn static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - args[0].asObject(rt).asFunction(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt).asFunction(rt) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - args[0].asBool() + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asBool() ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithOptionalArg(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -597,9 +597,9 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithO static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getEnums( rt, - args[0].asNumber(), - args[1].asNumber(), - args[2].asString(rt) + count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asNumber(), + count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asNumber(), + count <= 2 ? throw jsi::JSError(rt, \\"Expected argument in position 2 to be passed\\") : args[2].asString(rt) ); } From 50c9a47f55000dbfbf5e8acafa749da2aff78cd5 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 27 Feb 2024 09:41:24 -0800 Subject: [PATCH 019/361] Add missing #pragma once's in ReactCommon Summary: ## Changelog: [Internal] - Was writing some unit tests, accidentally included `ImageProps.h` twice (once directly and once transitively) and realized that we have a handful of files without `#pragma once`. This fixes it for header files inside `ReactCommon`. Reviewed By: zeyap Differential Revision: D54258058 fbshipit-source-id: 70f4e9935304803187d1affd72ed44157b1d8fb3 --- packages/react-native/ReactCommon/cxxreact/ErrorUtils.h | 2 ++ .../react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h | 2 ++ .../react-native/ReactCommon/react/debug/react_native_assert.h | 2 ++ .../react-native/ReactCommon/react/debug/react_native_expect.h | 2 ++ .../ReactCommon/react/renderer/animations/conversions.h | 2 ++ .../ReactCommon/react/renderer/components/image/ImageProps.h | 2 ++ .../android/react/renderer/components/progressbar/conversions.h | 2 ++ .../ReactCommon/react/renderer/components/text/conversions.h | 2 ++ .../ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h | 2 ++ .../react/renderer/scheduler/AsynchronousEventBeat.h | 2 ++ .../ReactCommon/react/renderer/scheduler/InspectorData.h | 2 ++ .../ReactCommon/react/runtime/BridgelessJSCallInvoker.h | 2 ++ .../react/runtime/BridgelessNativeMethodCallInvoker.h | 2 ++ .../ReactCommon/react/runtime/BufferedRuntimeExecutor.h | 2 ++ .../ReactCommon/react/utils/SimpleThreadSafeCache.h | 2 ++ 15 files changed, 30 insertions(+) diff --git a/packages/react-native/ReactCommon/cxxreact/ErrorUtils.h b/packages/react-native/ReactCommon/cxxreact/ErrorUtils.h index 89603e628a7b1d..bb08c4894a0bbb 100644 --- a/packages/react-native/ReactCommon/cxxreact/ErrorUtils.h +++ b/packages/react-native/ReactCommon/cxxreact/ErrorUtils.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h b/packages/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h index cb607d3ca5b976..858f9b7f325e8e 100644 --- a/packages/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h +++ b/packages/react-native/ReactCommon/cxxreact/SharedProxyCxxModule.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include diff --git a/packages/react-native/ReactCommon/react/debug/react_native_assert.h b/packages/react-native/ReactCommon/react/debug/react_native_assert.h index 5f4036486bdce8..1d399d45421759 100644 --- a/packages/react-native/ReactCommon/react/debug/react_native_assert.h +++ b/packages/react-native/ReactCommon/react/debug/react_native_assert.h @@ -18,6 +18,8 @@ // For recoverable conditions that can be violated by user mistake (e.g. JS // code passes an unexpected prop value), consider react_native_expect instead. +#pragma once + #include "flags.h" #undef react_native_assert diff --git a/packages/react-native/ReactCommon/react/debug/react_native_expect.h b/packages/react-native/ReactCommon/react/debug/react_native_expect.h index 45656664101e43..cfc4d66f8da82a 100644 --- a/packages/react-native/ReactCommon/react/debug/react_native_expect.h +++ b/packages/react-native/ReactCommon/react/debug/react_native_expect.h @@ -20,6 +20,8 @@ // will see a helpful diagnostic (beyond a low level log). That concern is the // caller's responsibility. +#pragma once + #include "flags.h" #undef react_native_expect diff --git a/packages/react-native/ReactCommon/react/renderer/animations/conversions.h b/packages/react-native/ReactCommon/react/renderer/animations/conversions.h index 70f2486040390e..34a0957c6502b1 100644 --- a/packages/react-native/ReactCommon/react/renderer/animations/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/animations/conversions.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/components/image/ImageProps.h b/packages/react-native/ReactCommon/react/renderer/components/image/ImageProps.h index 0909b49bff20dd..3cb643a8d5e0a2 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/image/ImageProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/image/ImageProps.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h index fdfbe9fc523157..843755a8fa5015 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/progressbar/android/react/renderer/components/progressbar/conversions.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/text/conversions.h index f9002441c916c2..b9af7534475ab7 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/text/conversions.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h index a73bb52ce3c347..c15de49aac6b82 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/ErrorUtils.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/AsynchronousEventBeat.h b/packages/react-native/ReactCommon/react/renderer/scheduler/AsynchronousEventBeat.h index 3c8dfa068b91d0..af877980b00dae 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/AsynchronousEventBeat.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/AsynchronousEventBeat.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/renderer/scheduler/InspectorData.h b/packages/react-native/ReactCommon/react/renderer/scheduler/InspectorData.h index 1a0b1523adf917..d420c0329ebb9f 100644 --- a/packages/react-native/ReactCommon/react/renderer/scheduler/InspectorData.h +++ b/packages/react-native/ReactCommon/react/renderer/scheduler/InspectorData.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h index bfab788da2fa50..b6308c4169c4f8 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h index 79f922976e18ff..952a48427ef325 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/runtime/BufferedRuntimeExecutor.h b/packages/react-native/ReactCommon/react/runtime/BufferedRuntimeExecutor.h index 99a6a5352cfc85..17d3b3aff16ca6 100644 --- a/packages/react-native/ReactCommon/react/runtime/BufferedRuntimeExecutor.h +++ b/packages/react-native/ReactCommon/react/runtime/BufferedRuntimeExecutor.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include diff --git a/packages/react-native/ReactCommon/react/utils/SimpleThreadSafeCache.h b/packages/react-native/ReactCommon/react/utils/SimpleThreadSafeCache.h index a0855f68433058..c5cd6e4bfa67a1 100644 --- a/packages/react-native/ReactCommon/react/utils/SimpleThreadSafeCache.h +++ b/packages/react-native/ReactCommon/react/utils/SimpleThreadSafeCache.h @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#pragma once + #include #include #include From 8317325fb2bf6563a9314431c42c90ff68fb35fb Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Tue, 27 Feb 2024 12:28:49 -0800 Subject: [PATCH 020/361] Changelog for 0.73.5 and 0.71.17 (#43216) Summary: Changelog: [Internal] - Changelog for 0.73.5 and 0.71.17 Pull Request resolved: https://github.com/facebook/react-native/pull/43216 Reviewed By: hezi Differential Revision: D54270560 Pulled By: lunaleaps fbshipit-source-id: 34167f5ba44c230c86896e61bff733e2be11367f --- CHANGELOG.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ed7209fa548ae..3298cc030fdb86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -499,6 +499,21 @@ - Bump activesupport to minimum 6.1.7.5 CVE-2023-38037. ([07a159f279](https://github.com/facebook/react-native/commit/07a159f279cdcbed29c9c437dec1c0b8ac2d852f) by [@lunaleaps](https://github.com/lunaleaps)) +## v0.73.5 + +### Security + +- Update CLI to 12.3.6 ([ffcd8f5249](https://github.com/facebook/react-native/commit/ffcd8f524903d5d6e92e864472aaefd52dea77cf) by [@szymonrybczak](https://github.com/szymonrybczak)) + +### Changed + +- Hermes bump ([3bdd54a51c](https://github.com/facebook/react-native/commit/3bdd54a51ceea30cbbd0d1c45e9c391a80371dd2) by [@lunaleaps](https://github.com/lunaleaps)) + +### Fixed + +- Fix: fix codegen not finding all third-party libraries ([67e2bb455f](https://github.com/facebook/react-native/commit/67e2bb455fd39f00fbf2b4d4f2f019327929efa6) by [@tido64](https://github.com/tido64)) +- Fix compiler flags passed to libraries ([929df582c8](https://github.com/facebook/react-native/commit/929df582c885ad60bd34e52ced481f8e9d5666d9) by [@cipolleschi](https://github.com/cipolleschi)) + ## v0.73.4 ### Fixed @@ -1490,6 +1505,12 @@ This file contains all changelogs for latest releases, from 0.70.0 onward. Pleas - Enable Address and Undefined Behavior Sanitizers on RNTester ([65e61f3c88](https://github.com/facebook/react-native/commit/65e61f3c88388d4a2ed88bcc9a2cb5ba63fd8afa) by [@Saadnajmi](https://github.com/Saadnajmi)) +## v0.71.17 + +### Security + +- Update CLI to 10.2.7 ([28998075d9](https://github.com/facebook/react-native/commit/28998075d98754bc72a65887346f027a9657b6a3) by [@szymonrybczak](https://github.com/szymonrybczak)) + ## v0.71.16 ### Changed From 57ed0fb30931979742634a1faa9a4d3b5261e50d Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Tue, 27 Feb 2024 17:33:40 -0800 Subject: [PATCH 021/361] MapBuffer long support (#43030) Summary: This adds support for 64 bit integer (long) values to MapBuffer. Per the wide gamut color [RFC](https://github.com/react-native-community/discussions-and-proposals/pull/738) Android encodes wide gamut colors as long values so we need to update MapBuffer to support 64 bit integers as well. ## Changelog: [ANDROID] [ADDED] - Add 64 bit integer (long) value support to MapBuffer Pull Request resolved: https://github.com/facebook/react-native/pull/43030 Test Plan: I've added a test to the MapBuffer test suite. This new API is otherwise currently unused but will be used in subsequent PRs as part of wide gamut color support changes. Reviewed By: mdvacca Differential Revision: D53881809 Pulled By: NickGerleman fbshipit-source-id: 39c20b93493a2609db9f66426640ef5e97d6e1a8 --- .../ReactAndroid/api/ReactAndroid.api | 6 ++++++ .../react/common/mapbuffer/MapBuffer.kt | 20 +++++++++++++++++- .../common/mapbuffer/ReadableMapBuffer.kt | 14 +++++++++++++ .../common/mapbuffer/WritableMapBuffer.kt | 15 +++++++++++++ .../react/renderer/mapbuffer/MapBuffer.cpp | 8 +++++++ .../react/renderer/mapbuffer/MapBuffer.h | 3 +++ .../renderer/mapbuffer/MapBufferBuilder.cpp | 9 ++++++++ .../renderer/mapbuffer/MapBufferBuilder.h | 2 +- .../mapbuffer/tests/MapBufferTest.cpp | 21 +++++++++++++++++++ 9 files changed, 96 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index f0978a30b7200b..903db80d5c0c6b 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1793,6 +1793,7 @@ public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer : public abstract fun getDouble (I)D public abstract fun getInt (I)I public abstract fun getKeyOffset (I)I + public abstract fun getLong (I)J public abstract fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public abstract fun getMapBufferList (I)Ljava/util/List; public abstract fun getString (I)Ljava/lang/String; @@ -1806,6 +1807,7 @@ public final class com/facebook/react/common/mapbuffer/MapBuffer$DataType : java public static final field BOOL Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field DOUBLE Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field INT Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; + public static final field LONG Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field MAP Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static final field STRING Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; public static fun valueOf (Ljava/lang/String;)Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; @@ -1817,6 +1819,7 @@ public abstract interface class com/facebook/react/common/mapbuffer/MapBuffer$En public abstract fun getDoubleValue ()D public abstract fun getIntValue ()I public abstract fun getKey ()I + public abstract fun getLongValue ()J public abstract fun getMapBufferValue ()Lcom/facebook/react/common/mapbuffer/MapBuffer; public abstract fun getStringValue ()Ljava/lang/String; public abstract fun getType ()Lcom/facebook/react/common/mapbuffer/MapBuffer$DataType; @@ -1837,6 +1840,7 @@ public final class com/facebook/react/common/mapbuffer/ReadableMapBuffer : com/f public fun getDouble (I)D public fun getInt (I)I public fun getKeyOffset (I)I + public fun getLong (I)J public synthetic fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/ReadableMapBuffer; public fun getMapBufferList (I)Ljava/util/List; @@ -1859,6 +1863,7 @@ public final class com/facebook/react/common/mapbuffer/WritableMapBuffer : com/f public fun getDouble (I)D public fun getInt (I)I public fun getKeyOffset (I)I + public fun getLong (I)J public fun getMapBuffer (I)Lcom/facebook/react/common/mapbuffer/MapBuffer; public fun getMapBufferList (I)Ljava/util/List; public fun getString (I)Ljava/lang/String; @@ -1866,6 +1871,7 @@ public final class com/facebook/react/common/mapbuffer/WritableMapBuffer : com/f public fun iterator ()Ljava/util/Iterator; public final fun put (ID)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (II)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; + public final fun put (IJ)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (ILcom/facebook/react/common/mapbuffer/MapBuffer;)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (ILjava/lang/String;)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; public final fun put (IZ)Lcom/facebook/react/common/mapbuffer/WritableMapBuffer; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt index 301837032fbbf0..53bb6b855434f1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/MapBuffer.kt @@ -44,7 +44,8 @@ public interface MapBuffer : Iterable { INT, DOUBLE, STRING, - MAP + MAP, + LONG } /** @@ -109,6 +110,16 @@ public interface MapBuffer : Iterable { */ public fun getInt(key: Int): Int + /** + * Provides parsed [Long] value if the entry for given key exists with [DataType.LONG] type + * + * @param key key to lookup [Long] value for + * @return value associated with the requested key + * @throws IllegalArgumentException if the key doesn't exist + * @throws IllegalStateException if the data type doesn't match + */ + public fun getLong(key: Int): Long + /** * Provides parsed [Double] value if the entry for given key exists with [DataType.DOUBLE] type * @@ -175,6 +186,13 @@ public interface MapBuffer : Iterable { */ public val intValue: Int + /** + * Entry value represented as [Long] + * + * @throws IllegalStateException if the data type doesn't match [DataType.LONG] + */ + public val longValue: Long + /** * Entry value represented as [Double] * diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt index 66add82a7e9e23..80371e93c27131 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/ReadableMapBuffer.kt @@ -115,6 +115,10 @@ public class ReadableMapBuffer : MapBuffer { return buffer.getInt(bufferPosition) } + private fun readLongValue(bufferPosition: Int): Long { + return buffer.getLong(bufferPosition) + } + private fun readBooleanValue(bufferPosition: Int): Boolean { return readIntValue(bufferPosition) == 1 } @@ -180,6 +184,9 @@ public class ReadableMapBuffer : MapBuffer { override fun getInt(key: Int): Int = readIntValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.INT)) + override fun getLong(key: Int): Long = + readLongValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.LONG)) + override fun getDouble(key: Int): Double = readDoubleValue(getTypedValueOffsetForKey(key, MapBuffer.DataType.DOUBLE)) @@ -223,6 +230,7 @@ public class ReadableMapBuffer : MapBuffer { when (entry.type) { MapBuffer.DataType.BOOL -> builder.append(entry.booleanValue) MapBuffer.DataType.INT -> builder.append(entry.intValue) + MapBuffer.DataType.LONG -> builder.append(entry.longValue) MapBuffer.DataType.DOUBLE -> builder.append(entry.doubleValue) MapBuffer.DataType.STRING -> builder.append(entry.stringValue) MapBuffer.DataType.MAP -> builder.append(entry.mapBufferValue.toString()) @@ -280,6 +288,12 @@ public class ReadableMapBuffer : MapBuffer { return readIntValue(bucketOffset + VALUE_OFFSET) } + override val longValue: Long + get() { + assertType(MapBuffer.DataType.LONG) + return readLongValue(bucketOffset + VALUE_OFFSET) + } + override val booleanValue: Boolean get() { assertType(MapBuffer.DataType.BOOL) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt index fb145f4dddf697..f79e9122b53b98 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/common/mapbuffer/WritableMapBuffer.kt @@ -48,6 +48,15 @@ public class WritableMapBuffer : MapBuffer { */ public fun put(key: Int, value: Int): WritableMapBuffer = putInternal(key, value) + /** + * Adds a long value for given key to the MapBuffer. + * + * @param key entry key + * @param value entry value + * @throws IllegalArgumentException if key is out of [UShort] range + */ + public fun put(key: Int, value: Long): WritableMapBuffer = putInternal(key, value) + /** * Adds a double value for given key to the MapBuffer. * @@ -107,6 +116,8 @@ public class WritableMapBuffer : MapBuffer { override fun getInt(key: Int): Int = verifyValue(key, values.get(key)) + override fun getLong(key: Int): Long = verifyValue(key, values.get(key)) + override fun getDouble(key: Int): Double = verifyValue(key, values.get(key)) override fun getString(key: Int): String = verifyValue(key, values.get(key)) @@ -128,6 +139,7 @@ public class WritableMapBuffer : MapBuffer { return when (val value = this) { is Boolean -> DataType.BOOL is Int -> DataType.INT + is Long -> DataType.LONG is Double -> DataType.DOUBLE is String -> DataType.STRING is MapBuffer -> DataType.MAP @@ -153,6 +165,9 @@ public class WritableMapBuffer : MapBuffer { override val intValue: Int get() = verifyValue(key, values.valueAt(index)) + override val longValue: Long + get() = verifyValue(key, values.valueAt(index)) + override val doubleValue: Double get() = verifyValue(key, values.valueAt(index)) diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp index 8a46d17fa3b0da..5d9c0aa56ef912 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.cpp @@ -61,6 +61,14 @@ int32_t MapBuffer::getInt(Key key) const { bytes_.data() + valueOffset(bucketIndex)); } +int64_t MapBuffer::getLong(Key key) const { + auto bucketIndex = getKeyBucket(key); + react_native_assert(bucketIndex != -1 && "Key not found in MapBuffer"); + + return *reinterpret_cast( + bytes_.data() + valueOffset(bucketIndex)); +} + bool MapBuffer::getBool(Key key) const { return getInt(key) != 0; } diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h index 1efe45cf063114..968747ee64fb71 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBuffer.h @@ -104,6 +104,7 @@ class MapBuffer { Double = 2, String = 3, Map = 4, + Long = 5, }; explicit MapBuffer(std::vector data); @@ -118,6 +119,8 @@ class MapBuffer { int32_t getInt(MapBuffer::Key key) const; + int64_t getLong(MapBuffer::Key key) const; + bool getBool(MapBuffer::Key key) const; double getDouble(MapBuffer::Key key) const; diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp index 7bf76d91e6907e..c7eb0e38e9aeef 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.cpp @@ -13,6 +13,7 @@ using namespace facebook::react; namespace facebook::react { constexpr uint32_t INT_SIZE = sizeof(uint32_t); +constexpr uint32_t LONG_SIZE = sizeof(uint64_t); constexpr uint32_t DOUBLE_SIZE = sizeof(double); constexpr uint32_t MAX_BUCKET_VALUE_SIZE = sizeof(uint64_t); @@ -76,6 +77,14 @@ void MapBufferBuilder::putInt(MapBuffer::Key key, int32_t value) { INT_SIZE); } +void MapBufferBuilder::putLong(MapBuffer::Key key, int64_t value) { + storeKeyValue( + key, + MapBuffer::DataType::Long, + reinterpret_cast(&value), + LONG_SIZE); +} + void MapBufferBuilder::putString(MapBuffer::Key key, const std::string& value) { auto strSize = value.size(); const char* strData = value.data(); diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h index 60ca37d20aba74..2260e690a2d785 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/MapBufferBuilder.h @@ -27,7 +27,7 @@ class MapBufferBuilder { void putInt(MapBuffer::Key key, int32_t value); - // TODO: Support 64 bit integers + void putLong(MapBuffer::Key key, int64_t value); void putBool(MapBuffer::Key key, bool value); diff --git a/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp b/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp index 8f3baaaf59fdcf..5be4c9e1272d25 100644 --- a/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mapbuffer/tests/MapBufferTest.cpp @@ -5,6 +5,7 @@ * LICENSE file in the root directory of this source tree. */ +#include #include #include @@ -27,6 +28,26 @@ TEST(MapBufferTest, testSimpleIntMap) { EXPECT_EQ(map.getInt(1), 4321); } +TEST(MapBufferTest, testSimpleLongMap) { + auto builder = MapBufferBuilder(); + + int64_t minInt64 = std::numeric_limits::min(); + int64_t maxInt64 = std::numeric_limits::max(); + + builder.putLong(0, minInt64); + builder.putLong(1, maxInt64); + builder.putLong(2, 1125899906842623LL); + builder.putLong(3, -1125899906842623LL); + + auto map = builder.build(); + + EXPECT_EQ(map.count(), 4); + EXPECT_EQ(map.getLong(0), minInt64); + EXPECT_EQ(map.getLong(1), maxInt64); + EXPECT_EQ(map.getLong(2), 1125899906842623LL); + EXPECT_EQ(map.getLong(3), -1125899906842623LL); +} + TEST(MapBufferTest, testMapBufferExtension) { // 26 = 2 buckets: 2*10 + 6 sizeof(header) int initialSize = 26; From c3b0a8f1626939cf5c7b3864a5acf9d3dad26fb3 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Wed, 28 Feb 2024 06:09:38 -0800 Subject: [PATCH 022/361] Deprecate `getSurfacePresenter` and `getModuleRegistry` in favor of their props Summary: This change align the `getSurfacePresenter` and `getModuleRegistry` to the iOS convention for which these should be computed properties with no `get` prefix in their name. We want to land this change and to pick it in 0.74 so we can remove the `get` versions in 0.75. ## Changelog: [iOS][Deprecated] - Deprecate `getSurfacePresenter` and `getModuleRegistry` for `surfacePresenter` and moduleRegistry` props. Reviewed By: javache Differential Revision: D54253805 fbshipit-source-id: e9ff7db744a73a3bd0f8ae1d87875e54ddd9a1a4 --- .../platform/ios/ReactCommon/RCTHost.h | 8 ++++++-- .../platform/ios/ReactCommon/RCTHost.mm | 20 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h index 6b869377a836a5..ea4492980f976f 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.h @@ -52,6 +52,10 @@ typedef std::shared_ptr (^RCTHostJSEngineProv @property (nonatomic, weak, nullable) id runtimeDelegate; +@property (nonatomic, readonly) RCTSurfacePresenter *surfacePresenter; + +@property (nonatomic, readonly) RCTModuleRegistry *moduleRegistry; + - (void)start; - (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args; @@ -64,11 +68,11 @@ typedef std::shared_ptr (^RCTHostJSEngineProv - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)properties; -- (RCTSurfacePresenter *)getSurfacePresenter; +- (RCTSurfacePresenter *)getSurfacePresenter __attribute__((deprecated("Use `surfacePresenter` property instead."))); // Native module API -- (RCTModuleRegistry *)getModuleRegistry; +- (RCTModuleRegistry *)getModuleRegistry __attribute__((deprecated("Use `moduleRegistry` property instead."))); @end diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm index 711fcc037a30c3..711f94dfac4c71 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTHost.mm @@ -212,7 +212,7 @@ - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName mode:(DisplayMode)displayMode initialProperties:(NSDictionary *)properties { - RCTFabricSurface *surface = [[RCTFabricSurface alloc] initWithSurfacePresenter:[self getSurfacePresenter] + RCTFabricSurface *surface = [[RCTFabricSurface alloc] initWithSurfacePresenter:self.surfacePresenter moduleName:moduleName initialProperties:properties]; surface.surfaceHandler.setDisplayMode(displayMode); @@ -235,16 +235,28 @@ - (RCTFabricSurface *)createSurfaceWithModuleName:(NSString *)moduleName initial return [self createSurfaceWithModuleName:moduleName mode:DisplayMode::Visible initialProperties:properties]; } -- (RCTModuleRegistry *)getModuleRegistry +- (RCTModuleRegistry *)moduleRegistry { return _moduleRegistry; } -- (RCTSurfacePresenter *)getSurfacePresenter +// Deprecated +- (RCTModuleRegistry *)getModuleRegistry +{ + return self.moduleRegistry; +} + +- (RCTSurfacePresenter *)surfacePresenter { return [_instance surfacePresenter]; } +// Deprecated +- (RCTSurfacePresenter *)getSurfacePresenter +{ + return self.surfacePresenter; +} + - (void)callFunctionOnJSModule:(NSString *)moduleName method:(NSString *)method args:(NSArray *)args { [_instance callFunctionOnJSModule:moduleName method:method args:args]; @@ -276,7 +288,7 @@ - (void)didReceiveReloadCommand [_hostDelegate hostDidStart:self]; for (RCTFabricSurface *surface in [self _getAttachedSurfaces]) { - [surface resetWithSurfacePresenter:[self getSurfacePresenter]]; + [surface resetWithSurfacePresenter:self.surfacePresenter]; } } From a1197695fc7dd7750001dc60853fd19f162dc69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Wed, 28 Feb 2024 08:37:26 -0800 Subject: [PATCH 023/361] fix(iOS) [0.74]: properly warn about createRootViewWithBridge (#43146) Summary: This PR fixes an issue that `_logWarnIfCreateRootViewWithBridgeIsOverridden` was called in wrong place. Assuming user overrides this method and call to `[super]`: ```objc - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps { UIView *view = [super createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps]; view.backgroundColor = [UIColor redColor]; return view; } ``` This method still wasn't called in bridgeless (and not showing the error). Checking if user overrides this method in `appDidFinishWithLaunching` works every time ![simulator_screenshot_0E22557C-CE37-4617-A25A-F39A6ED4D3D0](https://github.com/facebook/react-native/assets/52801365/d7865f37-32f0-40ad-a252-74ab7c5b7757) ## Changelog: [IOS] [FIXED] - Properly warn about `createRootViewWithBridge` being deprecated Pull Request resolved: https://github.com/facebook/react-native/pull/43146 Test Plan: Check if warning is shown when message is overridden Reviewed By: huntie Differential Revision: D54303506 Pulled By: cipolleschi fbshipit-source-id: cf30555c791493f28b3015a189cf93b60cace8f8 --- packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index fc186499b8e3bc..6c464725d87d8d 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -118,6 +118,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; } + [self _logWarnIfCreateRootViewWithBridgeIsOverridden]; [self customizeRootView:(RCTRootView *)rootView]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [self createRootViewController]; @@ -160,7 +161,6 @@ - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps { - [self _logWarnIfCreateRootViewWithBridgeIsOverridden]; BOOL enableFabric = self.fabricEnabled; UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); From 779e3be1069a415c7634052b6742dbaeedbcac6e Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 08:47:35 -0800 Subject: [PATCH 024/361] Mark classes of package uimanager as @Nullsafe Summary: All these classes are NullSafe, let's mark them as NullSafe(Local) to ensure lint detect errors in the future bypass-github-export-checks changelog: [internal] internal Reviewed By: arushikesarwani94 Differential Revision: D54027177 fbshipit-source-id: 13b4352f0b61eec69bfdcb6a3e369faa4dfcc750 --- .../java/com/facebook/react/uimanager/ReactStylesDiffMap.java | 2 ++ .../com/facebook/react/uimanager/ReactYogaConfigProvider.java | 2 ++ .../main/java/com/facebook/react/uimanager/RootViewManager.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMap.java index 504bedbfe220da..7f7982597e8def 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactStylesDiffMap.java @@ -9,6 +9,7 @@ import android.view.View; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.Dynamic; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; @@ -32,6 +33,7 @@ * shouldn't be updated (whereas in all other cases it should be updated to the new value or the * property should be reset). */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class ReactStylesDiffMap { /* package */ final ReadableMap mBackingMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactYogaConfigProvider.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactYogaConfigProvider.java index 16fbb71ae118b5..67c80d2c80f8fd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactYogaConfigProvider.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactYogaConfigProvider.java @@ -7,10 +7,12 @@ package com.facebook.react.uimanager; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.yoga.YogaConfig; import com.facebook.yoga.YogaConfigFactory; import com.facebook.yoga.YogaErrata; +@Nullsafe(Nullsafe.Mode.LOCAL) public class ReactYogaConfigProvider { private static YogaConfig YOGA_CONFIG; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootViewManager.java index 4393528caac2a5..3a09de11df831d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/RootViewManager.java @@ -9,8 +9,10 @@ import android.view.ViewGroup; import android.widget.FrameLayout; +import com.facebook.infer.annotation.Nullsafe; /** View manager for ReactRootView components. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class RootViewManager extends ViewGroupManager { public static final String REACT_CLASS = "RootView"; From becb9a3df67b7933e35c2fc245999ce2a6ec6cf4 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 08:47:35 -0800 Subject: [PATCH 025/361] Mark classes of package uimanager as @Nullsafe Summary: All these classes are NullSafe, let's mark them as NullSafe(Local) to ensure lint detect errors in the future bypass-github-export-checks changelog: [internal] internal Reviewed By: javache Differential Revision: D54027186 fbshipit-source-id: 2cee2b598c3ef15641222018703a7d6a467ba30c --- .../java/com/facebook/react/uimanager/SimpleViewManager.java | 2 ++ .../src/main/java/com/facebook/react/uimanager/Spacing.java | 2 ++ .../facebook/react/uimanager/UIConstantsProviderManager.java | 2 ++ 3 files changed, 6 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/SimpleViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/SimpleViewManager.java index ef65aae2f83577..18be6800791658 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/SimpleViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/SimpleViewManager.java @@ -8,6 +8,7 @@ package com.facebook.react.uimanager; import android.view.View; +import com.facebook.infer.annotation.Nullsafe; /** * Common base class for most of the {@link ViewManager}s. It provides support for most common @@ -17,6 +18,7 @@ * * @param the view handled by this manager */ +@Nullsafe(Nullsafe.Mode.LOCAL) public abstract class SimpleViewManager extends BaseViewManager { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java index 9ff37664d52b67..889eeade9e4c65 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/Spacing.java @@ -7,6 +7,7 @@ package com.facebook.react.uimanager; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.yoga.YogaConstants; import java.util.Arrays; @@ -15,6 +16,7 @@ * properly implement interactions and updates for properties like margin, marginLeft, and * marginHorizontal. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class Spacing { /** Spacing type that represents the left direction. E.g. {@code marginLeft}. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIConstantsProviderManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIConstantsProviderManager.java index 06af04472248b3..5fdf6e535e2012 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIConstantsProviderManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIConstantsProviderManager.java @@ -7,6 +7,7 @@ package com.facebook.react.uimanager; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.proguard.annotations.DoNotStripAny; @@ -15,6 +16,7 @@ import com.facebook.soloader.SoLoader; import javax.annotation.Nullable; +@Nullsafe(Nullsafe.Mode.LOCAL) @DoNotStripAny public class UIConstantsProviderManager { From 2e708c9c2c909f41cb86d9a1552e2b46fb2c6391 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 08:47:35 -0800 Subject: [PATCH 026/361] Mark classes of package uimanager as @Nullsafe Summary: All these classes are NullSafe, let's mark them as NullSafe(Local) to ensure lint detect errors in the future bypass-github-export-checks changelog: [internal] internal Reviewed By: javache Differential Revision: D54027180 fbshipit-source-id: bf8875c06c8990172e6b449e12902691131b9cef --- .../java/com/facebook/react/uimanager/UIManagerHelper.java | 2 ++ .../facebook/react/uimanager/UIManagerModuleConstants.java | 4 +++- .../react/uimanager/UIManagerModuleConstantsHelper.java | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java index 52f635eaa6aac0..c4e7b0c5cd3474 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerHelper.java @@ -16,6 +16,7 @@ import android.widget.EditText; import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.CatalystInstance; import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactNoCrashSoftException; @@ -26,6 +27,7 @@ import com.facebook.react.uimanager.events.EventDispatcherProvider; /** Helper class for {@link UIManager}. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class UIManagerHelper { private static final String TAG = UIManagerHelper.class.getName(); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstants.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstants.java index ee4f7969235a01..be8c69379f741c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstants.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstants.java @@ -9,12 +9,14 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.ImageView; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.events.TouchEventType; import java.util.Map; /** Constants exposed to JS from {@link UIManagerModule}. */ -/* package */ class UIManagerModuleConstants { +/* package */ @Nullsafe(Nullsafe.Mode.LOCAL) +class UIManagerModuleConstants { public static final String ACTION_DISMISSED = "dismissed"; public static final String ACTION_ITEM_SELECTED = "itemSelected"; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index 098b7e15fa976e..4aa4c3900968f9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -10,6 +10,7 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.common.MapBuilder; import com.facebook.react.common.build.ReactBuildConfig; import com.facebook.react.config.ReactFeatureFlags; @@ -24,6 +25,7 @@ * Helps generate constants map for {@link UIManagerModule} by collecting and merging constants from * registered view managers. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class UIManagerModuleConstantsHelper { private static final String TAG = "UIManagerModuleConstantsHelper"; private static final String BUBBLING_EVENTS_KEY = "bubblingEventTypes"; From eff28ae113f6e5f7264faf22e2b2aa3511c2e21e Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 08:47:35 -0800 Subject: [PATCH 027/361] Mark classes of package uimanager as @Nullsafe Summary: All these classes are NullSafe, let's mark them as NullSafe(Local) to ensure lint detect errors in the future bypass-github-export-checks changelog: [internal] internal Reviewed By: javache Differential Revision: D54027184 fbshipit-source-id: 722a7e398849f5d935894f321aa0177167eebaef --- .../main/java/com/facebook/react/uimanager/ViewDefaults.java | 3 +++ .../facebook/react/uimanager/ViewGroupDrawingOrderHelper.java | 2 ++ .../java/com/facebook/react/uimanager/ViewGroupManager.java | 2 ++ 3 files changed, 7 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java index 8cab4071bda2ef..772011fb5c6077 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewDefaults.java @@ -7,7 +7,10 @@ package com.facebook.react.uimanager; +import com.facebook.infer.annotation.Nullsafe; + /** Default property values for Views to be shared between Views and ShadowViews. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class ViewDefaults { public static final float FONT_SIZE_SP = 14.0f; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupDrawingOrderHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupDrawingOrderHelper.java index 2bd1d754f3a398..99356c260c311f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupDrawingOrderHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupDrawingOrderHelper.java @@ -11,12 +11,14 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; import com.facebook.common.logging.FLog; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.common.ReactConstants; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; /** Helper to handle implementing ViewGroups with custom drawing order based on z-index. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public class ViewGroupDrawingOrderHelper { private final ViewGroup mViewGroup; private int mNumberOfChildrenWithZIndex = 0; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java index 419747ae9b92b8..52907b218c6b9f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java @@ -10,11 +10,13 @@ import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; +import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.UiThreadUtil; import java.util.List; import java.util.WeakHashMap; /** Class providing children management API for view managers of classes extending ViewGroup. */ +@Nullsafe(Nullsafe.Mode.LOCAL) public abstract class ViewGroupManager extends BaseViewManager implements IViewGroupManager { From a861a66d71d61a3b6e6d3f014ffb4502eae850e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 28 Feb 2024 09:53:18 -0800 Subject: [PATCH 028/361] Add uiThreadConditionalSync executor to AndroidExecutors Summary: Changelog: [internal] This adds a new type of executor in AndroidExecutors to execute runnables on the UI thread. If the caller is already on the UI thread it'd call the runnable immediately. Otherwise it'd be scheduled in the UI thread to execute asynchronously. Reviewed By: huntie Differential Revision: D53941120 fbshipit-source-id: b68c7a4540be2a12df930e4e52eeb7b7a1aa91d8 --- .../ReactAndroid/api/ReactAndroid.api | 1 + .../internal/bolts/AndroidExecutors.java | 44 +++++++++++++++++-- .../react/runtime/internal/bolts/Task.java | 4 ++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 903db80d5c0c6b..10388444d06e5c 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3673,6 +3673,7 @@ public abstract interface class com/facebook/react/runtime/internal/bolts/Contin public class com/facebook/react/runtime/internal/bolts/Task : com/facebook/react/interfaces/TaskInterface { public static final field BACKGROUND_EXECUTOR Ljava/util/concurrent/ExecutorService; + public static final field UI_THREAD_CONDITIONAL_SYNC_EXECUTOR Ljava/util/concurrent/Executor; public static final field UI_THREAD_EXECUTOR Ljava/util/concurrent/Executor; public static fun call (Ljava/util/concurrent/Callable;)Lcom/facebook/react/runtime/internal/bolts/Task; public static fun call (Ljava/util/concurrent/Callable;Lcom/facebook/react/runtime/internal/bolts/CancellationToken;)Lcom/facebook/react/runtime/internal/bolts/Task; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/AndroidExecutors.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/AndroidExecutors.java index 49518ccc90db0b..dc4e691dc0b753 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/AndroidExecutors.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/AndroidExecutors.java @@ -39,9 +39,11 @@ final class AndroidExecutors { private static final AndroidExecutors INSTANCE = new AndroidExecutors(); @NonNull private final Executor uiThread; + @NonNull private final Executor uiThreadConditionalSync; private AndroidExecutors() { uiThread = new UIThreadExecutor(); + uiThreadConditionalSync = new UIThreadConditionalSyncExecutor(); } /** @@ -122,16 +124,52 @@ public static void allowCoreThreadTimeout(@NonNull ThreadPoolExecutor executor, } } - /** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */ + /** + * An {@link java.util.concurrent.Executor} that schedules tasks to run asynchronously on the UI + * thread. + */ public static @NonNull Executor uiThread() { return INSTANCE.uiThread; } - /** An {@link java.util.concurrent.Executor} that runs tasks on the UI thread. */ + /** + * An {@link java.util.concurrent.Executor} that runs tasks on the UI thread (immediately if + * already on that thread). + */ + public static @NonNull Executor uiThreadConditionalSync() { + return INSTANCE.uiThreadConditionalSync; + } + + /** + * An {@link java.util.concurrent.Executor} that schedules tasks to run asynchronously on the UI + * thread. + */ private static class UIThreadExecutor implements Executor { + private final Handler mHandler = new Handler(Looper.getMainLooper()); + + @Override + public void execute(@NonNull Runnable command) { + // Otherwise, post it on the main thread handler + mHandler.post(command); + } + } + + /** + * An {@link java.util.concurrent.Executor} that runs tasks on the UI thread (immediately if + * already on that thread). + */ + private static class UIThreadConditionalSyncExecutor implements Executor { + private final Handler mHandler = new Handler(Looper.getMainLooper()); + @Override public void execute(@NonNull Runnable command) { - new Handler(Looper.getMainLooper()).post(command); + if (Looper.myLooper() == mHandler.getLooper()) { + // If we're already on the main thread, execute the command immediately + command.run(); + } else { + // Otherwise, post it on the main thread handler + mHandler.post(command); + } } } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java index 1f4db71e3368bf..634fb318a15212 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/internal/bolts/Task.java @@ -42,6 +42,10 @@ public class Task implements TaskInterface { /** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */ public static final Executor UI_THREAD_EXECUTOR = AndroidExecutors.uiThread(); + /** An {@link java.util.concurrent.Executor} that executes tasks on the UI thread. */ + public static final Executor UI_THREAD_CONDITIONAL_SYNC_EXECUTOR = + AndroidExecutors.uiThreadConditionalSync(); + /** * Interface for handlers invoked when a failed {@code Task} is about to be finalized, but the * exception has not been consumed. From 65c394f33ac4a0f61e65c4825d2a823e924f20f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 28 Feb 2024 09:53:18 -0800 Subject: [PATCH 029/361] Register ReactHostImpl with modern CDP backend Summary: Changelog: [Internal] This implements the integration of `ReactHost` with the modern CDP backend. It handles the registration of pages in CDP when we create new instances of `ReactHost` (which is the equivalent concept in React Native). The next PR will handle the registration of `ReactInstance` to complete the integration on bridgeless. Reviewed By: huntie Differential Revision: D51459049 fbshipit-source-id: 9576c8d8e38ca925035d90f2871bcd7aa534f725 --- .../facebook/react/runtime/ReactHostImpl.java | 3 + .../react/runtime/ReactHostInspectorTarget.kt | 36 +++++++++ .../runtime/jni/JReactHostInspectorTarget.cpp | 79 +++++++++++++++++++ .../runtime/jni/JReactHostInspectorTarget.h | 66 ++++++++++++++++ .../src/main/jni/react/runtime/jni/OnLoad.cpp | 2 + .../facebook/react/runtime/ReactHostTest.kt | 5 ++ .../react/runtime/ReactSurfaceTest.kt | 7 +- 7 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp create mode 100644 packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 674aeb42f9f7fd..93fe93ec08f1e3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -108,6 +108,7 @@ public class ReactHostImpl implements ReactHost { private final MemoryPressureRouter mMemoryPressureRouter; private final boolean mAllowPackagerServerAccess; private final boolean mUseDevSupport; + private final ReactHostInspectorTarget mReactHostInspectorTarget; private final Collection mReactInstanceEventListeners = Collections.synchronizedList(new ArrayList<>()); @@ -184,6 +185,7 @@ public ReactHostImpl( mDevSupportManager = new DisabledDevSupportManager(); } mUseDevSupport = useDevSupport; + mReactHostInspectorTarget = new ReactHostInspectorTarget(this); } @Override @@ -759,6 +761,7 @@ private Task getOrCreateStartTask() { @ThreadConfined(UI) private void moveToHostDestroy(@Nullable ReactContext currentContext) { mReactLifecycleStateManager.moveToOnHostDestroy(currentContext); + mReactHostInspectorTarget.close(); setCurrentActivity(null); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt new file mode 100644 index 00000000000000..6b6820d451d44d --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostInspectorTarget.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.runtime + +import com.facebook.jni.HybridData +import com.facebook.proguard.annotations.DoNotStripAny +import com.facebook.react.runtime.internal.bolts.Task +import com.facebook.soloader.SoLoader +import java.io.Closeable +import java.util.concurrent.Executor + +@DoNotStripAny +internal class ReactHostInspectorTarget(private val reactHostImpl: ReactHostImpl) : Closeable { + // fbjni looks for the exact name "mHybridData": + // https://github.com/facebookincubator/fbjni/blob/5587a7fd2b191656be9391a3832ce04c034009a5/cxx/fbjni/detail/Hybrid.h#L310 + @Suppress("NoHungarianNotation") + private val mHybridData: HybridData = + initHybrid(reactHostImpl, Task.UI_THREAD_CONDITIONAL_SYNC_EXECUTOR) + + private external fun initHybrid(reactHostImpl: ReactHostImpl, executor: Executor): HybridData + + override fun close() { + mHybridData.resetNative() + } + + private companion object { + init { + SoLoader.loadLibrary("rninstance") + } + } +} diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp new file mode 100644 index 00000000000000..eb47f4af4a327e --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.cpp @@ -0,0 +1,79 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JReactHostInspectorTarget.h" +#include +#include + +using namespace facebook::jni; +using namespace facebook::react::jsinspector_modern; + +namespace facebook::react { +JReactHostInspectorTarget::JReactHostInspectorTarget( + alias_ref reactHostImpl, + alias_ref executor) + : javaReactHostImpl_(make_global(reactHostImpl)), + javaExecutor_(make_global(executor)) { + auto& inspectorFlags = InspectorFlags::getInstance(); + if (inspectorFlags.getEnableModernCDPRegistry()) { + inspectorTarget_ = HostTarget::create( + *this, + [javaExecutor = + javaExecutor_](std::function&& callback) mutable { + auto jrunnable = + JNativeRunnable::newObjectCxxArgs(std::move(callback)); + javaExecutor->execute(jrunnable); + }); + + inspectorPageId_ = getInspectorInstance().addPage( + "React Native Bridgeless (Experimental)", + /* vm */ "", + [inspectorTargetWeak = std::weak_ptr(inspectorTarget_)]( + std::unique_ptr remote) + -> std::unique_ptr { + if (auto inspectorTarget = inspectorTargetWeak.lock()) { + return inspectorTarget->connect( + std::move(remote), + { + .integrationName = "Android Bridgeless (ReactHostImpl)", + }); + } + // Reject the connection. + return nullptr; + }, + {.nativePageReloads = true}); + } +} + +JReactHostInspectorTarget::~JReactHostInspectorTarget() { + if (inspectorPageId_.has_value()) { + getInspectorInstance().removePage(*inspectorPageId_); + } +} + +local_ref +JReactHostInspectorTarget::initHybrid( + alias_ref self, + jni::alias_ref reactHostImpl, + jni::alias_ref executor) { + return makeCxxInstance(reactHostImpl, executor); +} + +void JReactHostInspectorTarget::registerNatives() { + registerHybrid({ + makeNativeMethod("initHybrid", JReactHostInspectorTarget::initHybrid), + }); +} + +void JReactHostInspectorTarget::onReload(const PageReloadRequest& request) { + javaReactHostImpl_->reload("CDP Page.reload"); +} + +HostTarget* JReactHostInspectorTarget::getInspectorTarget() { + return inspectorTarget_ ? inspectorTarget_.get() : nullptr; +} +} // namespace facebook::react diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h new file mode 100644 index 00000000000000..d4fc38364d1243 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactHostInspectorTarget.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook::react { + +struct JTaskInterface : public jni::JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/interfaces/TaskInterface;"; +}; + +struct JReactHostImpl : public jni::JavaClass { + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/runtime/ReactHostImpl;"; + + jni::local_ref reload(const std::string& reason) { + static auto method = + javaClassStatic()->getMethod( + "reload"); + return method(self(), reason); + } +}; + +class JReactHostInspectorTarget + : public jni::HybridClass, + public jsinspector_modern::HostTargetDelegate { + public: + static constexpr auto kJavaDescriptor = + "Lcom/facebook/react/runtime/ReactHostInspectorTarget;"; + + ~JReactHostInspectorTarget() override; + + static jni::local_ref initHybrid( + jni::alias_ref jThis, + jni::alias_ref reactHost, + jni::alias_ref); + + static void registerNatives(); + + void onReload(const PageReloadRequest& request) override; + + jsinspector_modern::HostTarget* getInspectorTarget(); + + private: + JReactHostInspectorTarget( + jni::alias_ref reactHostImpl, + jni::alias_ref executor); + jni::global_ref javaReactHostImpl_; + jni::global_ref javaExecutor_; + + std::shared_ptr inspectorTarget_; + std::optional inspectorPageId_; + + friend HybridBase; +}; +} // namespace facebook::react diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/OnLoad.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/OnLoad.cpp index fa091d0f312d8a..f4dcbfa9a721ee 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/OnLoad.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/OnLoad.cpp @@ -9,6 +9,7 @@ #include #include "JJSTimerExecutor.h" +#include "JReactHostInspectorTarget.h" #include "JReactInstance.h" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*unused*/) { @@ -16,5 +17,6 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* /*unused*/) { facebook::react::JReactMarker::setLogPerfMarkerIfNeeded(); facebook::react::JReactInstance::registerNatives(); facebook::react::JJSTimerExecutor::registerNatives(); + facebook::react::JReactHostInspectorTarget::registerNatives(); }); } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt index 44825dd09eae8a..e82b56d9c0ad0b 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactHostTest.kt @@ -56,6 +56,8 @@ class ReactHostTest { private lateinit var bridgelessReactContext: BridgelessReactContext private lateinit var mockedReactInstanceCtor: MockedConstruction + private lateinit var mockedReactHostInspectorTargetCtor: + MockedConstruction private lateinit var mockedDevSupportManagerCtor: MockedConstruction private lateinit var mockedBridgelessReactContextCtor: MockedConstruction private lateinit var mockedMemoryPressureRouterCtor: MockedConstruction @@ -73,6 +75,8 @@ class ReactHostTest { bridgelessReactContext = Mockito.mock(BridgelessReactContext::class.java) mockedReactInstanceCtor = Mockito.mockConstruction(ReactInstance::class.java) + mockedReactHostInspectorTargetCtor = + Mockito.mockConstruction(ReactHostInspectorTarget::class.java) mockedDevSupportManagerCtor = Mockito.mockConstruction(BridgelessDevSupportManager::class.java) mockedBridgelessReactContextCtor = Mockito.mockConstruction(BridgelessReactContext::class.java) mockedMemoryPressureRouterCtor = Mockito.mockConstruction(MemoryPressureRouter::class.java) @@ -95,6 +99,7 @@ class ReactHostTest { @After fun tearDown() { mockedReactInstanceCtor.close() + mockedReactHostInspectorTargetCtor.close() mockedDevSupportManagerCtor.close() mockedBridgelessReactContextCtor.close() mockedMemoryPressureRouterCtor.close() diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactSurfaceTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactSurfaceTest.kt index 4d224410203489..014a45abb99827 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactSurfaceTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/ReactSurfaceTest.kt @@ -12,7 +12,6 @@ import android.content.Context import android.view.View import com.facebook.react.bridge.NativeMap import com.facebook.react.common.annotations.UnstableReactNativeAPI -import com.facebook.react.fabric.ComponentFactory import com.facebook.react.interfaces.fabric.SurfaceHandler import com.facebook.react.runtime.internal.bolts.Task import com.facebook.react.uimanager.events.EventDispatcher @@ -34,7 +33,6 @@ import org.robolectric.shadows.ShadowInstrumentation @OptIn(UnstableReactNativeAPI::class) @Config(shadows = [ShadowSoLoader::class]) class ReactSurfaceTest { - private lateinit var reactHostDelegate: ReactHostDelegate private lateinit var eventDispatcher: EventDispatcher private lateinit var reactHost: ReactHostImpl private lateinit var context: Context @@ -43,12 +41,9 @@ class ReactSurfaceTest { @Before fun setUp() { - reactHostDelegate = mock(ReactHostDelegate::class.java) eventDispatcher = mock(EventDispatcher::class.java) context = Robolectric.buildActivity(Activity::class.java).create().get() - val componentFactory = Mockito.mock(ComponentFactory::class.java) - reactHost = - Mockito.spy(ReactHostImpl(context, reactHostDelegate, componentFactory, false, {}, false)) + reactHost = Mockito.mock(ReactHostImpl::class.java) Mockito.doAnswer(mockedStartSurface()) .`when`(reactHost) .startSurface(ArgumentMatchers.any(ReactSurfaceImpl::class.java)) From 11394e7c88fc09fb27e315810543cd600cabdbb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 28 Feb 2024 09:53:18 -0800 Subject: [PATCH 030/361] Register ReactInstance with modern CDP backend Summary: Changelog: [Internal] This implements the integration of `ReactInstance` with the modern CDP backend. This is the last missing piece to complete the integration of bridgeless with the modern CDP backend, and now we can test it end to end. Reviewed By: huntie Differential Revision: D51459050 fbshipit-source-id: 54e8972ee199cbcc8e5e73d7215a34f008feeaa3 --- .../facebook/react/runtime/ReactHostImpl.java | 11 ++- .../facebook/react/runtime/ReactInstance.java | 12 ++- .../jni/react/runtime/jni/JReactInstance.cpp | 22 ++++-- .../jni/react/runtime/jni/JReactInstance.h | 11 ++- .../react/runtime/ReactInstance.cpp | 73 +++++++++++++------ 5 files changed, 95 insertions(+), 34 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 93fe93ec08f1e3..e3f9a864883196 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -915,7 +915,8 @@ private Task getOrCreateReactInstanceTask() { devSupportManager, mQueueThreadExceptionHandler, mReactJsExceptionHandler, - mUseDevSupport); + mUseDevSupport, + mReactHostInspectorTarget); if (ReactFeatureFlags .unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) { @@ -1200,6 +1201,10 @@ private Task getOrCreateReloadTask(String reason) { final ReactInstance reactInstance = reactInstanceTaskUnwrapper.unwrap(task, "1: Starting reload"); + if (reactInstance != null) { + reactInstance.unregisterFromInspector(); + } + final ReactContext reactContext = mBridgelessReactContextRef.getNullable(); if (reactContext == null) { raiseSoftException(method, "ReactContext is null. Reload reason: " + reason); @@ -1373,6 +1378,10 @@ private Task getOrCreateDestroyTask(final String reason, @Nullable Excepti final ReactInstance reactInstance = reactInstanceTaskUnwrapper.unwrap(task, "1: Starting destroy"); + if (reactInstance != null) { + reactInstance.unregisterFromInspector(); + } + // Step 1: Destroy DevSupportManager if (mUseDevSupport) { log(method, "DevSupportManager cleanup"); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 37d8d44d830a4b..8f71f3ca724f23 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -114,7 +114,8 @@ final class ReactInstance { DevSupportManager devSupportManager, QueueThreadExceptionHandler exceptionHandler, ReactJsExceptionHandler reactExceptionManager, - boolean useDevSupport) { + boolean useDevSupport, + ReactHostInspectorTarget reactHostInspectorTarget) { mBridgelessReactContext = bridgelessReactContext; mDelegate = delegate; @@ -182,7 +183,8 @@ public void onHostDestroy() { jsTimerExecutor, reactExceptionManager, bindingsInstaller, - isProfiling); + isProfiling, + reactHostInspectorTarget); mJavaScriptContextHolder = new JavaScriptContextHolder(getJavaScriptContext()); @@ -463,7 +465,8 @@ private native HybridData initHybrid( JSTimerExecutor jsTimerExecutor, ReactJsExceptionHandler jReactExceptionsManager, @Nullable BindingsInstaller jBindingsInstaller, - boolean isProfiling); + boolean isProfiling, + ReactHostInspectorTarget reactHostInspectorTarget); @DoNotStrip private static native JSTimerExecutor createJSTimerExecutor(); @@ -494,6 +497,9 @@ private native HybridData initHybrid( private native void handleMemoryPressureJs(int pressureLevel); + @ThreadConfined(ThreadConfined.UI) + /* package */ native void unregisterFromInspector(); + public void handleMemoryPressure(int level) { try { handleMemoryPressureJs(level); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp index ce3bc7b613e00d..0e789a5eec57c5 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp @@ -36,7 +36,9 @@ JReactInstance::JReactInstance( jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling) noexcept { + bool isProfiling, + jni::alias_ref + jReactHostInspectorTarget) noexcept { // TODO(janzer): Lazily create runtime auto sharedJSMessageQueueThread = std::make_shared(jsMessageQueueThread); @@ -64,7 +66,8 @@ JReactInstance::JReactInstance( jsRuntimeFactory->cthis()->createJSRuntime(sharedJSMessageQueueThread), sharedJSMessageQueueThread, timerManager, - std::move(jsErrorHandlingFunc)); + std::move(jsErrorHandlingFunc), + jReactHostInspectorTarget->cthis()->getInspectorTarget()); auto bufferedRuntimeExecutor = instance_->getBufferedRuntimeExecutor(); timerManager->setRuntimeExecutor(bufferedRuntimeExecutor); @@ -115,7 +118,9 @@ jni::local_ref JReactInstance::initHybrid( jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling) { + bool isProfiling, + jni::alias_ref + jReactHostInspectorTarget) { return makeCxxInstance( jsRuntimeFactory, jsMessageQueueThread, @@ -124,7 +129,8 @@ jni::local_ref JReactInstance::initHybrid( jsTimerExecutor, jReactExceptionManager, jBindingsInstaller, - isProfiling); + isProfiling, + jReactHostInspectorTarget); } void JReactInstance::loadJSBundleFromAssets( @@ -205,6 +211,10 @@ jlong JReactInstance::getJavaScriptContext() { return (jlong)(intptr_t)instance_->getJavaScriptContext(); } +void JReactInstance::unregisterFromInspector() { + instance_->unregisterFromInspector(); +} + void JReactInstance::registerNatives() { registerHybrid({ makeNativeMethod("initHybrid", JReactInstance::initHybrid), @@ -229,14 +239,14 @@ void JReactInstance::registerNatives() { JReactInstance::getBufferedRuntimeExecutor), makeNativeMethod( "getRuntimeScheduler", JReactInstance::getRuntimeScheduler), - makeNativeMethod( "registerSegmentNative", JReactInstance::registerSegment), makeNativeMethod( "handleMemoryPressureJs", JReactInstance::handleMemoryPressureJs), makeNativeMethod( "getJavaScriptContext", JReactInstance::getJavaScriptContext), + makeNativeMethod( + "unregisterFromInspector", JReactInstance::unregisterFromInspector), }); } - } // namespace facebook::react diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h index 6a28ea50c737e1..d6552a8a97895f 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.h @@ -27,6 +27,7 @@ #include "JJSTimerExecutor.h" #include "JJavaTimerManager.h" #include "JReactExceptionManager.h" +#include "JReactHostInspectorTarget.h" namespace facebook::react { @@ -45,7 +46,9 @@ class JReactInstance : public jni::HybridClass { jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling); + bool isProfiling, + jni::alias_ref + jReactHostInspectorTarget); /* * Instantiates and returns an instance of `JSTimerExecutor`. @@ -78,6 +81,8 @@ class JReactInstance : public jni::HybridClass { void handleMemoryPressureJs(jint level); + void unregisterFromInspector(); + private: friend HybridBase; @@ -90,7 +95,9 @@ class JReactInstance : public jni::HybridClass { jni::alias_ref jsTimerExecutor, jni::alias_ref jReactExceptionManager, jni::alias_ref jBindingsInstaller, - bool isProfiling) noexcept; + bool isProfiling, + jni::alias_ref + jReactHostInspectorTarget) noexcept; jni::alias_ref getJSCallInvokerHolder(); jni::alias_ref diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 09e97cfb5caa93..c2ade6b2e7c36c 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -7,6 +7,7 @@ #include "ReactInstance.h" +#include #include #include #include @@ -15,11 +16,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include @@ -37,16 +40,13 @@ ReactInstance::ReactInstance( jsErrorHandler_(jsErrorHandlingFunc), hasFatalJsError_(std::make_shared(false)), parentInspectorTarget_(parentInspectorTarget) { - auto runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), - weakTimerManager = - std::weak_ptr(timerManager_), - weakJsMessageQueueThread = - std::weak_ptr( - jsMessageQueueThread_), - weakHasFatalJsError = - std::weak_ptr(hasFatalJsError_)]( - std::function&& - callback) { + RuntimeExecutor runtimeExecutor = [weakRuntime = std::weak_ptr(runtime_), + weakTimerManager = + std::weak_ptr(timerManager_), + weakJsMessageQueueThread = + std::weak_ptr(jsMessageQueueThread_), + weakHasFatalJsError = std::weak_ptr( + hasFatalJsError_)](auto callback) { if (std::shared_ptr sharedHasFatalJsError = weakHasFatalJsError.lock()) { if (*sharedHasFatalJsError) { @@ -85,13 +85,40 @@ ReactInstance::ReactInstance( }; if (parentInspectorTarget_) { - inspectorTarget_ = &parentInspectorTarget_->registerInstance(*this); - runtimeInspectorTarget_ = - &inspectorTarget_->registerRuntime(*runtime_, runtimeExecutor); + auto executor = parentInspectorTarget_->executorFromThis(); + + auto runtimeExecutorThatWaitsForInspectorSetup = + std::make_shared(runtimeExecutor); + + // This code can execute from any thread, so we need to make sure we set up + // the inspector logic in the right one. The callback executes immediately + // if we are already in the right thread. + executor([this, runtimeExecutor, runtimeExecutorThatWaitsForInspectorSetup]( + jsinspector_modern::HostTarget& hostTarget) { + // Callbacks scheduled through the page target executor are generally + // not guaranteed to run (e.g.: if the page target is destroyed) + // but in this case it is because the page target cannot be destroyed + // before the instance finishes its setup: + // * On iOS it's because we do the setup synchronously. + // * On Android it's because we explicitly wait for the instance + // creation task to finish before starting the destruction. + inspectorTarget_ = &hostTarget.registerInstance(*this); + runtimeInspectorTarget_ = + &inspectorTarget_->registerRuntime(*runtime_, runtimeExecutor); + runtimeExecutorThatWaitsForInspectorSetup->flush(); + }); + + // We decorate the runtime executor used everywhere else to wait for the + // inspector to finish its setup. + runtimeExecutor = + [runtimeExecutorThatWaitsForInspectorSetup]( + std::function&& callback) { + runtimeExecutorThatWaitsForInspectorSetup->execute( + std::move(callback)); + }; } - runtimeScheduler_ = - std::make_shared(std::move(runtimeExecutor)); + runtimeScheduler_ = std::make_shared(runtimeExecutor); auto pipedRuntimeExecutor = [runtimeScheduler = runtimeScheduler_.get()]( @@ -104,13 +131,15 @@ ReactInstance::ReactInstance( } void ReactInstance::unregisterFromInspector() { - if (inspectorTarget_) { - assert(runtimeInspectorTarget_); - inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_); - assert(parentInspectorTarget_); - parentInspectorTarget_->unregisterInstance(*inspectorTarget_); - inspectorTarget_ = nullptr; - } + assert(inspectorTarget_); + + assert(runtimeInspectorTarget_); + inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_); + + assert(parentInspectorTarget_); + parentInspectorTarget_->unregisterInstance(*inspectorTarget_); + + inspectorTarget_ = nullptr; } RuntimeExecutor ReactInstance::getUnbufferedRuntimeExecutor() noexcept { From 798903a3a2b7de8d9360314810b666073bf76b06 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 09:53:21 -0800 Subject: [PATCH 031/361] Mark ViewGroupManager.getChildAt() as Nullable Summary: ViewGroup.getChildAt() is nullable, we should make ViewGroupManager.getChildAt() as well. see https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewGroup.java#6939 changelog: [internal] internal Reviewed By: javache Differential Revision: D54271529 fbshipit-source-id: 10170031ec560d3f2956474e3a82ffe41bc5dc36 --- .../facebook/react/uimanager/IViewGroupManager.java | 2 ++ .../com/facebook/react/uimanager/ViewGroupManager.java | 1 + .../react/views/view/ReactClippingViewManager.java | 10 +++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/IViewGroupManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/IViewGroupManager.java index 2c73196899a8e5..f505c24150c908 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/IViewGroupManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/IViewGroupManager.java @@ -8,6 +8,7 @@ package com.facebook.react.uimanager; import android.view.View; +import androidx.annotation.Nullable; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.UiThreadUtil; @@ -19,6 +20,7 @@ public interface IViewGroupManager extends IViewManagerWithChild void addView(T parent, View child, int index); /** @return child of the parent view at the index specified as a parameter. */ + @Nullable View getChildAt(T parent, int index); /** Removes View from the parent View at the index specified as a parameter. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java index 52907b218c6b9f..06fa73b93854b1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewGroupManager.java @@ -69,6 +69,7 @@ public int getChildCount(T parent) { } @Override + @Nullable public View getChildAt(T parent, int index) { return parent.getChildAt(index); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.java index 25621c3700897a..525183053a0ef0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactClippingViewManager.java @@ -8,6 +8,7 @@ package com.facebook.react.views.view; import android.view.View; +import androidx.annotation.Nullable; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.uimanager.ViewGroupManager; @@ -52,6 +53,7 @@ public int getChildCount(T parent) { } @Override + @Nullable public View getChildAt(T parent, int index) { boolean removeClippedSubviews = parent.getRemoveClippedSubviews(); if (removeClippedSubviews) { @@ -68,10 +70,12 @@ public void removeViewAt(T parent, int index) { boolean removeClippedSubviews = parent.getRemoveClippedSubviews(); if (removeClippedSubviews) { View child = getChildAt(parent, index); - if (child.getParent() != null) { - parent.removeView(child); + if (child != null) { + if (child.getParent() != null) { + parent.removeView(child); + } + parent.removeViewWithSubviewClippingEnabled(child); } - parent.removeViewWithSubviewClippingEnabled(child); } else { parent.removeViewAt(index); } From 7cfd686214c378349e64cbd10521d7e1a4abbed3 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 28 Feb 2024 10:03:15 -0800 Subject: [PATCH 032/361] Use standard (lowercase) `assert` in ReactInstanceIntegrationTest Summary: Changelog: [Internal] TSIA; `ASSERT` isn't universally defined so let's switch to `assert`. bypass-github-export-checks Reviewed By: huntie Differential Revision: D54305583 fbshipit-source-id: ee80b462f1372e53301f1bb66eb589e4f7da89c6 --- .../tests/ReactInstanceIntegrationTest.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h index b95500f609c382..34710c6d5c9c52 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h @@ -7,15 +7,17 @@ #pragma once +#include "InspectorMocks.h" +#include "ReactNativeMocks.h" +#include "UniquePtrFactory.h" + #include #include #include #include -#include -#include "InspectorMocks.h" -#include "ReactNativeMocks.h" -#include "UniquePtrFactory.h" +#include +#include namespace facebook::react::jsinspector_modern { @@ -49,7 +51,7 @@ class ReactInstanceIntegrationTest : public Test { MockRemoteConnection& getRemoteConnection() { EXPECT_EQ(mockRemoteConnections_.objectsVended(), 1); auto rawPtr = mockRemoteConnections_[0]; - ASSERT(rawPtr != nullptr); + assert(rawPtr); return *rawPtr; } From 659712b475025bda1a534bf3db094e77411b2014 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 28 Feb 2024 11:33:54 -0800 Subject: [PATCH 033/361] Destroy SessionState only after destroying HostAgent Summary: Changelog: [Internal] Fixes a bug detected by LeakSanitizer: `HostAgent`'s destructor writes to session state, but when the containing `HostTargetSession` is being torn down, the `SessionState` object currently gets destroyed first, resulting in a dangling reference. Reordering the members of `HostTargetSession` results in the correct destruction order. bypass-github-export-checks Reviewed By: robhogan Differential Revision: D54305545 fbshipit-source-id: e91a6f3de5eed327b811524548d01565e26234fa --- .../ReactCommon/jsinspector-modern/HostTarget.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp index f5e95824412a6b..4817e4d575754c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp @@ -95,8 +95,10 @@ class HostTargetSession { // Owned by this instance, but shared (weakly) with the frontend channel std::shared_ptr remote_; FrontendChannel frontendChannel_; - HostAgent hostAgent_; SessionState state_; + + // NOTE: hostAgent_ has a raw reference to state_ so must be destroyed first. + HostAgent hostAgent_; }; std::shared_ptr HostTarget::create( From 32c74fbc594b9eeb9198e0bedc9f710c0a0a7d40 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 28 Feb 2024 11:55:14 -0800 Subject: [PATCH 034/361] Explicitly init InspectorFlags::inconsistentFlagsStateLogged_ to avoid UB Summary: Changelog: [Internal] TSIA (bug found by UBSAN) bypass-github-export-checks Reviewed By: huntie Differential Revision: D54305549 fbshipit-source-id: e9c69d7922337c77d4503c5862637040a885eb0e --- .../ReactCommon/jsinspector-modern/InspectorFlags.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h index 74ec341be42f10..596f98d1344d98 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h @@ -45,7 +45,7 @@ class InspectorFlags { bool enableModernCDPRegistry_; bool enableCxxInspectorPackagerConnection_; - mutable bool inconsistentFlagsStateLogged_; + mutable bool inconsistentFlagsStateLogged_{false}; void assertFlagsMatchUpstream() const; }; From 252ef19c8d5bc5392d900af21136b351723f3b3c Mon Sep 17 00:00:00 2001 From: David Rickard Date: Wed, 28 Feb 2024 12:26:14 -0800 Subject: [PATCH 035/361] Allow partially visible items to be picked as scroll anchors for maintainVisibleContentPosition Summary: The current behavior for `maintainVisibleContentPosition` on ScrollView is to pick the first fully visible item as the scroll anchor. This has a number of disadvantages: * It causes problems for lists with loading indicators and large items. The loading glimmer can be picked as the anchor and pull the scroll down too quickly. This is the case for Marketplace. * It's inconsistent with the [CSS Scroll Anchoring](https://www.w3.org/TR/css-scroll-anchoring-1/) behavior, which is to pick the first partially visible view. This change will switch to picking the first partially visible view as the anchor, to align with the CSS implementation. Discussed the change with yungsters, NickGerleman, and cipolleschi and agreed about the change in behavior. This also enables `maintainVisibleContentPosition` for Android. After adding it to `validAttributes` for Android it appears to be working well. Previously it was not functional at all on Android, as the property change from React was not passed to ReactScrollViewManager.java. ## Changelog: [General] [Changed] - maintainVisibleContentPosition property on ScrollView now selects the first partially visible view as the anchor, rather than the first fully visible view. Reviewed By: NickGerleman Differential Revision: D54223244 fbshipit-source-id: 05ddfc0bbf16d61f9599b9d8066c0bd21b086301 --- .../Components/ScrollView/ScrollView.js | 54 +++++++++---------- .../ScrollView/ScrollViewNativeComponent.js | 1 + .../ScrollView/RCTScrollViewComponentView.mm | 6 +-- .../React/Views/ScrollView/RCTScrollView.m | 6 +-- .../MaintainVisibleScrollPositionHelper.java | 9 +++- 5 files changed, 42 insertions(+), 34 deletions(-) diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js index 8d73e00a609496..aab9f20baf2112 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -266,33 +266,6 @@ type IOSProps = $ReadOnly<{| * @platform ios */ canCancelContentTouches?: ?boolean, - /** - * When set, the scroll view will adjust the scroll position so that the first child that is - * currently visible and at or beyond `minIndexForVisible` will not change position. This is - * useful for lists that are loading content in both directions, e.g. a chat thread, where new - * messages coming in might otherwise cause the scroll position to jump. A value of 0 is common, - * but other values such as 1 can be used to skip loading spinners or other content that should - * not maintain position. - * - * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll - * to the top after making the adjustment if the user was within the threshold of the top before - * the adjustment was made. This is also useful for chat-like applications where you want to see - * new messages scroll into place, but not if the user has scrolled up a ways and it would be - * disruptive to scroll a bunch. - * - * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause - * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, - * don't re-order the content of any ScrollViews or Lists that use this feature. - * - * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute - * visibility. Occlusion, transforms, and other complexity won't be taken into account as to - * whether content is "visible" or not. - * - */ - maintainVisibleContentPosition?: ?$ReadOnly<{| - minIndexForVisible: number, - autoscrollToTopThreshold?: ?number, - |}>, /** * The maximum allowed zoom scale. The default value is 1.0. * @platform ios @@ -505,6 +478,33 @@ export type Props = $ReadOnly<{| * - `true`, deprecated, use 'always' instead */ keyboardShouldPersistTaps?: ?('always' | 'never' | 'handled' | true | false), + /** + * When set, the scroll view will adjust the scroll position so that the first child that is + * partially or fully visible and at or beyond `minIndexForVisible` will not change position. + * This is useful for lists that are loading content in both directions, e.g. a chat thread, + * where new messages coming in might otherwise cause the scroll position to jump. A value of 0 + * is common, but other values such as 1 can be used to skip loading spinners or other content + * that should not maintain position. + * + * The optional `autoscrollToTopThreshold` can be used to make the content automatically scroll + * to the top after making the adjustment if the user was within the threshold of the top before + * the adjustment was made. This is also useful for chat-like applications where you want to see + * new messages scroll into place, but not if the user has scrolled up a ways and it would be + * disruptive to scroll a bunch. + * + * Caveat 1: Reordering elements in the scrollview with this enabled will probably cause + * jumpiness and jank. It can be fixed, but there are currently no plans to do so. For now, + * don't re-order the content of any ScrollViews or Lists that use this feature. + * + * Caveat 2: This simply uses `contentOffset` and `frame.origin` in native code to compute + * visibility. Occlusion, transforms, and other complexity won't be taken into account as to + * whether content is "visible" or not. + * + */ + maintainVisibleContentPosition?: ?$ReadOnly<{| + minIndexForVisible: number, + autoscrollToTopThreshold?: ?number, + |}>, /** * Called when the momentum scroll starts (scroll which occurs as the ScrollView glides to a stop). */ diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 69ebcef0d56971..50d95a9de87f1e 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -46,6 +46,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = }, decelerationRate: true, disableIntervalMomentum: true, + maintainVisibleContentPosition: true, pagingEnabled: true, scrollEnabled: true, showsVerticalScrollIndicator: true, diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 90a9a134dcea72..265ad7a922b43f 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -752,13 +752,13 @@ - (void)_prepareForMaintainVisibleScrollPosition BOOL horizontal = _scrollView.contentSize.width > self.frame.size.width; int minIdx = props.maintainVisibleContentPosition.value().minIndexForVisible; for (NSUInteger ii = minIdx; ii < _contentView.subviews.count; ++ii) { - // Find the first entirely visible view. + // Find the first view that is partially or fully visible. UIView *subview = _contentView.subviews[ii]; BOOL hasNewView = NO; if (horizontal) { - hasNewView = subview.frame.origin.x > _scrollView.contentOffset.x; + hasNewView = subview.frame.origin.x + subview.frame.size.width > _scrollView.contentOffset.x; } else { - hasNewView = subview.frame.origin.y > _scrollView.contentOffset.y; + hasNewView = subview.frame.origin.y + subview.frame.size.height > _scrollView.contentOffset.y; } if (hasNewView || ii == _contentView.subviews.count - 1) { _prevFirstVisibleFrame = subview.frame; diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollView.m b/packages/react-native/React/Views/ScrollView/RCTScrollView.m index 1aead514ac3fa5..7dd55cf33487b6 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollView.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollView.m @@ -939,19 +939,19 @@ - (void)uiManagerWillPerformMounting:(RCTUIManager *)manager BOOL horz = [self isHorizontal:self->_scrollView]; NSUInteger minIdx = [self->_maintainVisibleContentPosition[@"minIndexForVisible"] integerValue]; for (NSUInteger ii = minIdx; ii < self->_contentView.subviews.count; ++ii) { - // Find the first entirely visible view. This must be done after we update the content offset + // Find the first partially or fully visible view. This must be done after we update the content offset // or it will tend to grab rows that were made visible by the shift in position UIView *subview = self->_contentView.subviews[ii]; BOOL hasNewView = NO; if (horz) { CGFloat leftInset = self.inverted ? self->_scrollView.contentInset.right : self->_scrollView.contentInset.left; CGFloat x = self->_scrollView.contentOffset.x + leftInset; - hasNewView = subview.frame.origin.x > x; + hasNewView = subview.frame.origin.x + subview.frame.size.width > x; } else { CGFloat bottomInset = self.inverted ? self->_scrollView.contentInset.top : self->_scrollView.contentInset.bottom; CGFloat y = self->_scrollView.contentOffset.y + bottomInset; - hasNewView = subview.frame.origin.y > y; + hasNewView = subview.frame.origin.y + subview.frame.size.height > y; } if (hasNewView || ii == self->_contentView.subviews.count - 1) { self->_prevFirstVisibleFrame = subview.frame; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java index 7839dcd80064a9..20ab0d71a47b83 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java @@ -34,6 +34,7 @@ @Nullsafe(Nullsafe.Mode.LOCAL) class MaintainVisibleScrollPositionHelper implements UIManagerListener { + private final ScrollViewT mScrollView; private final boolean mHorizontal; private @Nullable Config mConfig; @@ -42,6 +43,7 @@ class MaintainVisibleScrollPositionHelper currentScroll || i == contentView.getChildCount() - 1) { mFirstVisibleView = new WeakReference<>(child); Rect frame = new Rect(); From e1b0914e094a7fd119e54575c5c0ff06008ada22 Mon Sep 17 00:00:00 2001 From: David Vacca Date: Wed, 28 Feb 2024 17:45:27 -0800 Subject: [PATCH 036/361] Mark UIManagerModuleConstantsHelper.normalizeEventTypes as Nullable Summary: Mark UIManagerModuleConstantsHelper.normalizeEventTypes as Nullable changelog: [internal] internal Reviewed By: arushikesarwani94 Differential Revision: D54327799 fbshipit-source-id: 66dd42c8ed220e76c62e3d215c59d6547c374265 --- .../react/uimanager/UIManagerModuleConstantsHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java index 4aa4c3900968f9..4a246040c3152b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/UIManagerModuleConstantsHelper.java @@ -180,7 +180,7 @@ private static void validateDirectEventNames( } @VisibleForTesting - /* package */ static void normalizeEventTypes(Map events) { + /* package */ static void normalizeEventTypes(@Nullable Map events) { if (events == null) { return; } From 6204ea36d321c9e27757d5f36ff7e74fa68c54d5 Mon Sep 17 00:00:00 2001 From: Biki-das Date: Thu, 29 Feb 2024 02:38:46 -0800 Subject: [PATCH 037/361] - fixes component unmounting behaviour in itemSeperatorComponent (#43223) Summary: Reopen in reference to https://github.com/facebook/react-native/issues/42435 , as it had a lot of commits and fixes making it messed up. Weirdly when using a [Section List](https://reactnative.dev/docs/sectionlist) specifically when using the [SectionSeperatorComponent](https://reactnative.dev/docs/sectionlist#sectionseparatorcomponent), and adding additional Data on the renderItem List, there is a unmount occurring as the new Data is added, this only happens while using the `SectionSeparatorComponent` and limited to the same **Here is the Current Behaviour** https://github.com/facebook/react-native/assets/72331432/0622e789-ddbc-4038-8ccc-a421050eecbf **Here is the Expected Behaviour After Fixes** https://github.com/facebook/react-native/assets/72331432/2f0cc3a9-da97-43f5-8a4b-3faca74ae834 The issues is happening because the Parent View gets removed, as we add Data, the separator moves causing the unmount, the solution that i proposed here is to conditionally render to make sure that our separator renders correctly which required to add an empty view as the `itemSeparatorComponent`. ## Changelog: [General] [Added] - Fixes SectionList Unmounting issue with separatorComponent on data addition and removal. Pull Request resolved: https://github.com/facebook/react-native/pull/43223 Test Plan: i used the `rn-tester` App to test out the changes below is the code to test the same. Update the snapshots to align with the changes. ``` import React, {useEffect, useState} from 'react'; import { StyleSheet, Text, View, SafeAreaView, StatusBar, SectionList, Image, } from 'react-native'; interface Item { id: string; title: string; imgSrc: string; } interface Section { title: string; data: Item[]; } const keyExtractor = (item: Item, index: number) => `${item.title}-${index}`; const renderItem = ({item, index}: {item: Item; index: number}) => { return ; }; const additionalFruits = [ { id: '7', title: 'Sandwich', imgSrc: 'https://img.freepik.com/premium-vector/sanwich-vector-isolated-fast-food_484148-2.jpg', }, { id: '8', title: 'Burger', imgSrc: 'https://static.vecteezy.com/system/resources/thumbnails/033/494/666/original/animated-illustration-of-burger-cartoon-for-foods-menu-animation-free-video.jpg', }, { id: '9', title: 'Juice', imgSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQHg9yLXE7Jlq4OM9ey64TW4D9qUFaeGU76rg&usqp=CAU', }, { id: '10', title: 'Milkshake', imgSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcROpBez3eZKvEVdxBce9XyG6j6caDFMjV_xUQ&usqp=CAU', }, ]; const DATA: Section[] = [ { title: 'Items', data: [ { id: '1', title: 'Cake', imgSrc: 'https://static.vecteezy.com/system/resources/previews/012/132/227/original/cute-cake-cartoon-icon-illustration-food-recreation-icon-concept-isolated-premium-flat-cartoon-style-vector.jpg', }, { id: '2', title: 'Pizza', imgSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR2kYjlsayzKZx4hFo6fbH7S8pde2JRo2a0hfaeoz3O7bjqdJjhI0tFiSROM8G4UbdbwXU&usqp=CAU', }, { id: '3', title: 'Coke', imgSrc: 'https://png.pngtree.com/png-clipart/20220116/original/pngtree-cartoon-hand-painted-coke-bottle-png-image_7106844.png', }, { id: '4', title: 'Noodles', imgSrc: 'https://thumbs.dreamstime.com/z/cute-cartoon-vector-bowl-noodle-isolated-white-background-115120959.jpg', }, { id: '5', title: 'Pasta', imgSrc: 'https://t4.ftcdn.net/jpg/02/65/00/69/360_F_265006936_2dlz2VtcqZZUbco1VnDpU2diyd8OagFS.jpg', }, { id: '6', title: 'Fries', imgSrc: 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxISEBUQEBAVFRMTERkVFRISDw8PEBIVFRcWFhcSFRYYHSggGBolGxgVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OGxAQGismICYwLS4vLS0tLS0tLTUvLS0tLS0tLS0vLS0tLS0tLy0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAOMA3gMBIgACEQEDEQH/xAAcAAEAAgMBAQEAAAAAAAAAAAAABQYCBAcDAQj/xABEEAACAQIBBwgEDAUEAwAAAAAAAQIDEQQFEiExQVGRBhMiYXGBscFSkqHRBxcjMkJygrLC0uHwJDNiY6IUNFPxFUOT/8QAGwEBAAIDAQEAAAAAAAAAAAAAAAQFAQIDBgf/xAAzEQACAQICBwcDBAMBAAAAAAAAAQIDEQQhBRIxQVFhkRNxgaGx0fAUIuEVI2LBJDLxBv/aAAwDAQACEQMRAD8A7iAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYZ63riYuDMHxHji62ZByMVJKEXKWxGUruyPcGjhsoQm1FtKbTtFvXbXbebxrSqwqx1oO6EouLswADoYAAAAAAAAAAAAAAAAAAAAAAAAAAAABq4nFZjStfRfXY51asKUdabsjMYuTsjaILKVFZ0otaJL2PX5m9QylCdTmrNSzc7TazV7aGYZYp9FS3Oz7H+viV2kVDEYZzhnq5+/kd6N4VEnv+IrfJzGOjiOZk+jN5vUpfRl36u9FnyvLoLrfkyl5bp2mqi0X2rZJanw8Cw4jKCq0aM9s02/rRspLjcraGK/w6tN7ll4tJ+vmTq9LWqQqLft7188iFyhP5ehb/kX3ol8Od46pfE0ktjg+/P8A0RboZUfO06Uo/wAzOtJO1nFX0o6aHxMIJwltbVjXG05OMLbk/VslgYTnZNvYrkDlDK06UHNNN3Vk0rPTpXC5c4nGU8O0p3z4ECnSlUdolhBhTldJrar8TMlHIAAAAAAAAAAAAAAAAAAAAAGKknqZqY+epX62V/A5SccbKP0ZLMt1xTafHO4kCrj4wrKm1lvd9h3p4eU4uS3K5bSOyqvmvtXgamUcqukoye2ola2y95ey/E3sqroJ7mcsTXhiMNU1N1n5p/0ZhCUJRb3kG6mZiaEt8nB/asl4kzlGs/maLNad+kreXJNQjJa41E1wb8iVxuITk57LJ91kVFPFOGGlBPa15p39LeJLnT1nF8n6/kr+Mq85zlO3zW3D7Ozx4mjhcQ83Mvoi3JdTla/gj3yY71HJ7m+9tEfPoVJLYm+Gsrm7NpcCzhFf68MyZyZk2VSp/qKzsk06cdTlm6py6ty2+O9HFRli6MYu7hUafere888jYzncPCT1pZsu2Ojws+81cHG2Ph11E+Kv7yTh2lVhHmvVEaSlJz1tyeRcco10oON9L0FUytJSnTpN2Td5Pcm7X4ZxJ4qtd6e3iVrHVr1KkvQi0u22b4tm2Lxnb1dfcti+cbnLCUdX54HRKVeDgpxknBq6kmnG3aeeJxShG+u+q20qHJnEy5iVNvoqpdcNKXVezMMp4+UalovRGLbWxtq/u4llV0xJq0I5tbeD395w+gtUcb7PQ9sPyqqqu4SipwlUzUklGSu7LNe3v4l2OZ8lMNzmMp7oXm/srR/lmnTCZoqdWdJym287K/dnn3mNIU6dOajBWyz/AKAALMrwAAAAAAAAAAAAAACOyrDQpdz8isY75OvTrbG7Pq0WvwfsLnWp50XF7UVTKNHOhKD17OqSPNaWpdnWVRbJeqy9LFjgp5WfxM1uUKbUJbm1xt7iy85n4WM99OD79F/MrVSXO4a+1Rv3x1+D4kvkPEKeCtfTC8Xxzl7GjTR801Vg98X5f9OmIi1Tjyl6kXlr+V2SXu8zCdb+Gv8A27cVYzyy/kn2rxNKd5UKdNa5yjFcf0KpvJd5KhH7V3mvkypZu/V5kdleXTnZ7Pwot2HyVQpQbm77XJtxXckVvlDToaZUs/ObtpazHo2Jq+w3dFqTndHajWjOpkn32yPTkfXdqkNmiS7XofguBJOWZjKE98lHi838RFcmYNRuk25S2LYlb3m3liXRjOL+bJNNePFIwp9nWjLg15CpG9VrjddVYlMRWteWxK/BFcqP5GT2zml220+NzYxGNvRenTJ+yTu/Mzo0LypQeqN5vut5sjXtlz9MzNOOorv5YlMDTVKkovYry7dbIPFVG4SqPXUnZdi6T/CiSytXtTzVrk7d233d5A4xylUp0IvctGxzelnenmKMbvWfy2fsWvk1hI0qfOuVpzjdu9lGOtLwbJ3JGUuelNR0wgl03tbvoXVoK7lqtm01BbX/AIx/aLHyfwfNUIprpS6cu16l3KyLvRTnKpZPJLP5zeZV4pJwdSW1vL5yRKgA9EVoAAAAAAAAAAAAAABpV8U4ysrWRCY/EwlWko/OUU5Ldf8Aa4m9jm4zd1r0p7yjyxU41nOXzs55y8YnlcfXnUcqUtz2cPi8mWuEoKX3Lh1JvDdGc4bJfKLv0SXG3E1Mk4t0as6X0al423P6Ev3vMqldPMqxejOs+yWiz7HY8MbG2Ipy9Jx4ppeFirpVZRldbc/RomqKd1LevNG3luXyX2l4M0cnV86tQp+i87xa8GbWW38mvr+TIrITvjF/TB/dt5mYZo2gv2m+8sOX61qaj6UvYv1sVHKM9Nty8SwZdqXqKO6Ptb/6K/lJdP7KN5S2I3wkbJFvVCMcKqdHQnSTutcrq7b7fMg6M86nOnuV4+NuPiS+T694Zno6uwhsQubxHU37Jft8DlVlrJrxOdFPOPiRc3nSpxerOu+taPK5Y8O7zk9yUV95+KITm7VGt0nb2krh5ZlLOe5y9y4WRxrPJW+XJFXNKx4Yipn1uqGjvX6+BrZCjzmMc9kc6X4Y+N+4xc8yjKe2Wrv0LzZIcjMP0ZTf0pW7oq/i3wJMVaPka1Ptpyfh7knQo8/jYwemMPnbrR6Vu9tIu5WcZjo0Y3zdb0JWjd67mzyfx1Ss5SkkqcdC1tuWvX1LxL/RdaMP2krt538PQpcTGU4qexLInQAXpAAAAAAAAAAAAAAAANfFYdTjZ69j3MofKLAtNztaUdE14S/fUX3FqXNzzHaWY817pWdnxOUYnL+JqPp1U9FtMKS0btESi0vRi3GS/wBvJrnzV8snw4FzomhVquTi1ZW23334J8D0w+JzU4v5slp6nskjerVtFN7qkbPcm1+hX6WItJOWmN1ddW32G5UrOClCT1PQ9zi78HYoqlFpplxVw7jJX3k9lv8Alr6/kzR5NU/4ipL0YW75ZvuZM43CZ2HnUldWpupFandRb0kfybh0ak/Skl6sV72c4pxhmQozTpSS7jHKUr133eCI3FYaVSvGnG2dJJK7stulm9jn/EPtX3UfMEv42m90G/ZMxf713HWL1YXXAka2DjQlCbq3bTjmKOluTjpvfUrI0Msq86e9u3tXvNrlBPp0n1vxiRmKxGfiacY6k03xbt7DFTOSaW5mlFN2k+ZjUjfENb5G3lSdoKK+k7dy/aNWH+5+2/BkbyoyjKNWMIStmRu9CfSenb1W4nOnTdSpGK4XJNKk6tSMVwueuWKls2mtiv5LzLXyeo5lKMfRWntbu/M5hWylVc87O6StpzVrXcK3KrGU7KFe19L6FJ+MSyWEm7JNefsd62jqkoaqcfP2Oj5UnKrXVKGlpqKX9T1+XAu2AwqpU4046orXve197OPfBtlTE18pQU6zlFRnOacIaVmta0tHSlE7WX2jMN2cXN7Xl4flnndKQlRlGi3sV8vEAAtCrAAAAAAAAAAAAAAABxTK1Hm61Wn6FWUe5SaXsO1nI+XdHMxtTdLNkvtRV/amVuk43hGXB+qL/wD8/L96cOKv0fsyDlImsi4iLq0ZySdpxhJNXWnown4d8SvuR9o4hwd12NbGtxS6qkeoxGH7Wm47zq2PrRzZQ1uUXF22XVir5Lqyo1HQnqbvF7L9Xb4o8clcoaclm1ZZstkpan2vf1m9j8Oq0M6DTlHTGUWnfquiHUvnGew84qEsO3TqK1/lzUxUvl39ZeCPbB/7qL/tvz95HUqzlNOWvOV9mnUSeDj8vnbqT9sl+pFl9slfgztNWi1yGX5dOn3+KIvJ3SxTfo39izfM2sr1b1lujH3v3EZkzKNOlKc6ktNrJLpSbbu7cNpsk5Qeqru3qb0oSdO0Vd29Tbq4qNOpKpLVFydtrelJLtZUsXXcpSqS+c22+1mxlDGurJvVG7aj27X1kbWlptuLPD0OzV3taLrC4fso3e1+XIwNHGPpdiN0jqzvJ9pNhtO09h0b4EsNfEV6uyFFQ9eSl+A7Ec5+BbC2wlWrb59ZRvvUIR08ZS4HRi5wytTR4PS09fGT5WXRe9wADuVwAAAAAAAAAAAAAAAObfCnQtVpVfSp5vqSv+M6SUz4T8PfCRqL/wBdVX+rJNeOaRcZHWoy69Cz0NU1MbDnddVZedjlzkYOQcjC5Qn0BINn2E5LSm+1Npny58NrGT1WKmndTlffzkr+J6f+Tr/81TuqVF5msfDVwi9qXQ01I8F0M6laUneUm3vlJyftMDEXNjKyVj5OVkazZlUldmBukYYbI5G7Xdos06cG5RjFXblZJa23oSOsDlLaj9A/BvguZyZQT1yi6j+221/i4loNXJ2EVKjTpLVTpxguyMVHyNovIq0Uj5vWqdpUlN7231YABscwAAAAAAAAAAAAAAAQ/KnB87g69NK7dJuK/qh04+2KJg+MxKKknF7zenN05qcdqafQ/O20+NkjyjwPMYqtRSsozeb9WWmH+LRGnmrNOzPp0ZqcVKOx2a7nmj4AfLgyBcHy4APKrPYfZzseLNkjDADZ8ubGDwxctCXWS3ILA89lLDwtdKopy3Wppz0+ql3kJiJXl2HSfgUyZ8rXxTWiMFTi9nTec+9KMfWJWHjrSSK3SVbssPUlyt1yR10AFweBAAAAAAAAAAAAAAAAAAAAAOXfCvk7Nq0sQlonHm5bs6Oni4t+oUK523lvk3n8FVileUFzkd94aWl2xzl3nEeopcbT1at+OZ7nQOI7XCKL2xy8Nq9vA+ny5g5GLqESxcnoecqh5ymY3MpGGw2LmINzUCTsrg8sTLRbeErsw3Y1us/QXwdZL/0+T6UWrSqLnpbHepa1+tQUF3HE+SuSv9VjKNG3RlVTlr0Qh0pdnRT4o/SSVtCLLBwzcjy+n69lCiu9+i/vyMgATzzIAAAAAAAAAAAAAAAAAAAAB8scA5X5NeGxdWl9HPzobsyXSjbsTt9ln6AK7yh5JYbGTjUrZ6lGGZenKKvFNtJ3TvZt8WRsTQdWKttRa6Jx8cJVbnfVas7Z93t3M4PcXOy/Flgd9b16f5D58WOB31vXp/kIP0VTl1PQfr+D/l0/JxkHZviywO+t69P8g+LLA763r0/yD6Kpy6j9ewn8un5OMg7N8WWB31vXp/kHxZYHfW9en+QfRVOXUfr2E/l0/Jxo0687vs0HcfiywO+t69P8h5fFVgPSrf8A1h+Q2jg6nI1lp7CPZrdPyQfwLZH/AJuMkv7UPZKb+4r9p1cjsiZJpYWhGhRTzIX+c86Tcm5Nt7XdkiWNKGpBI8tjcR9RXlU3PZ3LYAAdCKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/Z', }, ], }, ]; const ItemComponent = ({item, index}: {item: Item; index: number}) => { useEffect(() => { console.log('Mount of', index, item.title); return () => { console.log('Unmount of', index, item.title); }; }, []); return ( {item.title} ); }; const App = () => { const [data, setData] = useState(DATA); const fetchNextPage = () => { const newInnerData = [...data[0].data, ...additionalFruits]; setData([{...data[0], data: newInnerData}]); }; return ( } renderSectionHeader={({section}) => ( {section.title} )} /> ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#F5F5F5', paddingTop: StatusBar.currentHeight, }, scrollView: { paddingHorizontal: 16, }, card: { backgroundColor: '#FFFFFF', flexDirection: 'row', alignItems: 'center', justifyContent: 'center', gap: 8, height: 200, padding: 16, borderRadius: 8, marginBottom: 16, borderWidth: 1, }, cardText: { fontSize: 30, }, headerText: { fontSize: 24, textAlign: 'center', marginBottom: 12, }, footerText: { fontSize: 24, textAlign: 'center', marginTop: 12, }, sectionHeaderText: { backgroundColor: '#FFFFFF', fontSize: 24, fontWeight: 'bold', }, imageStyles: { height: '100%', width: 100, }, }); export default App; ``` Reviewed By: yungsters Differential Revision: D54301991 Pulled By: javache fbshipit-source-id: d2cfafb1b4eb868761d849111b5abb7e9d584a46 --- .../__snapshots__/SectionList-test.js.snap | 102 ++-- .../Lists/VirtualizedSectionList.js | 16 +- .../VirtualizedSectionList-test.js.snap | 524 +++++++++--------- 3 files changed, 304 insertions(+), 338 deletions(-) diff --git a/packages/react-native/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap b/packages/react-native/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap index dd3dcacc32ef8c..dcb40ffe0ae809 100644 --- a/packages/react-native/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap +++ b/packages/react-native/Libraries/Lists/__tests__/__snapshots__/SectionList-test.js.snap @@ -264,31 +264,27 @@ exports[`SectionList renders all the bells and whistles 1`] = ` onLayout={[Function]} style={null} > - - - - - + + + - - - - + + - - - - - + + + - - - - + + - - - - - + + + - - - - + + ); - return leadingSeparator || separator ? ( - - {inverted === false ? leadingSeparator : separator} + const RenderSeparator = leadingSeparator || separator; + const firstSeparator = inverted === false ? leadingSeparator : separator; + const secondSeparator = inverted === false ? separator : leadingSeparator; + + return ( + <> + {RenderSeparator ? firstSeparator : null} {element} - {inverted === false ? separator : leadingSeparator} - - ) : ( - element + {RenderSeparator ? secondSeparator : null} + ); } diff --git a/packages/virtualized-lists/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap b/packages/virtualized-lists/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap index 8a01cb58500c54..8de2c76b838233 100644 --- a/packages/virtualized-lists/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap +++ b/packages/virtualized-lists/Lists/__tests__/__snapshots__/VirtualizedSectionList-test.js.snap @@ -252,80 +252,76 @@ exports[`VirtualizedSectionList handles separators correctly 1`] = ` onLayout={[Function]} style={null} > - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - + - + } + /> - - - - + + - - - - + + - - - - + + - - - - + + Date: Thu, 29 Feb 2024 03:06:52 -0800 Subject: [PATCH 038/361] Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE Summary: In OSS we have reports like [this one](https://github.com/facebook/react-native/issues/43241) where env variables from different settings might clash together, making react native apps fail to build hermes. For example, a team might have defined a BUILD_FROM_SOURCE env variable to build their specific project from source and that will clash with how react native apps installs Hermes. This change disambiguate the BUILD_FROM_SOURCE flag we have internally, moving to a less likely to clash RCT_BUILD_HERMES_FROM_SOURCE. ## Changelog: [iOS][Breaking] - Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE Reviewed By: huntie Differential Revision: D54356337 fbshipit-source-id: 1115e3c22cbcf1d64b7edae30da614d52423123b --- .circleci/configurations/executors.yml | 4 ++-- .circleci/configurations/jobs.yml | 2 +- packages/react-native/sdks/hermes-engine/hermes-utils.rb | 7 ++++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.circleci/configurations/executors.yml b/.circleci/configurations/executors.yml index 1c4c6a9bfb806c..1e20c133e36590 100644 --- a/.circleci/configurations/executors.yml +++ b/.circleci/configurations/executors.yml @@ -35,11 +35,11 @@ executors: xcode: *xcode_version resource_class: macos.x86.medium.gen2 environment: - - BUILD_FROM_SOURCE: true + - RCT_BUILD_HERMES_FROM_SOURCE: true reactnativeios-lts: <<: *defaults macos: xcode: '14.3.1' resource_class: macos.x86.medium.gen2 environment: - - BUILD_FROM_SOURCE: true + - RCT_BUILD_HERMES_FROM_SOURCE: true diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml index 39eb852857d3dd..d40dbc45e4a2c9 100644 --- a/.circleci/configurations/jobs.yml +++ b/.circleci/configurations/jobs.yml @@ -599,7 +599,7 @@ jobs: environment: - HERMES_WS_DIR: *hermes_workspace_root - HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion" - - BUILD_FROM_SOURCE: true + - RCT_BUILD_HERMES_FROM_SOURCE: true steps: - run: name: Install dependencies diff --git a/packages/react-native/sdks/hermes-engine/hermes-utils.rb b/packages/react-native/sdks/hermes-engine/hermes-utils.rb index 8c2f4f6c665a83..c0c7613192ebd8 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-utils.rb +++ b/packages/react-native/sdks/hermes-engine/hermes-utils.rb @@ -7,6 +7,7 @@ require 'rexml/document' HERMES_GITHUB_URL = "https://github.com/facebook/hermes.git" +ENV_BUILD_FROM_SOURCE = "RCT_BUILD_HERMES_FROM_SOURCE" module HermesEngineSourceType LOCAL_PREBUILT_TARBALL = :local_prebuilt_tarball @@ -30,7 +31,7 @@ def HermesEngineSourceType.isFromSource(source_type) # - To use a specific tarball, install the dependencies with: # `HERMES_ENGINE_TARBALL_PATH= bundle exec pod install` # - To force a build from source, install the dependencies with: -# `BUILD_FROM_SOURCE=true bundle exec pod install` +# `RCT_BUILD_HERMES_FROM_SOURCE=true bundle exec pod install` # If none of the two are provided, Cocoapods will check whether there is a tarball for the current version # (either release or nightly). If not, it will fall back to building from source (the latest commit on main). # @@ -85,11 +86,11 @@ def hermes_commit_envvar_defined() end def force_build_from_tag(react_native_path) - return ENV['BUILD_FROM_SOURCE'] === 'true' && File.exist?(hermestag_file(react_native_path)) + return ENV[ENV_BUILD_FROM_SOURCE] === 'true' && File.exist?(hermestag_file(react_native_path)) end def force_build_from_main(react_native_path) - return ENV['BUILD_FROM_SOURCE'] === 'true' && !File.exist?(hermestag_file(react_native_path)) + return ENV[ENV_BUILD_FROM_SOURCE] === 'true' && !File.exist?(hermestag_file(react_native_path)) end def release_artifact_exists(version) From 77cbe6d76db101cd31d5a32b1b485c60d3822474 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 29 Feb 2024 07:17:02 -0800 Subject: [PATCH 039/361] Extract RNCORE_CONFIG in a separate variable Summary: This change refactor the RNCORE_CONFIGS in a separate variable to simplify reuse. ## Changelog: [Internal] - Refactor code Reviewed By: dmytrorykun Differential Revision: D54308346 fbshipit-source-id: b9d7c8e0a9b4042f2ab1adeb7aae875264d22499 --- .../codegen/generate-artifacts-executor.js | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index c150b1956a648e..a89d40cb7f0cf5 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -34,18 +34,19 @@ const REACT_NATIVE_REPOSITORY_ROOT = path.join( ); const REACT_NATIVE_PACKAGE_ROOT_FOLDER = path.join(__dirname, '..', '..'); const CODEGEN_REPO_PATH = `${REACT_NATIVE_REPOSITORY_ROOT}/packages/react-native-codegen`; +const RNCORE_CONFIGS = { + ios: path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'ReactCommon'), + android: path.join( + REACT_NATIVE_PACKAGE_ROOT_FOLDER, + 'ReactAndroid', + 'build', + 'generated', + 'source', + 'codegen', + ), +}; const CORE_LIBRARIES_WITH_OUTPUT_FOLDER = { - rncore: { - ios: path.join(REACT_NATIVE_PACKAGE_ROOT_FOLDER, 'ReactCommon'), - android: path.join( - REACT_NATIVE_PACKAGE_ROOT_FOLDER, - 'ReactAndroid', - 'build', - 'generated', - 'source', - 'codegen', - ), - }, + rncore: RNCORE_CONFIGS, FBReactNativeSpec: { ios: null, android: path.join( From 23c541046c3c442a0115f17eeda63034223c2ccc Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 29 Feb 2024 07:17:02 -0800 Subject: [PATCH 040/361] Extract libraryName in a seprate variable Summary: This change factor out in a variable the `libraryName` to avoid verbosity. ## Changelog: [Internal] - factor out libraryName Reviewed By: dmytrorykun Differential Revision: D54308601 fbshipit-source-id: 1a64a6b960cc86a1cff059e3ba6a45c33bf3150e --- .../codegen/generate-artifacts-executor.js | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index a89d40cb7f0cf5..3c84671a876c11 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -416,19 +416,20 @@ function generateSchemaInfo(library, platform) { } function generateCode(outputPath, schemaInfo, includesGeneratedCode, platform) { - const tmpDir = fs.mkdtempSync( - path.join(os.tmpdir(), schemaInfo.library.config.name), - ); + const libraryName = schemaInfo.library.config.name; + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), libraryName)); const tmpOutputDir = path.join(tmpDir, 'out'); fs.mkdirSync(tmpOutputDir, {recursive: true}); - console.log(`[Codegen] Generating Native Code for ${platform}`); + console.log( + `[Codegen] Generating Native Code for ${libraryName} - ${platform}`, + ); const useLocalIncludePaths = includesGeneratedCode; generateSpecsCLIExecutor.generateSpecFromInMemorySchema( platform, schemaInfo.schema, tmpOutputDir, - schemaInfo.library.config.name, + libraryName, 'com.facebook.fbreact.specs', schemaInfo.library.config.type, useLocalIncludePaths, @@ -436,10 +437,7 @@ function generateCode(outputPath, schemaInfo, includesGeneratedCode, platform) { // Finally, copy artifacts to the final output directory. const outputDir = - reactNativeCoreLibraryOutputPath( - schemaInfo.library.config.name, - platform, - ) ?? outputPath; + reactNativeCoreLibraryOutputPath(libraryName, platform) ?? outputPath; fs.mkdirSync(outputDir, {recursive: true}); // TODO: Fix this. This will not work on Windows. execSync(`cp -R ${tmpOutputDir}/* "${outputDir}"`); From 9a27c08fb9c80eb4b65a8dc7bd96db09e301bf72 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 29 Feb 2024 07:17:02 -0800 Subject: [PATCH 041/361] Add script to generate RNCore components only Summary: This change extracts the function to create RNCore components in a separate reusable unit. RNCore is now generate in the `node_modules` folder when the app runs pod install, which is a problem because there are use cases where it's not possible to modify the `node_modules` folder or the generated files might be lost. The goal is to: - extract this function - execute this function before packing react-native during the release. (see D54308411) In this way, we are going to generate the RNCore files in the react-native path that will be packaged and then released. Users of react-native will have the generated code directly in the node_modules with no need to generate it. ## Changelog: [General][Added] - Add function to only generate RNCore components Reviewed By: huntie Differential Revision: D54308713 fbshipit-source-id: 0fa9ab4ba7b66c577663f0c736742c4d5583f617 --- .../codegen/generate-artifacts-executor.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 3c84671a876c11..ca6ac08689dc49 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -593,6 +593,22 @@ function cleanupEmptyFilesAndFolders(filepath) { } } +function generateRNCoreComponentsIOS(projectRoot /*: string */) /*: void*/ { + const ios = 'ios'; + buildCodegenIfNeeded(); + const pkgJson = readPkgJsonInDirectory(projectRoot); + const rncoreLib = findProjectRootLibraries(pkgJson, projectRoot).filter( + library => library.config.name === 'rncore', + )[0]; + if (!rncoreLib) { + throw new Error( + "[Codegen] Can't find rncore library. Failed to generate rncore artifacts", + ); + } + const rncoreSchemaInfo = generateSchemaInfo(rncoreLib, ios); + generateCode('', rncoreSchemaInfo, false, ios); +} + // Execute /** @@ -686,7 +702,8 @@ function execute(projectRoot, targetPlatform, baseOutputPath) { } module.exports = { - execute: execute, + execute, + generateRNCoreComponentsIOS, // exported for testing purposes only: _extractLibrariesFromJSON: extractLibrariesFromJSON, _cleanupEmptyFilesAndFolders: cleanupEmptyFilesAndFolders, From 03ba46f7e69d802530d43b5516da5f77def23fbd Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 29 Feb 2024 07:17:02 -0800 Subject: [PATCH 042/361] Avoid generation of RNCore component if they have been generated already Summary: Added a check to avoid the regeneration of RNCore components in case they have been generated already. In order to maintain backward compatibility and to make sure not to break internal use cases, I think we should still keep the possibility to generate these components at `pod install` time. Internal users of RNTester, for example, will not run `yarn prepack` before building react-native using OSS technology. Notice that, in this specific case, the Codegen generates the file in a path that is not `node_modules`. ## Changelog: [General][Added] - Skip generation of RNCore if the files have been already generated Reviewed By: dmytrorykun Differential Revision: D54308832 fbshipit-source-id: 0b5822a367eb0b191c42bc92f8bff20d541c5b29 --- .../codegen/generate-artifacts-executor.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index ca6ac08689dc49..271a66e093dee6 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -415,7 +415,33 @@ function generateSchemaInfo(library, platform) { }; } +function shouldSkipGenerationForRncore(schemaInfo, platform) { + if (platform !== 'ios' || schemaInfo.library.config.name !== 'rncore') { + return false; + } + const rncoreOutputPath = path.join( + RNCORE_CONFIGS.ios, + 'react', + 'renderer', + 'components', + 'rncore', + ); + const rncoreAbsolutePath = path.resolve(rncoreOutputPath); + return ( + rncoreAbsolutePath.includes('node_modules') && + fs.existsSync(rncoreAbsolutePath) && + fs.readdirSync(rncoreAbsolutePath).length > 0 + ); +} + function generateCode(outputPath, schemaInfo, includesGeneratedCode, platform) { + if (shouldSkipGenerationForRncore(schemaInfo, platform)) { + console.log( + '[Codegen - rncore] Skipping iOS code generation for rncore as it has been generated already.', + ); + return; + } + const libraryName = schemaInfo.library.config.name; const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), libraryName)); const tmpOutputDir = path.join(tmpDir, 'out'); From 5d72e1115e7cdeeb0245385748c91a9b3142cfe9 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Thu, 29 Feb 2024 07:17:02 -0800 Subject: [PATCH 043/361] Extract prepack tasks in a JS script and add codegen generation Summary: This change moves the prepack script of react-native in a separate script, so we can make sure we execute all the preprocessing we need before packing and publishing React Native to OSS. ## Changelog: [General][Changed] - Moved the tasks of prepack in a separate node script Reviewed By: huntie Differential Revision: D54308411 fbshipit-source-id: 989c2b8c6cf88a1e9d87cf34e43351b5c0e7ea73 --- packages/react-native/package.json | 2 +- packages/react-native/scripts/prepack.js | 25 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 packages/react-native/scripts/prepack.js diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 96f4169119e201..dcd725c23bd5dd 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -89,7 +89,7 @@ "types" ], "scripts": { - "prepack": "cp ../../README.md .", + "prepack": "node ./scripts/prepack.js", "featureflags-check": "node ./scripts/featureflags/index.js --verify-unchanged", "featureflags-update": "node ./scripts/featureflags/index.js" }, diff --git a/packages/react-native/scripts/prepack.js b/packages/react-native/scripts/prepack.js new file mode 100644 index 00000000000000..694e891117dd62 --- /dev/null +++ b/packages/react-native/scripts/prepack.js @@ -0,0 +1,25 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + * @oncall react_native + */ + +const { + generateRNCoreComponentsIOS, +} = require('./codegen/generate-artifacts-executor'); +const fs = require('fs'); + +function main() { + console.info('[Prepack] Copying README.md'); + fs.copyFileSync('../../README.md', './README.md'); + generateRNCoreComponentsIOS('.'); +} + +if (require.main === module) { + main(); +} From 0555fdd93afb00b6b25ba7ace76b0d65b7458c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 29 Feb 2024 07:43:09 -0800 Subject: [PATCH 044/361] Gate inspector target creation and destruction behind inspector feature flags Summary: Changelog: [internal] This fixes a crashes during logout on Android and iOS caused by trying to unregister the inspector from instances that were not previously registered. This is because I removed a check in D51459050 that was necessary when the inspector was disabled via the flag (and we call the `unregisterFromInspector` method unconditionally). This also gates the registration/unregistration on Android properly. Reviewed By: huntie Differential Revision: D54357554 fbshipit-source-id: 945288acdabdface324884bee1e832870ec8806f --- .../facebook/react/runtime/ReactHostImpl.java | 24 +++++++++++++++---- .../facebook/react/runtime/ReactInstance.java | 4 ++-- .../jni/react/runtime/jni/JReactInstance.cpp | 4 +++- .../react/runtime/ReactInstance.cpp | 14 +++++------ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index e3f9a864883196..40a29a1d8f9bad 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -48,6 +48,7 @@ import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.DevSupportManagerBase; import com.facebook.react.devsupport.DisabledDevSupportManager; +import com.facebook.react.devsupport.InspectorFlags; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.fabric.ComponentFactory; import com.facebook.react.fabric.FabricUIManager; @@ -108,7 +109,6 @@ public class ReactHostImpl implements ReactHost { private final MemoryPressureRouter mMemoryPressureRouter; private final boolean mAllowPackagerServerAccess; private final boolean mUseDevSupport; - private final ReactHostInspectorTarget mReactHostInspectorTarget; private final Collection mReactInstanceEventListeners = Collections.synchronizedList(new ArrayList<>()); @@ -136,6 +136,8 @@ public class ReactHostImpl implements ReactHost { private final Set> mBeforeDestroyListeners = Collections.synchronizedSet(new HashSet<>()); + private @Nullable ReactHostInspectorTarget mReactHostInspectorTarget; + public ReactHostImpl( Context context, ReactHostDelegate delegate, @@ -185,7 +187,6 @@ public ReactHostImpl( mDevSupportManager = new DisabledDevSupportManager(); } mUseDevSupport = useDevSupport; - mReactHostInspectorTarget = new ReactHostInspectorTarget(this); } @Override @@ -761,7 +762,7 @@ private Task getOrCreateStartTask() { @ThreadConfined(UI) private void moveToHostDestroy(@Nullable ReactContext currentContext) { mReactLifecycleStateManager.moveToOnHostDestroy(currentContext); - mReactHostInspectorTarget.close(); + destroyReactHostInspectorTarget(); setCurrentActivity(null); } @@ -916,7 +917,7 @@ private Task getOrCreateReactInstanceTask() { mQueueThreadExceptionHandler, mReactJsExceptionHandler, mUseDevSupport, - mReactHostInspectorTarget); + getOrCreateReactHostInspectorTarget()); if (ReactFeatureFlags .unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) { @@ -1529,4 +1530,19 @@ public void setJsEngineResolutionAlgorithm( @Nullable JSEngineResolutionAlgorithm jsEngineResolutionAlgorithm) { mJSEngineResolutionAlgorithm = jsEngineResolutionAlgorithm; } + + private @Nullable ReactHostInspectorTarget getOrCreateReactHostInspectorTarget() { + if (mReactHostInspectorTarget == null && InspectorFlags.getEnableModernCDPRegistry()) { + mReactHostInspectorTarget = new ReactHostInspectorTarget(this); + } + + return mReactHostInspectorTarget; + } + + private void destroyReactHostInspectorTarget() { + if (mReactHostInspectorTarget != null) { + mReactHostInspectorTarget.close(); + mReactHostInspectorTarget = null; + } + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 8f71f3ca724f23..1a748d6c7298a4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -115,7 +115,7 @@ final class ReactInstance { QueueThreadExceptionHandler exceptionHandler, ReactJsExceptionHandler reactExceptionManager, boolean useDevSupport, - ReactHostInspectorTarget reactHostInspectorTarget) { + @Nullable ReactHostInspectorTarget reactHostInspectorTarget) { mBridgelessReactContext = bridgelessReactContext; mDelegate = delegate; @@ -466,7 +466,7 @@ private native HybridData initHybrid( ReactJsExceptionHandler jReactExceptionsManager, @Nullable BindingsInstaller jBindingsInstaller, boolean isProfiling, - ReactHostInspectorTarget reactHostInspectorTarget); + @Nullable ReactHostInspectorTarget reactHostInspectorTarget); @DoNotStrip private static native JSTimerExecutor createJSTimerExecutor(); diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp index 0e789a5eec57c5..a74cc54fc45668 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/runtime/jni/JReactInstance.cpp @@ -67,7 +67,9 @@ JReactInstance::JReactInstance( sharedJSMessageQueueThread, timerManager, std::move(jsErrorHandlingFunc), - jReactHostInspectorTarget->cthis()->getInspectorTarget()); + jReactHostInspectorTarget + ? jReactHostInspectorTarget->cthis()->getInspectorTarget() + : nullptr); auto bufferedRuntimeExecutor = instance_->getBufferedRuntimeExecutor(); timerManager->setRuntimeExecutor(bufferedRuntimeExecutor); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index c2ade6b2e7c36c..392ab7513d0b91 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -131,15 +131,15 @@ ReactInstance::ReactInstance( } void ReactInstance::unregisterFromInspector() { - assert(inspectorTarget_); + if (inspectorTarget_) { + assert(runtimeInspectorTarget_); + inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_); - assert(runtimeInspectorTarget_); - inspectorTarget_->unregisterRuntime(*runtimeInspectorTarget_); + assert(parentInspectorTarget_); + parentInspectorTarget_->unregisterInstance(*inspectorTarget_); - assert(parentInspectorTarget_); - parentInspectorTarget_->unregisterInstance(*inspectorTarget_); - - inspectorTarget_ = nullptr; + inspectorTarget_ = nullptr; + } } RuntimeExecutor ReactInstance::getUnbufferedRuntimeExecutor() noexcept { From d889d77aed1214097c5841c7a13327bdb1edfbc0 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Thu, 29 Feb 2024 09:29:19 -0800 Subject: [PATCH 045/361] Add changelog for 0.72.11 Summary: Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D54356952 fbshipit-source-id: dadfeaa1208c00055baad2b8cd704723a530742e --- CHANGELOG.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3298cc030fdb86..a1501e9f85f6d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -563,6 +563,25 @@ - Fix race condition between A11yManager and UIManager ([f39f34ed82](https://github.com/facebook/react-native/commit/f39f34ed82997d0595522a285c3cb8693594e718) by [@cipolleschi](https://github.com/cipolleschi)) - Fix symbol not found _jump_fcontext with use_frameworks ([a2771ce58a](https://github.com/facebook/react-native/commit/a2771ce58ac221d1ac0de265c1ce571212fbcf83) by [@cipolleschi](https://github.com/cipolleschi)) +## v0.72.11 + +### Changed + +- Upgrade CLI to 11.4.1 ([c57a29a08c](https://github.com/facebook/react-native/commit/c57a29a08c086728ea3bbb6b077c92fae6792d11) by [@szymonrybczak](https://github.com/szymonrybczak)) +- Update Metro to ^0.76.9, CLI to ^11.4.0 ([ddff36f770](https://github.com/facebook/react-native/commit/ddff36f7705f1b5b2e27bfb2ee62f6726dfdd7bd) by [@robhogan](https://github.com/robhogan)) + +#### iOS specific + +- Improve Swift support for 3rd party libs ([6939021518](https://github.com/facebook/react-native/commit/693902151899c85ff00418d75df4377a1096efee) by [@cipolleschi](https://github.com/cipolleschi)) + +### Fixed + +- Fix overriding EXCLUDED_ARCHS when installing Hermes on RN v0.72 ([a4282a91c3](https://github.com/facebook/react-native/commit/a4282a91c32f947adfb4f210e296e8dfeefdae34) by [@ken0nek](https://github.com/ken0nek)) + +#### iOS specific + +- Don't allow cocoapods 1.15. ([08fd9170fc](https://github.com/facebook/react-native/commit/08fd9170fcdc7042fdcfe5f54eec71ed245d9795) by [@blakef](https://github.com/blakef)) + ## v0.72.10 ### Added From 4d982dcdae9ac8466b7109fb491ab9c1fb24ac6b Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Thu, 29 Feb 2024 10:23:09 -0800 Subject: [PATCH 046/361] Undo moving of TurboModule to internal and expose utility function for TurboModule.class.isAssignableFrom (#43219) Summary: After discussing with mdvacca, we prefer to undo the change of `TurboModule` package to `.internal` as this is a quite aggressive breaking change for the ecosystem. Moreover: users should not invoke `TurboModule.class.isAssignableFrom` because `TurboModule` is `.internal`. Therefore I'm exposing another API to check if a class is a TurboModule as a static field of `ReactModuleInfo`. ## Changelog: [INTERNAL] - Do not use TurboModule.class.isAssignableFrom Pull Request resolved: https://github.com/facebook/react-native/pull/43219 Test Plan: Tests are attached Reviewed By: mdvacca, cipolleschi Differential Revision: D54280882 Pulled By: cortinico fbshipit-source-id: 9443c8aa23cf70dd5cfe574fe573d83313134358 --- .../modules/GenerateModuleJavaSpec.js | 2 +- .../GenerateModuleJavaSpec-test.js.snap | 18 +++---- .../ReactAndroid/api/ReactAndroid.api | 11 ++-- .../facebook/react/CoreModulesPackage.java | 3 +- .../com/facebook/react/DebugCorePackage.java | 3 +- ...eactPackageTurboModuleManagerDelegate.java | 6 +-- .../react/bridge/JavaModuleWrapper.java | 2 +- .../facebook/react/bridge/ModuleHolder.java | 3 +- .../core/TurboModuleInteropUtils.java | 2 +- .../turbomodule/core/TurboModuleManager.java | 2 +- .../core/TurboModuleManagerDelegate.java | 2 +- .../core/interfaces/TurboModule.kt | 19 ------- .../react/module/model/ReactModuleInfo.java | 10 ++++ .../processing/ReactModuleSpecProcessor.java | 4 +- .../react/modules/fresco/FrescoModule.java | 2 +- .../modules/systeminfo/AndroidInfoModule.java | 2 +- .../react/runtime/CoreReactPackage.java | 3 +- .../react/shell/MainReactPackage.java | 3 +- .../core/interfaces/TurboModule.kt | 21 ++++---- .../react/bridge/BaseJavaModuleTest.kt | 2 +- .../modules/model/ReactModuleInfoTest.kt | 51 +++++++++++++++++++ .../android/ReactCommon/JavaTurboModule.h | 2 +- .../android/NativeSampleTurboModuleSpec.java | 2 +- 23 files changed, 107 insertions(+), 68 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/interfaces/TurboModule.kt create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/model/ReactModuleInfoTest.kt diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js index 2dc407f303476f..8335f705ae6eb6 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleJavaSpec.js @@ -462,7 +462,7 @@ module.exports = { 'com.facebook.react.bridge.ReactApplicationContext', 'com.facebook.react.bridge.ReactContextBaseJavaModule', 'com.facebook.react.bridge.ReactMethod', - 'com.facebook.react.internal.turbomodule.core.interfaces.TurboModule', + 'com.facebook.react.turbomodule.core.interfaces.TurboModule', 'com.facebook.proguard.annotations.DoNotStrip', 'javax.annotation.Nonnull', ]); diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap index a03ec04f54d55d..875476d45acaae 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleJavaSpec-test.js.snap @@ -20,7 +20,7 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -66,7 +66,7 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -136,7 +136,7 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -178,7 +178,7 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class AliasTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -224,7 +224,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeCameraRollManagerSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -272,7 +272,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeExceptionsManagerSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -338,7 +338,7 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.Arrays; import java.util.HashSet; import java.util.Map; @@ -462,7 +462,7 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeSampleTurboModuleSpec extends ReactContextBaseJavaModule implements TurboModule { @@ -500,7 +500,7 @@ import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import javax.annotation.Nonnull; public abstract class NativeSampleTurboModule2Spec extends ReactContextBaseJavaModule implements TurboModule { diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 10388444d06e5c..a7d34c4324c94f 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -322,7 +322,7 @@ public abstract class com/facebook/react/ReactPackageTurboModuleManagerDelegate protected fun (Lcom/facebook/react/bridge/ReactApplicationContext;Ljava/util/List;Lcom/facebook/jni/HybridData;)V public fun getEagerInitModuleNames ()Ljava/util/List; public fun getLegacyModule (Ljava/lang/String;)Lcom/facebook/react/bridge/NativeModule; - public fun getModule (Ljava/lang/String;)Lcom/facebook/react/internal/turbomodule/core/interfaces/TurboModule; + public fun getModule (Ljava/lang/String;)Lcom/facebook/react/turbomodule/core/interfaces/TurboModule; public fun unstable_enableSyncVoidMethods ()Z public fun unstable_isLegacyModuleRegistered (Ljava/lang/String;)Z public fun unstable_isModuleRegistered (Ljava/lang/String;)Z @@ -2846,6 +2846,7 @@ public class com/facebook/react/module/model/ReactModuleInfo { public fun (Ljava/lang/String;Ljava/lang/String;ZZZZ)V public fun (Ljava/lang/String;Ljava/lang/String;ZZZZZ)V public fun canOverrideExistingModule ()Z + public static fun classIsTurboModule (Ljava/lang/Class;)Z public fun className ()Ljava/lang/String; public fun hasConstants ()Z public fun isCxxModule ()Z @@ -3189,7 +3190,7 @@ public class com/facebook/react/modules/dialog/DialogModule : com/facebook/fbrea public fun showAlert (Lcom/facebook/react/bridge/ReadableMap;Lcom/facebook/react/bridge/Callback;Lcom/facebook/react/bridge/Callback;)V } -public class com/facebook/react/modules/fresco/FrescoModule : com/facebook/react/bridge/ReactContextBaseJavaModule, com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/internal/turbomodule/core/interfaces/TurboModule, com/facebook/react/modules/common/ModuleDataCleaner$Cleanable { +public class com/facebook/react/modules/fresco/FrescoModule : com/facebook/react/bridge/ReactContextBaseJavaModule, com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/modules/common/ModuleDataCleaner$Cleanable, com/facebook/react/turbomodule/core/interfaces/TurboModule { public static final field NAME Ljava/lang/String; public fun (Lcom/facebook/react/bridge/ReactApplicationContext;)V public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/imagepipeline/core/ImagePipeline;Z)V @@ -3430,7 +3431,7 @@ public class com/facebook/react/modules/systeminfo/AndroidInfoHelpers { public static fun getServerHost (Ljava/lang/Integer;)Ljava/lang/String; } -public class com/facebook/react/modules/systeminfo/AndroidInfoModule : com/facebook/fbreact/specs/NativePlatformConstantsAndroidSpec, com/facebook/react/internal/turbomodule/core/interfaces/TurboModule { +public class com/facebook/react/modules/systeminfo/AndroidInfoModule : com/facebook/fbreact/specs/NativePlatformConstantsAndroidSpec, com/facebook/react/turbomodule/core/interfaces/TurboModule { public fun (Lcom/facebook/react/bridge/ReactApplicationContext;)V public fun getAndroidID ()Ljava/lang/String; public fun getTypedExportedConstants ()Ljava/util/Map; @@ -3797,7 +3798,9 @@ public abstract interface class com/facebook/react/turbomodule/core/interfaces/C public abstract interface class com/facebook/react/turbomodule/core/interfaces/NativeMethodCallInvokerHolder { } -public abstract interface class com/facebook/react/turbomodule/core/interfaces/TurboModule : com/facebook/react/internal/turbomodule/core/interfaces/TurboModule { +public abstract interface class com/facebook/react/turbomodule/core/interfaces/TurboModule { + public abstract fun initialize ()V + public abstract fun invalidate ()V } public abstract class com/facebook/react/uimanager/BaseViewManager : com/facebook/react/uimanager/ViewManager, android/view/View$OnLayoutChangeListener, com/facebook/react/uimanager/BaseViewManagerInterface { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java index 3ffbc8aa28d22d..ae1bb0131fd22e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java @@ -17,7 +17,6 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactMarker; import com.facebook.react.devsupport.LogBoxModule; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; @@ -115,7 +114,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { reactModule.canOverrideExistingModule(), reactModule.needsEagerInit(), reactModule.isCxxModule(), - TurboModule.class.isAssignableFrom(moduleClass))); + ReactModuleInfo.classIsTurboModule(moduleClass))); } return () -> reactModuleInfoMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java index 69471937ab8501..2e1d3d976cdf3b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/DebugCorePackage.java @@ -12,7 +12,6 @@ import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.devsupport.JSCHeapCapture; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; @@ -74,7 +73,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { reactModule.canOverrideExistingModule(), reactModule.needsEagerInit(), reactModule.isCxxModule(), - TurboModule.class.isAssignableFrom(moduleClass))); + ReactModuleInfo.classIsTurboModule(moduleClass))); } return () -> reactModuleInfoMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java index 448ec258d47593..2d674204089752 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactPackageTurboModuleManagerDelegate.java @@ -16,9 +16,9 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.internal.turbomodule.core.TurboModuleManagerDelegate; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.model.ReactModuleInfo; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -121,14 +121,14 @@ private void initialize( reactModule.canOverrideExistingModule(), true, reactModule.isCxxModule(), - TurboModule.class.isAssignableFrom(moduleClass)) + ReactModuleInfo.classIsTurboModule(moduleClass)) : new ReactModuleInfo( moduleName, moduleClass.getName(), module.canOverrideExistingModule(), true, CxxModuleWrapper.class.isAssignableFrom(moduleClass), - TurboModule.class.isAssignableFrom(moduleClass)); + ReactModuleInfo.classIsTurboModule(moduleClass)); reactModuleInfoMap.put(moduleName, moduleInfo); moduleMap.put(moduleName, module); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaModuleWrapper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaModuleWrapper.java index 5e08e165801c6a..44abd25f26a761 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaModuleWrapper.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaModuleWrapper.java @@ -15,7 +15,7 @@ import androidx.annotation.Nullable; import com.facebook.proguard.annotations.DoNotStrip; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import com.facebook.systrace.Systrace; import com.facebook.systrace.SystraceMessage; import java.lang.reflect.Method; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java index 25f170f1134a92..77d011b93cfaa9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ModuleHolder.java @@ -20,7 +20,6 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.common.ReactConstants; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.model.ReactModuleInfo; import com.facebook.systrace.SystraceMessage; import java.util.concurrent.atomic.AtomicInteger; @@ -73,7 +72,7 @@ public ModuleHolder(NativeModule nativeModule) { nativeModule.canOverrideExistingModule(), true, CxxModuleWrapper.class.isAssignableFrom(nativeModule.getClass()), - TurboModule.class.isAssignableFrom(nativeModule.getClass())); + ReactModuleInfo.classIsTurboModule(nativeModule.getClass())); mModule = nativeModule; PrinterHolder.getPrinter() diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleInteropUtils.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleInteropUtils.java index 50ce80eb46af0b..496cf39a313ba9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleInteropUtils.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleInteropUtils.java @@ -18,7 +18,7 @@ import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashSet; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManager.java index e66dbc3492830b..d627f82b7fd3f8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManager.java @@ -19,12 +19,12 @@ import com.facebook.react.bridge.ReactNoCrashSoftException; import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.RuntimeExecutor; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry; import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; import com.facebook.react.turbomodule.core.NativeMethodCallInvokerHolderImpl; import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java index 9fe0fdb630d308..39539cdd6f34d5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/TurboModuleManagerDelegate.java @@ -12,7 +12,7 @@ import com.facebook.jni.HybridData; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.NativeModule; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.ArrayList; import java.util.List; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/interfaces/TurboModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/interfaces/TurboModule.kt deleted file mode 100644 index 0e546d282864a3..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/turbomodule/core/interfaces/TurboModule.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.internal.turbomodule.core.interfaces -/** All turbo modules should inherit from this interface */ -public interface TurboModule { - /** Initialize the TurboModule. */ - public fun initialize() - - /** - * Called during the turn down process of ReactHost. This method is called before React Native is - * stopped. Override this method to clean up resources used by the TurboModule. - */ - public fun invalidate() -} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java index ae4a56bbc3a969..8be508edf80479 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/model/ReactModuleInfo.java @@ -7,6 +7,8 @@ package com.facebook.react.module.model; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; + /** * Data holder class holding native module specifications. {@link ReactModuleSpecProcessor} creates * these so Java modules don't have to be instantiated at React Native start up. @@ -80,4 +82,12 @@ public boolean isCxxModule() { public boolean isTurboModule() { return mIsTurboModule; } + + /** + * Checks if the passed class is a TurboModule. Useful to populate the parameter [isTurboModule] + * in the constructor of ReactModuleInfo. + */ + public static boolean classIsTurboModule(Class clazz) { + return TurboModule.class.isAssignableFrom(clazz); + } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java index 969ea6ddb09939..4f85ff932503b6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/module/processing/ReactModuleSpecProcessor.java @@ -161,13 +161,13 @@ private CodeBlock getCodeBlockForReactModuleInfos(List nativeModules) builder.addStatement("$T map = new $T()", MAP_TYPE, INSTANTIATED_MAP_TYPE); String turboModuleInterfaceCanonicalName = - "com.facebook.react.internal.turbomodule.core.interfaces.TurboModule"; + "com.facebook.react.turbomodule.core.interfaces.TurboModule"; TypeMirror turboModuleInterface = mElements.getTypeElement(turboModuleInterfaceCanonicalName).asType(); if (turboModuleInterface == null) { throw new RuntimeException( - "com.facebook.react.internal.turbomodule.core.interfaces.TurboModule interface not found."); + "com.facebook.react.turbomodule.core.interfaces.TurboModule interface not found."); } for (String nativeModule : nativeModules) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java index 34f9fd7121b0c7..3ac33b5d0e58bf 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/fresco/FrescoModule.java @@ -19,12 +19,12 @@ import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.common.ReactConstants; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.modules.common.ModuleDataCleaner; import com.facebook.react.modules.network.CookieJarContainer; import com.facebook.react.modules.network.ForwardingCookieHandler; import com.facebook.react.modules.network.OkHttpClientProvider; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.HashSet; import okhttp3.JavaNetCookieJar; import okhttp3.OkHttpClient; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java index b5b7f82b5cf6b9..3c283271487eda 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoModule.java @@ -18,8 +18,8 @@ import com.facebook.fbreact.specs.NativePlatformConstantsAndroidSpec; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.HashMap; import java.util.Map; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java index cb8b9c13af09ae..deae9de23347e3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/CoreReactPackage.java @@ -14,7 +14,6 @@ import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.devsupport.LogBoxModule; import com.facebook.react.devsupport.interfaces.DevSupportManager; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; @@ -103,7 +102,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { reactModule.canOverrideExistingModule(), reactModule.needsEagerInit(), reactModule.isCxxModule(), - TurboModule.class.isAssignableFrom(moduleClass))); + ReactModuleInfo.classIsTurboModule(moduleClass))); } } return () -> reactModuleInfoMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java index dac68508acaa0f..b95774889eb4fc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/shell/MainReactPackage.java @@ -15,7 +15,6 @@ import com.facebook.react.bridge.ModuleSpec; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; import com.facebook.react.module.annotations.ReactModule; import com.facebook.react.module.annotations.ReactModuleList; import com.facebook.react.module.model.ReactModuleInfo; @@ -297,7 +296,7 @@ public ReactModuleInfoProvider getReactModuleInfoProvider() { reactModule.canOverrideExistingModule(), reactModule.needsEagerInit(), reactModule.isCxxModule(), - TurboModule.class.isAssignableFrom(moduleClass))); + ReactModuleInfo.classIsTurboModule(moduleClass))); } } return () -> reactModuleInfoMap; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt index 394ffd69bfa622..6333b8125400b8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt @@ -6,15 +6,14 @@ */ package com.facebook.react.turbomodule.core.interfaces +/** All turbo modules should inherit from this interface */ +public interface TurboModule { + /** Initialize the TurboModule. */ + public fun initialize() -import com.facebook.react.common.annotations.DeprecatedInNewArchitecture - -/** - * This interface was introduced for backward compatibility purposes. This interface will be - * deprecated as part of the deprecation and removal of ReactModuleInfoProvider in the near future. - * - * See description of https://github.com/facebook/react-native/pull/41412 for more context. - */ -@DeprecatedInNewArchitecture -public interface TurboModule : - com.facebook.react.internal.turbomodule.core.interfaces.TurboModule {} + /** + * Called during the turn down process of ReactHost. This method is called before React Native is + * stopped. Override this method to clean up resources used by the TurboModule. + */ + public fun invalidate() +} diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/BaseJavaModuleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/BaseJavaModuleTest.kt index 85ae9a6d476476..49e9709df4a1e4 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/BaseJavaModuleTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/BaseJavaModuleTest.kt @@ -7,7 +7,7 @@ package com.facebook.react.bridge -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule +import com.facebook.react.turbomodule.core.interfaces.TurboModule import com.facebook.testutils.shadows.ShadowSoLoader import org.junit.Before import org.junit.Test diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/model/ReactModuleInfoTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/model/ReactModuleInfoTest.kt new file mode 100644 index 00000000000000..d3c072a6e5d10b --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/model/ReactModuleInfoTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.modules.model + +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.turbomodule.core.interfaces.TurboModule +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +class ReactModuleInfoTest { + + @Test + fun testCreateReactModuleInfo() { + val reactModuleInfo = + ReactModuleInfo( + /* name = */ "name", + /* className = */ "class", + /* canOverrideExistingModule = */ false, + /* needsEagerInit = */ false, + /* isCxxModule = */ false, + /* isTurboModule = */ false) + assertEquals("name", reactModuleInfo.name()) + assertFalse(reactModuleInfo.canOverrideExistingModule()) + assertFalse(reactModuleInfo.needsEagerInit()) + assertFalse(reactModuleInfo.isCxxModule) + assertFalse(reactModuleInfo.isTurboModule) + } + + @Test + fun classIsTurboModule_withRandomClass() { + assertFalse(ReactModuleInfo.classIsTurboModule(String::class.java)) + } + + @Test + fun classIsTurboModule_withTurboModule() { + assertTrue(ReactModuleInfo.classIsTurboModule(TestTurboModule::class.java)) + } + + inner class TestTurboModule : TurboModule { + override fun initialize() = Unit + + override fun invalidate() = Unit + } +} diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h index 66ebd30f92a4f4..cb020a852e6a1a 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/android/ReactCommon/JavaTurboModule.h @@ -19,7 +19,7 @@ namespace facebook::react { struct JTurboModule : jni::JavaClass { static auto constexpr kJavaDescriptor = - "Lcom/facebook/react/internal/turbomodule/core/interfaces/TurboModule;"; + "Lcom/facebook/react/turbomodule/core/interfaces/TurboModule;"; }; class JSI_EXPORT JavaTurboModule : public TurboModule { diff --git a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java index 6b05e380a21ee1..92d5687d7e7e5b 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java +++ b/packages/react-native/ReactCommon/react/nativemodule/samples/platform/android/NativeSampleTurboModuleSpec.java @@ -19,7 +19,7 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.internal.turbomodule.core.interfaces.TurboModule; +import com.facebook.react.turbomodule.core.interfaces.TurboModule; import java.util.Arrays; import java.util.HashSet; import java.util.Map; From 21171222eb9220f6d226dc739fbfcdf6c614e2ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 29 Feb 2024 11:38:30 -0800 Subject: [PATCH 047/361] More spec-compliant execution of microtasks Summary: Changelog: [internal] This modifies the method to run microtasks in `RuntimeScheduler_Modern` to align a bit better with the spec. In this case, we'll check if we're already running microtasks when we call that method, and skip if that's the case. We're not currently calling this method recursively so this shouldn't really be a change with the current logic. Reviewed By: javache Differential Revision: D54302537 fbshipit-source-id: ef5e12e68e0c7f8c9258929609c050ef78e4cde5 --- .../RuntimeScheduler_Modern.cpp | 77 ++++++++++--------- .../RuntimeScheduler_Modern.h | 3 + .../ReactCommon/react/utils/OnScopeExit.h | 36 +++++++++ 3 files changed, 81 insertions(+), 35 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/utils/OnScopeExit.h diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp index 4a30a2ff5c4034..aa737c68310ed1 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp @@ -11,45 +11,12 @@ #include #include #include +#include #include #include "ErrorUtils.h" namespace facebook::react { -namespace { -/** - * This is partially equivalent to the "Perform a microtask checkpoint" step in - * the Web event loop. See - * https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint. - * - * Iterates on \c drainMicrotasks until it completes or hits the retries bound. - */ -void executeMicrotasks(jsi::Runtime& runtime) { - SystraceSection s("RuntimeScheduler::executeMicrotasks"); - - uint8_t retries = 0; - // A heuristic number to guard infinite or absurd numbers of retries. - const static unsigned int kRetriesBound = 255; - - while (retries < kRetriesBound) { - try { - // The default behavior of \c drainMicrotasks is unbounded execution. - // We may want to make it bounded in the future. - if (runtime.drainMicrotasks()) { - break; - } - } catch (jsi::JSError& error) { - handleJSError(runtime, error, true); - } - retries++; - } - - if (retries == kRetriesBound) { - throw std::runtime_error("Hits microtasks retries bound."); - } -} -} // namespace - #pragma mark - Public RuntimeScheduler_Modern::RuntimeScheduler_Modern( @@ -298,7 +265,7 @@ void RuntimeScheduler_Modern::executeTask( if (ReactNativeFeatureFlags::enableMicrotasks()) { // "Perform a microtask checkpoint" step. - executeMicrotasks(runtime); + performMicrotaskCheckpoint(runtime); } if (ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop()) { @@ -339,4 +306,44 @@ void RuntimeScheduler_Modern::executeMacrotask( } } +/** + * This is partially equivalent to the "Perform a microtask checkpoint" step in + * the Web event loop. See + * https://html.spec.whatwg.org/multipage/webappapis.html#perform-a-microtask-checkpoint. + * + * Iterates on \c drainMicrotasks until it completes or hits the retries bound. + */ +void RuntimeScheduler_Modern::performMicrotaskCheckpoint( + jsi::Runtime& runtime) { + SystraceSection s("RuntimeScheduler::performMicrotaskCheckpoint"); + + if (performingMicrotaskCheckpoint_) { + return; + } + + performingMicrotaskCheckpoint_ = true; + OnScopeExit restoreFlag([&]() { performingMicrotaskCheckpoint_ = false; }); + + uint8_t retries = 0; + // A heuristic number to guard infinite or absurd numbers of retries. + const static unsigned int kRetriesBound = 255; + + while (retries < kRetriesBound) { + try { + // The default behavior of \c drainMicrotasks is unbounded execution. + // We may want to make it bounded in the future. + if (runtime.drainMicrotasks()) { + break; + } + } catch (jsi::JSError& error) { + handleJSError(runtime, error, true); + } + retries++; + } + + if (retries == kRetriesBound) { + throw std::runtime_error("Hits microtasks retries bound."); + } +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h index 34c8eb4cf16cbf..0759d8470bd54b 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h @@ -178,6 +178,9 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { void updateRendering(); + bool performingMicrotaskCheckpoint_{false}; + void performMicrotaskCheckpoint(jsi::Runtime& runtime); + /* * Returns a time point representing the current point in time. May be called * from multiple threads. diff --git a/packages/react-native/ReactCommon/react/utils/OnScopeExit.h b/packages/react-native/ReactCommon/react/utils/OnScopeExit.h new file mode 100644 index 00000000000000..ce8e907da3bdb0 --- /dev/null +++ b/packages/react-native/ReactCommon/react/utils/OnScopeExit.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook::react { + +template +class OnScopeExit { + public: + explicit OnScopeExit(const Lambda&& lambda) noexcept + : lambda_(std::move(lambda)) {} + + // Non-movable + OnScopeExit(const OnScopeExit&) = delete; + OnScopeExit(OnScopeExit&&) = delete; + + // Non-copyable + OnScopeExit& operator=(const OnScopeExit&) = delete; + OnScopeExit& operator=(OnScopeExit&&) = delete; + + ~OnScopeExit() noexcept { + lambda_(); + } + + private: + Lambda lambda_; +}; + +} // namespace facebook::react From 67b9628af588e8fc778d732fc387dbd48acf705e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Thu, 29 Feb 2024 13:12:49 -0800 Subject: [PATCH 048/361] Modify native module codegen to throw JS errors when passing null values for non-nullable arguments Summary: Changelog: [General][Breaking] Native modules using the codegen now throw an error when called with `null` for optional but not nullable arguments. ## Context Right now, if you have a native module using the codegen with a method like this: ``` someMethod(value?: number): void; ``` And you call it like this: ``` NativeModule.someMethod(null); ``` The app doesn't throw an error, but it should because this method shouldn't accept `null` according to its type definition. ## Changes This modifies the codegen to only check for `undefined` in those cases, otherwise trying to cast the value to the expected type and failing if it's `null`. NOTE: this is technically a breaking change, but if people are using Flow or TypeScript in their projects they're very unlikely to hit this case, because they would've complained if you tried to pass `null` in these cases. Reviewed By: cipolleschi Differential Revision: D54206289 fbshipit-source-id: 58f2f2f3009d203b96189d3c66d1ae98a9e4fb36 --- .../GenerateModuleCpp-test.js.snap | 56 +++++++++---------- .../generators/modules/GenerateModuleCpp.js | 6 ++ .../GenerateModuleCpp-test.js.snap | 6 +- 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap index 1fbcaf5a6e5e05..3130ea41984170 100644 --- a/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/e2e/__tests__/modules/__snapshots__/GenerateModuleCpp-test.js.snap @@ -643,7 +643,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSp static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -714,70 +714,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_voidF static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), - count <= 1 || args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), - count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), + count <= 1 || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), + count <= 2 || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asFunction(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asFunction(rt)) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); } @@ -1464,7 +1464,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSp static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleNullableAndOptionalCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { @@ -1535,70 +1535,70 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_voidF static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getBool(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getBool( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getNumber(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getNumber( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getString(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getString( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asString(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getArray(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getArray( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asArray(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getObject(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObject( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getObjectShape(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getObjectShape( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getAlias(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getAlias( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getRootTag(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getRootTag( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValue(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValue( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), - count <= 1 || args[1].isNull() || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), - count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asNumber()), + count <= 1 || args[1].isUndefined() ? std::nullopt : std::make_optional(args[1].asString(rt)), + count <= 2 || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValueWithCallback(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { static_cast(&turboModule)->getValueWithCallback( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asFunction(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt).asFunction(rt)) ); return jsi::Value::undefined(); } static jsi::Value __hostFunction_NativeSampleTurboModuleOptionalCxxSpecJSI_getValueWithPromise(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithPromise( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); } diff --git a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js index 2fa915d1943010..8928c0e8566062 100644 --- a/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js +++ b/packages/react-native-codegen/src/generators/modules/GenerateModuleCpp.js @@ -132,6 +132,12 @@ function serializeArg( const val = `args[${index}]`; const expression = callback(val); + // param?: T + if (optional && !nullable) { + // throw new Error('are we hitting this case? ' + moduleName); + return `count <= ${index} || ${val}.isUndefined() ? std::nullopt : std::make_optional(${expression})`; + } + // param: ?T // param?: ?T if (nullable || optional) { diff --git a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap index 7be9050fc36d06..dcfbcaa3e16023 100644 --- a/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap +++ b/packages/react-native-codegen/src/generators/modules/__tests__/__snapshots__/GenerateModuleCpp-test.js.snap @@ -61,7 +61,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_optionalMetho rt, count <= 0 ? throw jsi::JSError(rt, \\"Expected argument in position 0 to be passed\\") : args[0].asObject(rt), count <= 1 ? throw jsi::JSError(rt, \\"Expected argument in position 1 to be passed\\") : args[1].asObject(rt).asFunction(rt), - count <= 2 || args[2].isNull() || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt).asArray(rt)) + count <= 2 || args[2].isUndefined() ? std::nullopt : std::make_optional(args[2].asObject(rt).asArray(rt)) ); return jsi::Value::undefined(); } @@ -243,7 +243,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithP static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getWithWithOptionalArgs(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { auto result = static_cast(&turboModule)->getWithWithOptionalArgs( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asBool()) ); return result ? jsi::Value(std::move(*result)) : jsi::Value::null(); } @@ -591,7 +591,7 @@ static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithP static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getValueWithOptionalArg(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { return static_cast(&turboModule)->getValueWithOptionalArg( rt, - count <= 0 || args[0].isNull() || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) + count <= 0 || args[0].isUndefined() ? std::nullopt : std::make_optional(args[0].asObject(rt)) ); } static jsi::Value __hostFunction_NativeSampleTurboModuleCxxSpecJSI_getEnums(jsi::Runtime &rt, TurboModule &turboModule, const jsi::Value* args, size_t count) { From 2053364e5a3bdec07d534a3f2bb5b7de21f42ce9 Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Thu, 29 Feb 2024 14:19:29 -0800 Subject: [PATCH 049/361] Update hermes-parser and related packages in fbsource to 0.20.0 Summary: Bump hermes-parser and related packages to [0.20.0](https://github.com/facebook/hermes/blob/main/tools/hermes-parser/js/CHANGELOG.md). Changelog: [internal] Reviewed By: alexmckenley Differential Revision: D54368487 fbshipit-source-id: a5a05f1e499ff5d8bda4649433bd285f7215d3da --- package.json | 8 +- .../hermes-inspector-msggen/src/Property.js | 4 +- .../package.json | 2 +- packages/react-native-codegen/package.json | 4 +- .../Components/TextInput/TextInput.js | 16 ++-- .../Components/Touchable/Touchable.js | 4 +- .../Core/Devtools/parseErrorStack.js | 10 +-- .../Core/Devtools/parseHermesStack.js | 32 ++++---- .../Libraries/Interaction/TouchHistoryMath.js | 8 +- .../getNativeComponentAttributes.js | 4 +- .../Libraries/StyleSheet/StyleSheetTypes.js | 4 +- .../Libraries/Utilities/Platform.android.js | 8 +- .../__snapshots__/public-api-test.js.snap | 4 +- .../webapis/dom/nodes/ReadOnlyElement.js | 10 +-- .../private/webapis/dom/nodes/ReadOnlyNode.js | 10 +-- packages/rn-tester/js/RNTesterAppShared.js | 4 +- .../Accessibility/AccessibilityExample.js | 12 +-- .../PerformanceComparisonExample.js | 4 +- .../PlatformColor/PlatformColorExample.js | 4 +- .../js/examples/Pressable/PressableExample.js | 4 +- .../js/examples/Touchable/TouchableExample.js | 4 +- .../Lists/VirtualizedListCellRenderer.js | 4 +- scripts/npm-utils.js | 4 +- .../prepare-package-for-release.js | 4 +- yarn.lock | 74 +++++++++---------- 25 files changed, 121 insertions(+), 125 deletions(-) diff --git a/package.json b/package.json index edd4f2cfd6945d..3d2388850a613e 100644 --- a/package.json +++ b/package.json @@ -87,11 +87,11 @@ "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", - "flow-api-translator": "0.19.2", + "flow-api-translator": "0.20.0", "flow-bin": "^0.229.2", "glob": "^7.1.1", - "hermes-eslint": "0.19.2", - "hermes-transform": "0.19.2", + "hermes-eslint": "0.20.0", + "hermes-transform": "0.20.0", "inquirer": "^7.1.0", "jest": "^29.6.3", "jest-junit": "^10.0.0", @@ -104,7 +104,7 @@ "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "prettier": "2.8.8", - "prettier-plugin-hermes-parser": "0.19.2", + "prettier-plugin-hermes-parser": "0.20.0", "react": "18.2.0", "react-test-renderer": "18.2.0", "rimraf": "^3.0.2", diff --git a/packages/hermes-inspector-msggen/src/Property.js b/packages/hermes-inspector-msggen/src/Property.js index a673916035755f..3874d83c58c733 100644 --- a/packages/hermes-inspector-msggen/src/Property.js +++ b/packages/hermes-inspector-msggen/src/Property.js @@ -194,8 +194,8 @@ class RefProperty extends Property { return this.cyclical ? `{nullptr, deleter<${fullCppType}>}` : this.optional - ? '' - : '{}'; + ? '' + : '{}'; } } diff --git a/packages/react-native-babel-transformer/package.json b/packages/react-native-babel-transformer/package.json index 14c8f39b904ad8..3bac9a7b458bb9 100644 --- a/packages/react-native-babel-transformer/package.json +++ b/packages/react-native-babel-transformer/package.json @@ -17,7 +17,7 @@ "dependencies": { "@babel/core": "^7.20.0", "@react-native/babel-preset": "0.74.0", - "hermes-parser": "0.19.2", + "hermes-parser": "0.20.0", "nullthrows": "^1.1.1" }, "peerDependencies": { diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index fdde30bcd9c54c..dabc128e1904c3 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -31,7 +31,7 @@ "dependencies": { "@babel/parser": "^7.20.0", "glob": "^7.1.1", - "hermes-parser": "0.19.2", + "hermes-parser": "0.20.0", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", @@ -49,7 +49,7 @@ "@babel/plugin-transform-flow-strip-types": "^7.20.0", "@babel/preset-env": "^7.20.0", "chalk": "^4.0.0", - "hermes-estree": "0.19.2", + "hermes-estree": "0.20.0", "micromatch": "^4.0.4", "prettier": "2.8.8", "rimraf": "^3.0.2", diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index 7b522fe5dcb026..c8ead59c119222 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -1158,8 +1158,8 @@ function InternalTextInput(props: Props): React.Node { typeof props.value === 'string' ? props.value : typeof props.defaultValue === 'string' - ? props.defaultValue - : ''; + ? props.defaultValue + : ''; // This is necessary in case native updates the text and JS decides // that the update should be ignored and we should stick with the value @@ -1736,12 +1736,12 @@ const ExportedForwardRef: React.AbstractComponent< textContentType != null ? textContentType : Platform.OS === 'ios' && - autoComplete && - autoComplete in autoCompleteWebToTextContentTypeMap - ? // $FlowFixMe[invalid-computed-prop] - // $FlowFixMe[prop-missing] - autoCompleteWebToTextContentTypeMap[autoComplete] - : textContentType + autoComplete && + autoComplete in autoCompleteWebToTextContentTypeMap + ? // $FlowFixMe[invalid-computed-prop] + // $FlowFixMe[prop-missing] + autoCompleteWebToTextContentTypeMap[autoComplete] + : textContentType } {...restProps} forwardedRef={forwardedRef} diff --git a/packages/react-native/Libraries/Components/Touchable/Touchable.js b/packages/react-native/Libraries/Components/Touchable/Touchable.js index c34ca4f8b85ec6..899385a995a89d 100644 --- a/packages/react-native/Libraries/Components/Touchable/Touchable.js +++ b/packages/react-native/Libraries/Components/Touchable/Touchable.js @@ -40,8 +40,8 @@ const extractSingleTouch = (nativeEvent: { return !hasTouches && hasChangedTouches ? changedTouches[0] : hasTouches - ? touches[0] - : nativeEvent; + ? touches[0] + : nativeEvent; }; /** diff --git a/packages/react-native/Libraries/Core/Devtools/parseErrorStack.js b/packages/react-native/Libraries/Core/Devtools/parseErrorStack.js index 9b84537c3d9863..d52ae1faffade8 100644 --- a/packages/react-native/Libraries/Core/Devtools/parseErrorStack.js +++ b/packages/react-native/Libraries/Core/Devtools/parseErrorStack.js @@ -47,11 +47,11 @@ function parseErrorStack(errorStack?: string): Array { const parsedStack = Array.isArray(errorStack) ? errorStack : global.HermesInternal - ? convertHermesStack(parseHermesStack(errorStack)) - : stacktraceParser.parse(errorStack).map((frame): StackFrame => ({ - ...frame, - column: frame.column != null ? frame.column - 1 : null, - })); + ? convertHermesStack(parseHermesStack(errorStack)) + : stacktraceParser.parse(errorStack).map((frame): StackFrame => ({ + ...frame, + column: frame.column != null ? frame.column - 1 : null, + })); return parsedStack; } diff --git a/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js b/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js index 1193afd88f9507..f7b6929834b388 100644 --- a/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js +++ b/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js @@ -88,25 +88,25 @@ function parseLine(line: string): ?HermesStackEntry { asFrame[2] === 'native' ? {type: 'NATIVE'} : asFrame[3] === 'address at ' - ? isInternalBytecodeSourceUrl(asFrame[4]) - ? { - type: 'INTERNAL_BYTECODE', - sourceUrl: asFrame[4], - line1Based: Number.parseInt(asFrame[5], 10), - virtualOffset0Based: Number.parseInt(asFrame[6], 10), - } + ? isInternalBytecodeSourceUrl(asFrame[4]) + ? { + type: 'INTERNAL_BYTECODE', + sourceUrl: asFrame[4], + line1Based: Number.parseInt(asFrame[5], 10), + virtualOffset0Based: Number.parseInt(asFrame[6], 10), + } + : { + type: 'BYTECODE', + sourceUrl: asFrame[4], + line1Based: Number.parseInt(asFrame[5], 10), + virtualOffset0Based: Number.parseInt(asFrame[6], 10), + } : { - type: 'BYTECODE', + type: 'SOURCE', sourceUrl: asFrame[4], line1Based: Number.parseInt(asFrame[5], 10), - virtualOffset0Based: Number.parseInt(asFrame[6], 10), - } - : { - type: 'SOURCE', - sourceUrl: asFrame[4], - line1Based: Number.parseInt(asFrame[5], 10), - column1Based: Number.parseInt(asFrame[6], 10), - }, + column1Based: Number.parseInt(asFrame[6], 10), + }, }; } const asSkipped = line.match(RE_SKIPPED); diff --git a/packages/react-native/Libraries/Interaction/TouchHistoryMath.js b/packages/react-native/Libraries/Interaction/TouchHistoryMath.js index cbcbe2606de9ad..aec0d66913137b 100644 --- a/packages/react-native/Libraries/Interaction/TouchHistoryMath.js +++ b/packages/react-native/Libraries/Interaction/TouchHistoryMath.js @@ -48,10 +48,10 @@ const TouchHistoryMath = { ofCurrent && isXAxis ? oneTouchData.currentPageX : ofCurrent && !isXAxis - ? oneTouchData.currentPageY - : !ofCurrent && isXAxis - ? oneTouchData.previousPageX - : oneTouchData.previousPageY; + ? oneTouchData.currentPageY + : !ofCurrent && isXAxis + ? oneTouchData.previousPageX + : oneTouchData.previousPageY; count = 1; } } else { diff --git a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js index 318a2d18a4e18e..d768a6487187f9 100644 --- a/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js +++ b/packages/react-native/Libraries/ReactNative/getNativeComponentAttributes.js @@ -77,8 +77,8 @@ function getNativeComponentAttributes(uiViewClassName: string): any { ? true : {process} : process == null - ? {diff} - : {diff, process}; + ? {diff} + : {diff, process}; } // Unfortunately, the current setup declares style properties as top-level diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index d4b5ab921132fc..c39bcb97ea3ca5 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -918,5 +918,5 @@ export type ____FlattenStyleProp_Internal< > = TStyleProp extends null | void | false | '' ? empty : TStyleProp extends $ReadOnlyArray - ? ____FlattenStyleProp_Internal - : TStyleProp; + ? ____FlattenStyleProp_Internal + : TStyleProp; diff --git a/packages/react-native/Libraries/Utilities/Platform.android.js b/packages/react-native/Libraries/Utilities/Platform.android.js index 5272465aa7c5ac..e2cfdf8aa64285 100644 --- a/packages/react-native/Libraries/Utilities/Platform.android.js +++ b/packages/react-native/Libraries/Utilities/Platform.android.js @@ -78,10 +78,10 @@ const Platform: PlatformType = { ? // $FlowFixMe[incompatible-return] spec.android : 'native' in spec - ? // $FlowFixMe[incompatible-return] - spec.native - : // $FlowFixMe[incompatible-return] - spec.default, + ? // $FlowFixMe[incompatible-return] + spec.native + : // $FlowFixMe[incompatible-return] + spec.default, }; module.exports = Platform; diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 591a451b02b748..54740e29317cee 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -7750,8 +7750,8 @@ export type ____FlattenStyleProp_Internal< > = TStyleProp extends null | void | false | \\"\\" ? empty : TStyleProp extends $ReadOnlyArray - ? ____FlattenStyleProp_Internal - : TStyleProp; + ? ____FlattenStyleProp_Internal + : TStyleProp; " `; diff --git a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js index 46fb34c1e8f555..e1b58a294fae5d 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js +++ b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyElement.js @@ -151,9 +151,8 @@ export default class ReadOnlyElement extends ReadOnlyNode { const node = getShadowNode(this); if (node != null) { - const scrollPosition = nullthrows(getFabricUIManager()).getScrollPosition( - node, - ); + const scrollPosition = + nullthrows(getFabricUIManager()).getScrollPosition(node); if (scrollPosition != null) { return scrollPosition[0]; } @@ -166,9 +165,8 @@ export default class ReadOnlyElement extends ReadOnlyNode { const node = getShadowNode(this); if (node != null) { - const scrollPosition = nullthrows(getFabricUIManager()).getScrollPosition( - node, - ); + const scrollPosition = + nullthrows(getFabricUIManager()).getScrollPosition(node); if (scrollPosition != null) { return scrollPosition[1]; } diff --git a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js index 2eb5d742ff2cc3..2c29c2d105af85 100644 --- a/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js +++ b/packages/react-native/src/private/webapis/dom/nodes/ReadOnlyNode.js @@ -125,9 +125,8 @@ export default class ReadOnlyNode { return null; } - const parentInstanceHandle = nullthrows(getFabricUIManager()).getParentNode( - shadowNode, - ); + const parentInstanceHandle = + nullthrows(getFabricUIManager()).getParentNode(shadowNode); if (parentInstanceHandle == null) { return null; @@ -323,9 +322,8 @@ export function getChildNodes( return []; } - const childNodeInstanceHandles = nullthrows( - getFabricUIManager(), - ).getChildNodes(shadowNode); + const childNodeInstanceHandles = + nullthrows(getFabricUIManager()).getChildNodes(shadowNode); return childNodeInstanceHandles .map(instanceHandle => getPublicInstanceFromInternalInstanceHandle(instanceHandle), diff --git a/packages/rn-tester/js/RNTesterAppShared.js b/packages/rn-tester/js/RNTesterAppShared.js index 131a838b976477..87cb6b69dfe47a 100644 --- a/packages/rn-tester/js/RNTesterAppShared.js +++ b/packages/rn-tester/js/RNTesterAppShared.js @@ -217,8 +217,8 @@ const RNTesterApp = ({ activeModuleTitle != null ? activeModuleTitle : screen === Screens.COMPONENTS - ? 'Components' - : 'APIs'; + ? 'Components' + : 'APIs'; const activeExampleList = screen === Screens.COMPONENTS ? examplesList.components : examplesList.apis; diff --git a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js index f6d9126c67bba3..bd14a80134039c 100644 --- a/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js +++ b/packages/rn-tester/js/examples/Accessibility/AccessibilityExample.js @@ -645,8 +645,8 @@ class NestedCheckBox extends React.Component< checkbox2 && this.state.checkbox3 ? true : checkbox2 || this.state.checkbox3 - ? 'mixed' - : false, + ? 'mixed' + : false, }); }; @@ -659,8 +659,8 @@ class NestedCheckBox extends React.Component< this.state.checkbox2 && checkbox3 ? true : this.state.checkbox2 || checkbox3 - ? 'mixed' - : false, + ? 'mixed' + : false, }); }; @@ -680,8 +680,8 @@ class NestedCheckBox extends React.Component< this.state.checkbox1 === 'mixed' ? mixedCheckboxImageSource : this.state.checkbox1 - ? checkImageSource - : uncheckImageSource + ? checkImageSource + : uncheckImageSource } /> Meat diff --git a/packages/rn-tester/js/examples/Performance/PerformanceComparisonExample.js b/packages/rn-tester/js/examples/Performance/PerformanceComparisonExample.js index 896b8defbb8568..fb0ac33a9cd023 100644 --- a/packages/rn-tester/js/examples/Performance/PerformanceComparisonExample.js +++ b/packages/rn-tester/js/examples/Performance/PerformanceComparisonExample.js @@ -84,8 +84,8 @@ function PerfExampleWrapper(props: { {loadExample === SHOW_BAD_EXAMPLE ? badExampleContents : loadExample === SHOW_GOOD_EXAMPLE - ? goodExampleContents - : null} + ? goodExampleContents + : null} diff --git a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js index 2437e8509cb211..c8f4bd6baccdeb 100644 --- a/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js +++ b/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js @@ -297,8 +297,8 @@ function VariantColorsExample() { Platform.OS === 'ios' ? DynamicColorIOS({light: 'red', dark: 'blue'}) : Platform.OS === 'android' - ? PlatformColor('?attr/colorAccent') - : 'red', + ? PlatformColor('?attr/colorAccent') + : 'red', }} /> diff --git a/packages/rn-tester/js/examples/Pressable/PressableExample.js b/packages/rn-tester/js/examples/Pressable/PressableExample.js index 5266d69bb41376..6dfe4be3031ed3 100644 --- a/packages/rn-tester/js/examples/Pressable/PressableExample.js +++ b/packages/rn-tester/js/examples/Pressable/PressableExample.js @@ -244,8 +244,8 @@ function PressableNativeMethods() { {status == null ? 'Missing Ref!' : status === true - ? 'Native Methods Exist' - : 'Native Methods Missing!'} + ? 'Native Methods Exist' + : 'Native Methods Missing!'} diff --git a/packages/rn-tester/js/examples/Touchable/TouchableExample.js b/packages/rn-tester/js/examples/Touchable/TouchableExample.js index 4f978e9d5993d8..7827437cca1c03 100644 --- a/packages/rn-tester/js/examples/Touchable/TouchableExample.js +++ b/packages/rn-tester/js/examples/Touchable/TouchableExample.js @@ -321,8 +321,8 @@ function TouchableNativeMethodChecker< {status == null ? 'Missing Ref!' : status === true - ? 'Native Methods Exist' - : 'Native Methods Missing!'} + ? 'Native Methods Exist' + : 'Native Methods Missing!'} ); diff --git a/packages/virtualized-lists/Lists/VirtualizedListCellRenderer.js b/packages/virtualized-lists/Lists/VirtualizedListCellRenderer.js index afe3eea7ad4bc9..d67f19884bdedc 100644 --- a/packages/virtualized-lists/Lists/VirtualizedListCellRenderer.js +++ b/packages/virtualized-lists/Lists/VirtualizedListCellRenderer.js @@ -203,8 +203,8 @@ export default class CellRenderer extends React.Component< ? [styles.rowReverse, inversionStyle] : [styles.columnReverse, inversionStyle] : horizontal - ? [styles.row, inversionStyle] - : inversionStyle; + ? [styles.row, inversionStyle] + : inversionStyle; const result = !CellRendererComponent ? ( Date: Thu, 29 Feb 2024 15:46:43 -0800 Subject: [PATCH 050/361] Add BridgelessCatalystInstance as a placeholder for backwards comptability of legacy APIs of CatalystInstance Summary: In order to make the legacy APIs of Catalyst Instance backwards compatible, introducing a regular class that implements CatalystInstance so as to make these APIs available for folks in Bridgeless mode as well. Changelog: [Internal] internal Reviewed By: RSNara Differential Revision: D54093013 fbshipit-source-id: f494c05e79f570883f9b5374cd177862970304c0 --- .../ReactAndroid/api/ReactAndroid.api | 41 ++++ .../react/bridge/CatalystInstance.java | 2 +- .../react/bridge/CatalystInstanceImpl.java | 3 +- .../react/bridge/JSIModuleRegistry.java | 4 +- .../react/bridge/NativeArrayInterface.java | 2 +- .../runtime/BridgelessCatalystInstance.kt | 200 ++++++++++++++++++ 6 files changed, 247 insertions(+), 5 deletions(-) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index a7d34c4324c94f..d1144df5d315b5 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -949,6 +949,10 @@ public abstract class com/facebook/react/bridge/NativeArray : com/facebook/react public fun toString ()Ljava/lang/String; } +public abstract interface class com/facebook/react/bridge/NativeArrayInterface { + public abstract fun toString ()Ljava/lang/String; +} + public abstract class com/facebook/react/bridge/NativeMap { public fun (Lcom/facebook/jni/HybridData;)V public fun toString ()Ljava/lang/String; @@ -3565,6 +3569,43 @@ public abstract class com/facebook/react/runtime/BindingsInstaller { public fun (Lcom/facebook/jni/HybridData;)V } +public final class com/facebook/react/runtime/BridgelessCatalystInstance : com/facebook/react/bridge/CatalystInstance { + public fun ()V + public fun addBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V + public fun addJSIModules (Ljava/util/List;)V + public fun callFunction (Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/NativeArray;)V + public fun destroy ()V + public fun extendNativeModules (Lcom/facebook/react/bridge/NativeModuleRegistry;)V + public fun getFabricUIManager ()Lcom/facebook/react/bridge/UIManager; + public fun getJSCallInvokerHolder ()Lcom/facebook/react/turbomodule/core/interfaces/CallInvokerHolder; + public fun getJSIModule (Lcom/facebook/react/bridge/JSIModuleType;)Lcom/facebook/react/bridge/JSIModule; + public fun getJSModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/JavaScriptModule; + public fun getJavaScriptContextHolder ()Lcom/facebook/react/bridge/JavaScriptContextHolder; + public fun getNativeMethodCallInvokerHolder ()Lcom/facebook/react/turbomodule/core/interfaces/NativeMethodCallInvokerHolder; + public fun getNativeModule (Ljava/lang/Class;)Lcom/facebook/react/bridge/NativeModule; + public fun getNativeModule (Ljava/lang/String;)Lcom/facebook/react/bridge/NativeModule; + public fun getNativeModules ()Ljava/util/Collection; + public fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; + public fun getRuntimeExecutor ()Lcom/facebook/react/bridge/RuntimeExecutor; + public fun getRuntimeScheduler ()Lcom/facebook/react/bridge/RuntimeScheduler; + public fun getSourceURL ()Ljava/lang/String; + public fun handleMemoryPressure (I)V + public fun hasNativeModule (Ljava/lang/Class;)Z + public fun hasRunJSBundle ()Z + public fun invokeCallback (ILcom/facebook/react/bridge/NativeArrayInterface;)V + public fun isDestroyed ()Z + public fun loadScriptFromAssets (Landroid/content/res/AssetManager;Ljava/lang/String;Z)V + public fun loadScriptFromFile (Ljava/lang/String;Ljava/lang/String;Z)V + public fun loadSplitBundleFromFile (Ljava/lang/String;Ljava/lang/String;)V + public fun registerSegment (ILjava/lang/String;)V + public fun removeBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V + public fun runJSBundle ()V + public fun setFabricUIManager (Lcom/facebook/react/bridge/UIManager;)V + public fun setSourceURLs (Ljava/lang/String;Ljava/lang/String;)V + public fun setTurboModuleManager (Lcom/facebook/react/bridge/JSIModule;)V + public fun setTurboModuleRegistry (Lcom/facebook/react/internal/turbomodule/core/interfaces/TurboModuleRegistry;)V +} + public class com/facebook/react/runtime/CoreReactPackage$$ReactModuleInfoProvider : com/facebook/react/module/model/ReactModuleInfoProvider { public fun ()V public fun getReactModuleInfos ()Ljava/util/Map; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java index 0ee0dd6df275ee..b2e2d7cadc1ff1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstance.java @@ -120,7 +120,7 @@ public interface CatalystInstance RuntimeScheduler getRuntimeScheduler(); @Deprecated - void addJSIModules(List jsiModules); + void addJSIModules(List> jsiModules); /** * Returns a hybrid object that contains a pointer to a JS CallInvoker, which is used to schedule diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java index 3658f68cac44f7..f86dffbf341dd2 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/CatalystInstanceImpl.java @@ -537,7 +537,8 @@ public JavaScriptContextHolder getJavaScriptContextHolder() { public native RuntimeScheduler getRuntimeScheduler(); @Override - public void addJSIModules(List jsiModules) { + @Deprecated + public void addJSIModules(List> jsiModules) { mJSIModuleRegistry.registerModules(jsiModules); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java index e81b361d16841d..90d5cde4fcbce5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JSIModuleRegistry.java @@ -26,8 +26,8 @@ public JSIModule getModule(JSIModuleType moduleType) { return Assertions.assertNotNull(jsiModuleHolder.getJSIModule()); } - public void registerModules(List jsiModules) { - for (JSIModuleSpec spec : jsiModules) { + public void registerModules(List> jsiModules) { + for (JSIModuleSpec spec : jsiModules) { mModules.put(spec.getJSIModuleType(), new JSIModuleHolder(spec)); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeArrayInterface.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeArrayInterface.java index a410a3aeb289b3..6791df05e6d510 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeArrayInterface.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/NativeArrayInterface.java @@ -7,7 +7,7 @@ package com.facebook.react.bridge; -interface NativeArrayInterface { +public interface NativeArrayInterface { @Override String toString(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt new file mode 100644 index 00000000000000..f7388357f27555 --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt @@ -0,0 +1,200 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.runtime + +import android.content.res.AssetManager +import com.facebook.proguard.annotations.DoNotStrip +import com.facebook.react.bridge.CatalystInstance +import com.facebook.react.bridge.JSIModule +import com.facebook.react.bridge.JSIModuleSpec +import com.facebook.react.bridge.JSIModuleType +import com.facebook.react.bridge.JavaScriptContextHolder +import com.facebook.react.bridge.JavaScriptModule +import com.facebook.react.bridge.NativeArray +import com.facebook.react.bridge.NativeArrayInterface +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.NativeModuleRegistry +import com.facebook.react.bridge.NotThreadSafeBridgeIdleDebugListener +import com.facebook.react.bridge.RuntimeExecutor +import com.facebook.react.bridge.RuntimeScheduler +import com.facebook.react.bridge.UIManager +import com.facebook.react.bridge.queue.ReactQueueConfiguration +import com.facebook.react.common.annotations.DeprecatedInNewArchitecture +import com.facebook.react.common.annotations.VisibleForTesting +import com.facebook.react.internal.turbomodule.core.interfaces.TurboModuleRegistry +import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder +import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHolder + +@DoNotStrip +@DeprecatedInNewArchitecture +class BridgelessCatalystInstance : CatalystInstance { + override fun handleMemoryPressure(level: Int) { + throw UnsupportedOperationException("Unimplemented method 'handleMemoryPressure'") + } + + override fun loadScriptFromAssets( + assetManager: AssetManager, + assetURL: String, + loadSynchronously: Boolean + ) { + throw UnsupportedOperationException("Unimplemented method 'loadScriptFromAssets'") + } + + override fun loadScriptFromFile(fileName: String, sourceURL: String, loadSynchronously: Boolean) { + throw UnsupportedOperationException("Unimplemented method 'loadScriptFromFile'") + } + + override fun loadSplitBundleFromFile(fileName: String, sourceURL: String) { + throw UnsupportedOperationException("Unimplemented method 'loadSplitBundleFromFile'") + } + + override fun setSourceURLs(deviceURL: String, remoteURL: String) { + throw UnsupportedOperationException("Unimplemented method 'setSourceURLs'") + } + + override fun runJSBundle() { + throw UnsupportedOperationException("Unimplemented method 'runJSBundle'") + } + + override fun hasRunJSBundle(): Boolean { + throw UnsupportedOperationException("Unimplemented method 'hasRunJSBundle'") + } + + override fun getSourceURL(): String? { + throw UnsupportedOperationException("Unimplemented method 'getSourceURL'") + } + + @DoNotStrip + override fun invokeCallback(callbackID: Int, arguments: NativeArrayInterface) { + throw UnsupportedOperationException("Unimplemented method 'invokeCallback'") + } + + override fun callFunction(module: String, method: String, arguments: NativeArray) { + throw UnsupportedOperationException("Unimplemented method 'callFunction'") + } + + override fun destroy() { + throw UnsupportedOperationException("Unimplemented method 'destroy'") + } + + override fun isDestroyed(): Boolean { + throw UnsupportedOperationException("Unimplemented method 'isDestroyed'") + } + + @VisibleForTesting + override fun initialize() { + throw UnsupportedOperationException("Unimplemented method 'initialize'") + } + + override fun getReactQueueConfiguration(): ReactQueueConfiguration { + throw UnsupportedOperationException("Unimplemented method 'getReactQueueConfiguration'") + } + + override fun getJSModule(jsInterface: Class): T { + throw UnsupportedOperationException("Unimplemented method 'getJSModule'") + } + + override fun hasNativeModule(nativeModuleInterface: Class): Boolean { + throw UnsupportedOperationException("Unimplemented method 'hasNativeModule'") + } + + override fun getNativeModule(nativeModuleInterface: Class): T? { + throw UnsupportedOperationException("Unimplemented method 'getNativeModule'") + } + + override fun getNativeModule(moduleName: String): NativeModule? { + throw UnsupportedOperationException("Unimplemented method 'getNativeModule'") + } + + @Deprecated( + message = + "getJSIModule(JSIModuleType moduleType) is deprecated and will be deleted in the future. Please use ReactInstanceEventListener to subscribe for react instance events instead.") + override fun getJSIModule(moduleType: JSIModuleType): JSIModule { + throw UnsupportedOperationException("Unimplemented method 'getJSIModule'") + } + + override fun getNativeModules(): Collection { + throw UnsupportedOperationException("Unimplemented method 'getNativeModules'") + } + + override fun extendNativeModules(modules: NativeModuleRegistry) { + throw UnsupportedOperationException("Unimplemented method 'extendNativeModules'") + } + + override fun addBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) { + throw UnsupportedOperationException("Unimplemented method 'addBridgeIdleDebugListener'") + } + + override fun removeBridgeIdleDebugListener(listener: NotThreadSafeBridgeIdleDebugListener) { + throw UnsupportedOperationException("Unimplemented method 'removeBridgeIdleDebugListener'") + } + + override fun registerSegment(segmentId: Int, path: String) { + throw UnsupportedOperationException("Unimplemented method 'registerSegment'") + } + + @VisibleForTesting + override fun setGlobalVariable(propName: String, jsonValue: String) { + throw UnsupportedOperationException("Unimplemented method 'setGlobalVariable'") + } + + @Deprecated(message = "This API is unsupported in the New Architecture.") + override fun getJavaScriptContextHolder(): JavaScriptContextHolder { + throw UnsupportedOperationException("Unimplemented method 'getJavaScriptContextHolder'") + } + + override fun getRuntimeExecutor(): RuntimeExecutor { + throw UnsupportedOperationException("Unimplemented method 'getRuntimeExecutor'") + } + + override fun getRuntimeScheduler(): RuntimeScheduler { + throw UnsupportedOperationException("Unimplemented method 'getRuntimeScheduler'") + } + + @Deprecated(message = "This API is unsupported in the New Architecture.") + override fun addJSIModules(jsiModules: List>) { + throw UnsupportedOperationException("Unimplemented method 'addJSIModules'") + } + + override fun getJSCallInvokerHolder(): CallInvokerHolder { + throw UnsupportedOperationException("Unimplemented method 'getJSCallInvokerHolder'") + } + + override fun getNativeMethodCallInvokerHolder(): NativeMethodCallInvokerHolder { + throw UnsupportedOperationException("Unimplemented method 'getNativeMethodCallInvokerHolder'") + } + + @Deprecated( + message = + "setTurboModuleManager(JSIModule getter) is deprecated and will be deleted in the future. Please use setTurboModuleRegistry(TurboModuleRegistry turboModuleRegistry) instead.", + replaceWith = ReplaceWith("setTurboModuleRegistry(turboModuleRegistry)")) + override fun setTurboModuleManager(getter: JSIModule) { + throw UnsupportedOperationException("Unimplemented method 'setTurboModuleManager'") + } + + @DeprecatedInNewArchitecture( + message = + "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") + override fun setTurboModuleRegistry(turboModuleRegistry: TurboModuleRegistry) { + throw UnsupportedOperationException("Unimplemented method 'setTurboModuleRegistry'") + } + + @DeprecatedInNewArchitecture( + message = + "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") + override fun setFabricUIManager(fabricUIManager: UIManager) { + throw UnsupportedOperationException("Unimplemented method 'setFabricUIManager'") + } + + @DeprecatedInNewArchitecture( + message = + "This method will be deprecated later as part of Stable APIs with bridge removal and not encouraged usage.") + override fun getFabricUIManager(): UIManager { + throw UnsupportedOperationException("Unimplemented method 'getFabricUIManager'") + } +} From 4cfac8eea63129059559f0a65c038dfe95e12d7c Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Fri, 1 Mar 2024 02:38:48 -0800 Subject: [PATCH 051/361] Restore Content-Length header in inspector-proxy JSON responses Summary: Changelog: [General][Fixed] Re-enable listing Hermes debugger targets in chrome://inspect, broken in 0.74 RC Fixes https://github.com/facebook/react-native/issues/43259. Reverts D52958725 and fixes the original `Content-Length` Unicode bug using a different approach. Reviewed By: fabriziocucci Differential Revision: D54409847 fbshipit-source-id: ed5bb464ab67f37535947646b124814d8bbf797c --- .../__tests__/InspectorProxyHttpApi-test.js | 66 ++++++++++++++++++- .../src/inspector-proxy/InspectorProxy.js | 1 + 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js index e601f219f06324..e5501b8e3ceb66 100644 --- a/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js +++ b/packages/dev-middleware/src/__tests__/InspectorProxyHttpApi-test.js @@ -14,11 +14,13 @@ import type { JsonVersionResponse, } from '../inspector-proxy/types'; -import {fetchJson} from './FetchUtils'; +import {fetchJson, fetchLocal} from './FetchUtils'; import {createDeviceMock} from './InspectorDeviceUtils'; import {withAbortSignalForEachTest} from './ResourceUtils'; import {withServerForEachTest} from './ServerUtils'; +import nullthrows from 'nullthrows'; + // Must be greater than or equal to PAGES_POLLING_INTERVAL in `InspectorProxy.js`. const PAGES_POLLING_DELAY = 1000; @@ -309,5 +311,67 @@ describe('inspector proxy HTTP API', () => { } }); }); + + test('handles Unicode data safely', async () => { + const device = await createDeviceMock( + `${serverRef.serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`, + autoCleanup.signal, + ); + try { + device.getPages.mockImplementation(() => [ + { + app: 'bar-app 📱', + id: 'page1 🛂', + title: 'bar-title 📰', + vm: 'bar-vm 🤖', + }, + ]); + + jest.advanceTimersByTime(PAGES_POLLING_DELAY); + + const json = await fetchJson( + `${serverRef.serverBaseUrl}${endpoint}`, + ); + expect(json).toEqual([ + expect.objectContaining({ + description: 'bar-app 📱', + deviceName: 'foo', + id: 'device1-page1 🛂', + title: 'bar-title 📰', + vm: 'bar-vm 🤖', + }), + ]); + } finally { + device.close(); + } + }); + + test('includes a valid Content-Length header', async () => { + // NOTE: This test is needed because chrome://inspect's HTTP client is picky + // and doesn't accept responses without a Content-Length header. + const device = await createDeviceMock( + `${serverRef.serverBaseWsUrl}/inspector/device?device=device1&name=foo&app=bar`, + autoCleanup.signal, + ); + try { + device.getPages.mockImplementation(() => [ + { + app: 'bar-app', + id: 'page1', + title: 'bar-title', + vm: 'bar-vm', + }, + ]); + + jest.advanceTimersByTime(PAGES_POLLING_DELAY); + + const response = await fetchLocal( + `${serverRef.serverBaseUrl}${endpoint}`, + ); + expect(response.headers.get('Content-Length')).not.toBeNull(); + } finally { + device.close(); + } + }); }); }); diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index 066fa44cc3d536..0f4146d5e01884 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -167,6 +167,7 @@ export default class InspectorProxy implements InspectorProxyQueries { response.writeHead(200, { 'Content-Type': 'application/json; charset=UTF-8', 'Cache-Control': 'no-cache', + 'Content-Length': Buffer.byteLength(data).toString(), Connection: 'close', }); response.end(data); From 4d2262b8d2b38eddbdfb2264a33f87c28aa7712f Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Fri, 1 Mar 2024 03:12:08 -0800 Subject: [PATCH 052/361] Add scrollEventThrottle to validAttributes to ScrollView view config on Android Summary: The `scrollEventThrottle` prop is missing in the ViewConfig for ScrollView for the Android platform. Because of that it was ignored by native in the New Architecture. This diff fixes that. Changelog: [Android][Fixed] - Add support for scrollEventThrottle for ScrollView on the New Architecture. Reviewed By: fkgozali Differential Revision: D54303157 fbshipit-source-id: 824f32c2f9fb3958271b094bbfc770992a4335e1 --- .../Libraries/Components/ScrollView/ScrollViewNativeComponent.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 50d95a9de87f1e..7c250c9a30b9ba 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -60,6 +60,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = sendMomentumEvents: true, borderRadius: true, nestedScrollEnabled: true, + scrollEventThrottle: true, borderStyle: true, borderRightColor: { process: require('../../StyleSheet/processColor').default, From d6a44e632a7ffbd60b90dac410294947cd82f2d8 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Fri, 1 Mar 2024 03:59:08 -0800 Subject: [PATCH 053/361] getChildAtWithSubviewClippingEnabled should be @Nullable Summary: The RemoveDeleteTree operation assumes it can safely call getChildAt with indices that are out of bounds to find all the children. `getChildAtWithSubviewClippingEnabled` was unnecessarily stricter than `getChildAt` and would crash in such cases. Changelog: [Android][Fixed] - Fix crash in `getChildAtWithSubviewClippingEnabled` Reviewed By: NickGerleman Differential Revision: D54380975 fbshipit-source-id: 17e93c685cd07b02dc20efa2fae89090d6e38457 --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index 793a0f9a584300..af5dea7170d488 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -637,8 +637,11 @@ protected void dispatchSetPressed(boolean pressed) { return mAllChildrenCount; } - /*package*/ View getChildAtWithSubviewClippingEnabled(int index) { - return Assertions.assertNotNull(mAllChildren)[index]; + /*package*/ @Nullable + View getChildAtWithSubviewClippingEnabled(int index) { + return index >= 0 && index < mAllChildrenCount + ? Assertions.assertNotNull(mAllChildren)[index] + : null; } /*package*/ void addViewWithSubviewClippingEnabled(View child, int index) { From 571ef5660abb82d6ed842b6d5d8a9daf152177f0 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 1 Mar 2024 04:11:40 -0800 Subject: [PATCH 054/361] introduce experimental props to ScrollView - JS part (#43265) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43265 changelog: [internal] Add experimental props to control scroll speed on iOS. Reviewed By: rubennorte Differential Revision: D53757138 fbshipit-source-id: e4d9787240ad421d3e4a1d50c860d7bcb26f43b5 --- .../Components/ScrollView/ScrollView.js | 21 ++++++++++++++++++- .../ScrollView/ScrollViewNativeComponent.js | 1 + 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js index aab9f20baf2112..d8814ccefc4846 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollView.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollView.js @@ -438,6 +438,20 @@ export type Props = $ReadOnly<{| * - `'fast'`: 0.99 on iOS, 0.9 on Android */ decelerationRate?: ?DecelerationRateType, + + /** + * *Experimental, iOS Only*. The API is experimental and will change in future releases. + * + * Controls how much distance is travelled after user stops scrolling. + * Value greater than 1 will increase the distance travelled. + * Value less than 1 will decrease the distance travelled. + * + * @deprecated + * + * The default value is 1. + */ + experimental_endDraggingSensitivityMultiplier?: ?number, + /** * When true, the scroll view's children are arranged horizontally in a row * instead of vertically in a column. The default value is false. @@ -1733,8 +1747,11 @@ class ScrollView extends React.Component { this.props.horizontal === true ? styles.baseHorizontal : styles.baseVertical; + + const {experimental_endDraggingSensitivityMultiplier, ...otherProps} = + this.props; const props = { - ...this.props, + ...otherProps, alwaysBounceHorizontal, alwaysBounceVertical, style: StyleSheet.compose(baseStyle, this.props.style), @@ -1759,6 +1776,8 @@ class ScrollView extends React.Component { onTouchStart: this._handleTouchStart, onTouchCancel: this._handleTouchCancel, onScroll: this._handleScroll, + endDraggingSensitivityMultiplier: + experimental_endDraggingSensitivityMultiplier, scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle, diff --git a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js index 7c250c9a30b9ba..8c1126849022d2 100644 --- a/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js +++ b/packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js @@ -132,6 +132,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig = }, contentInsetAdjustmentBehavior: true, decelerationRate: true, + endDraggingSensitivityMultiplier: true, directionalLockEnabled: true, disableIntervalMomentum: true, indicatorStyle: true, From d9b0f15c844abce5e97edfd401656d84d0c84133 Mon Sep 17 00:00:00 2001 From: jayshah Date: Fri, 1 Mar 2024 04:59:32 -0800 Subject: [PATCH 055/361] fix(iOS): add extended check for content typeapplication/javascript (#43262) Summary: When used with expo, JS code content type is `application/javascript; charset=UTF-8` instead of just `application/javascript`, We have a really large bundle and the application shows stuck at "Bundling 100%" and does not show "Downloading 1..100%". Here we improve the check for the content type to correctly show the progress. ## Changelog: [IOS] [FIXED] - Fixed headers content type check for iOS bundle download [ANDROID] [CHANGED] - Expose `rrc_textinput` via prefab. Pull Request resolved: https://github.com/facebook/react-native/pull/43274 Reviewed By: cipolleschi Differential Revision: D54482657 Pulled By: cortinico fbshipit-source-id: ca7f4127f1808f841d88925238666e837de75bd0 --- packages/react-native/ReactAndroid/build.gradle.kts | 7 +++++++ .../ReactAndroid/cmake-utils/ReactNative-application.cmake | 2 ++ 2 files changed, 9 insertions(+) diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 17d75f688275e6..38fdca228cb72e 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -125,6 +125,11 @@ val preparePrefab by "react/renderer/components/view/"), Pair("../ReactCommon/react/renderer/components/view/platform/android/", ""), )), + PrefabPreprocessingEntry( + "rrc_textinput", + Pair( + "../ReactCommon/react/renderer/components/textinput/", + "react/renderer/components/androidtextinput/")), PrefabPreprocessingEntry( "rrc_legacyviewmanagerinterop", Pair( @@ -540,6 +545,7 @@ android { "rrc_image", "rrc_root", "rrc_view", + "rrc_textinput", "rrc_legacyviewmanagerinterop", "jsi", "glog", @@ -664,6 +670,7 @@ android { create("rrc_image") { headers = File(prefabHeadersDir, "rrc_image").absolutePath } create("rrc_root") { headers = File(prefabHeadersDir, "rrc_root").absolutePath } create("rrc_view") { headers = File(prefabHeadersDir, "rrc_view").absolutePath } + create("rrc_textinput") { headers = File(prefabHeadersDir, "rrc_textinput").absolutePath } create("rrc_legacyviewmanagerinterop") { headers = File(prefabHeadersDir, "rrc_legacyviewmanagerinterop").absolutePath } diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index 1ad0af8843dbc1..c27c8e58b4c2c7 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -74,6 +74,7 @@ add_library(react_cxxreactpackage ALIAS ReactAndroid::react_cxxreactpackage) add_library(react_render_core ALIAS ReactAndroid::react_render_core) add_library(react_render_graphics ALIAS ReactAndroid::react_render_graphics) add_library(rrc_view ALIAS ReactAndroid::rrc_view) +add_library(rrc_textinput ALIAS ReactAndroid::rrc_textinput) add_library(jsi ALIAS ReactAndroid::jsi) add_library(glog ALIAS ReactAndroid::glog) add_library(fabricjni ALIAS ReactAndroid::fabricjni) @@ -108,6 +109,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_render_mapbuffer # prefab ready rrc_image # prefab ready rrc_view # prefab ready + rrc_textinput # prefab ready rrc_legacyviewmanagerinterop # prefab ready runtimeexecutor # prefab ready turbomodulejsijni # prefab ready From 5f45700bd06fb253650c8653b511b084b99eeb7f Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 4 Mar 2024 04:26:36 -0800 Subject: [PATCH 069/361] Fix NullPointerException thrown on startup (#43293) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43293 Was debugging this, and found that this exception was being thrown due to `DefaultBindingsInstaller`, which was an invalid hybrid object. The ReactInstance initializer fully supports this being null, so let's use that as default. Changelog: [Android][Fixed] NullPointerException is no longer ignored in MessageQueueThreadHandler Reviewed By: sammy-SC Differential Revision: D54434417 fbshipit-source-id: 52417b390061eface0f0578e32796d3a85303e03 --- .../queue/MessageQueueThreadHandler.java | 11 ---------- .../defaults/DefaultBindingsInstaller.kt | 20 ------------------- .../defaults/DefaultReactHostDelegate.kt | 2 +- .../jni/react/jni/JMessageQueueThread.cpp | 1 - .../main/jni/react/jni/JMessageQueueThread.h | 4 ---- 5 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultBindingsInstaller.kt diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadHandler.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadHandler.java index ddac0bfec7360f..010b6871593ea1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadHandler.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/queue/MessageQueueThreadHandler.java @@ -10,8 +10,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Message; -import com.facebook.common.logging.FLog; -import com.facebook.react.common.ReactConstants; /** Handler that can catch and dispatch Exceptions to an Exception handler. */ public class MessageQueueThreadHandler extends Handler { @@ -28,15 +26,6 @@ public void dispatchMessage(Message msg) { try { super.dispatchMessage(msg); } catch (Exception e) { - if (e instanceof NullPointerException) { - FLog.e( - ReactConstants.TAG, - "Caught NullPointerException when dispatching message in MessageQueueThreadHandler. This is likely caused by runnable" - + "(msg.callback) being nulled in Android Handler after dispatching and before handling (see T170239922 for more details)." - + "Currently we observe that it only happen once which is during initialisation. Due to fixing probably involve Android " - + "System code, we decide to ignore here for now and print an error message for debugging purpose in case this cause more serious issues in future."); - return; - } mExceptionHandler.handleException(e); } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultBindingsInstaller.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultBindingsInstaller.kt deleted file mode 100644 index 06a47d80908ebb..00000000000000 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultBindingsInstaller.kt +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -package com.facebook.react.defaults - -import com.facebook.jni.annotations.DoNotStrip -import com.facebook.react.common.annotations.UnstableReactNativeAPI -import com.facebook.react.runtime.BindingsInstaller - -/** - * A utility class that provides users a default [BindingsInstaller] class that's used to initialize - * [ReactHostDelegate] - */ -@DoNotStrip -@UnstableReactNativeAPI -public class DefaultBindingsInstaller : BindingsInstaller(null) {} diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt index 5f53398208a74d..3c50cac823e6f7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactHostDelegate.kt @@ -43,7 +43,7 @@ public class DefaultReactHostDelegate( override val jsBundleLoader: JSBundleLoader, override val reactPackages: List = emptyList(), override val jsRuntimeFactory: JSRuntimeFactory = HermesInstance(), - override val bindingsInstaller: BindingsInstaller = DefaultBindingsInstaller(), + override val bindingsInstaller: BindingsInstaller? = null, private val reactNativeConfig: ReactNativeConfig = ReactNativeConfig.DEFAULT_CONFIG, private val exceptionHandler: (Exception) -> Unit = {}, override val turboModuleManagerDelegateBuilder: ReactPackageTurboModuleManagerDelegate.Builder diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.cpp index df01e447a42e5d..e945c01e267944 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include #include diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.h b/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.h index 3926fa906deaaf..716e58b0a7b61e 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/jni/JMessageQueueThread.h @@ -42,10 +42,6 @@ class JMessageQueueThread : public MessageQueueThread { */ void quitSynchronous() override; - JavaMessageQueueThread::javaobject jobj() { - return m_jobj.get(); - } - private: jni::global_ref m_jobj; }; From 6461dcd07b681ab0069a81caccb0db136523bf7f Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 4 Mar 2024 04:41:41 -0800 Subject: [PATCH 070/361] =?UTF-8?q?Port:=20@react-native-community/cli#cle?= =?UTF-8?q?an=20=E2=86=92=20@react-native/core-cli-utils#clean=20(#43287)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43287 Move react-native-community/cli clean into core per RFC-0759. Provides: - android - metro - npm - bun - watchman - yarn - cocoapods These tasks are used to clear up caching artefacts in React Native projects. This is going to be called by the `react-native-community/cli` once we publish these in an npm package. Changelog: [General][Added] RFC-0759 Move cli clean into core Reviewed By: cipolleschi Differential Revision: D53997878 fbshipit-source-id: 56907be714184abecc8e3ef677ffc83e9ee7b54d --- packages/core-cli-utils/README.md | 52 +++++++ packages/core-cli-utils/index.js | 16 ++ packages/core-cli-utils/package.json | 30 ++++ packages/core-cli-utils/private/clean.js | 187 +++++++++++++++++++++++ packages/core-cli-utils/private/types.js | 15 ++ packages/core-cli-utils/private/utils.js | 24 +++ 6 files changed, 324 insertions(+) create mode 100644 packages/core-cli-utils/README.md create mode 100644 packages/core-cli-utils/index.js create mode 100644 packages/core-cli-utils/package.json create mode 100644 packages/core-cli-utils/private/clean.js create mode 100644 packages/core-cli-utils/private/types.js create mode 100644 packages/core-cli-utils/private/utils.js diff --git a/packages/core-cli-utils/README.md b/packages/core-cli-utils/README.md new file mode 100644 index 00000000000000..151cdeef757568 --- /dev/null +++ b/packages/core-cli-utils/README.md @@ -0,0 +1,52 @@ +# @react-native/core-cli-utils + +![npm package](https://img.shields.io/npm/v/@react-native/core-cli-utils?color=brightgreen&label=npm%20package) + +A collection of utilites to help Frameworks build their React Native CLI tooling. This is not intended to be used directly use users of React Native. + +## Usage + +```js +import { Command } from 'commander'; +import cli from '@react-native/core-cli-utils'; +import debug from 'debug'; + +const android = new Command('android'); + +const frameworkFindsAndroidSrcDir = "..."; +const tasks = cli.clean.android(frameworkFindsAndroidSrcDir); +const log = debug('fancy-framework:android'); + +android + .command('clean') + .description(cli.clean.android) + .action(async () => { + const log = debug('fancy-framework:android:clean'); + log(`🧹 let me clean your Android caches`); + // Add other caches your framework needs besides the normal React Native caches + // here. + for (const task of tasks) { + try { + log(`\t ${task.label}`); + // See: https://github.com/sindresorhus/execa#lines + const {stdout} = await task.action({ lines: true }) + log(stdout.join('\n\tGradle: ')); + } catch (e) { + log(`\t ⚠️ whoops: ${e.message}`); + } + } + }); +``` + +And you'd be using it like this: + +```bash +$ ./fancy-framework android clean +🧹 let me clean your Android caches + Gradle: // a bunch of gradle output + Gradle: .... +``` + +## Contributing + +Changes to this package can be made locally and linked against your app. Please see the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). diff --git a/packages/core-cli-utils/index.js b/packages/core-cli-utils/index.js new file mode 100644 index 00000000000000..b2f8691f099daf --- /dev/null +++ b/packages/core-cli-utils/index.js @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import {tasks as clean} from './private/clean.js'; + +export default { + clean, +}; diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json new file mode 100644 index 00000000000000..64ffab0912f117 --- /dev/null +++ b/packages/core-cli-utils/package.json @@ -0,0 +1,30 @@ +{ + "name": "@react-native/core-cli-utils", + "version": "0.74.0", + "description": "React Native CLI library for Frameworks to build on", + "main": "index.js", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/facebook/react-native.git", + "directory": "packages/core-cli-utils" + }, + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/core-cli-utils#readme", + "keywords": [ + "cli-utils", + "react-native" + ], + "bugs": "https://github.com/facebook/react-native/issues", + "engines": { + "node": ">=18" + }, + "files": [ + "dist" + ], + "dependencies": {}, + "devDependencies": {} +} diff --git a/packages/core-cli-utils/private/clean.js b/packages/core-cli-utils/private/clean.js new file mode 100644 index 00000000000000..7f5165e4ce0ef8 --- /dev/null +++ b/packages/core-cli-utils/private/clean.js @@ -0,0 +1,187 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import type {Task} from './types'; +import type {Options as ExecaOptions} from 'execa'; + +import {isMacOS, isWindows, task} from './utils'; +import execa from 'execa'; +import {existsSync, readdirSync, rm} from 'fs'; +import os from 'os'; +import path from 'path'; + +type CleanTasks = { + android: (androidSrcDir: ?string) => Task[], + metro: () => Task[], + npm: (projectRootDir: string, verifyCache?: boolean) => Task[], + bun: (projectRootDir: string) => Task[], + watchman: (projectRootDir: string) => Task[], + yarn: (projectRootDir: string) => Task[], + cocoapods?: (projectRootDir: string) => Task[], +}; + +const rmrf = (pathname: string) => { + if (!existsSync(pathname)) { + return; + } + rm(pathname, {maxRetries: 3, recursive: true, force: true}); +}; + +/** + * Removes the contents of a directory matching a given pattern, but keeps the directory. + * @private + */ +export function deleteDirectoryContents( + directory: string, + filePattern: RegExp, +): Task['action'] { + return async function deleteDirectoryContentsAction() { + const base = path.dirname(directory); + const files = readdirSync(base).filter((filename: string) => + filePattern.test(filename), + ); + for (const filename of files) { + rmrf(path.join(base, filename)); + } + }; +} + +/** + * Removes a directory recursively. + * @private + */ +export function deleteDirectory(directory: string): Task['action'] { + return async function cleanDirectoryAction() { + rmrf(directory); + }; +} + +/** + * Deletes the contents of the tmp directory matching a given pattern. + * @private + */ +export function deleteTmpDirectoryContents( + filepattern: RegExp, +): ReturnType { + return deleteDirectoryContents(os.tmpdir(), filepattern); +} + +// The tasks that cleanup various build artefacts. +export const tasks: CleanTasks = { + /** + * Cleans up the Android Gradle cache + */ + android: (androidSrcDir: ?string) => [ + task('🧹 Clean Gradle cache', async function gradle(opts?: ExecaOptions) { + const gradlew = path.join( + androidSrcDir ?? 'android', + isWindows ? 'gradlew.bat' : 'gradlew', + ); + + if (!existsSync(gradlew)) { + return; + } + const script = path.basename(gradlew); + const cwd = path.dirname(gradlew); + await execa(isWindows ? script : `./${script}`, ['clean'], { + cwd, + ...opts, + }); + }), + ], + + /** + * Agressively cleans up all Metro caches. + */ + metro: () => [ + task('🧹 Clean Metro cache', deleteTmpDirectoryContents(/^metro-.+/)), + task('🧹 Clean Haste cache', deleteTmpDirectoryContents(/^haste-map-.+/)), + task( + '🧹 Clean React Native cache', + deleteTmpDirectoryContents(/^react-.+/), + ), + ], + + /** + * Cleans up the `node_modules` folder and optionally garbage collects the npm cache. + */ + npm: (projectRootDir: string, verifyCache = false) => { + const _tasks = [ + task( + '🧹 Clean node_modules', + deleteDirectory(path.join(projectRootDir, 'node_modules')), + ), + ]; + if (verifyCache) { + _tasks.push( + task('🔬 Verify npm cache', (opts?: ExecaOptions) => + execa('npm', ['cache', 'verify'], {cwd: projectRootDir, ...opts}), + ), + ); + } + return _tasks; + }, + + /** + * Cleans up the Bun cache. + */ + bun: (projectRootDir: string) => [ + task('🧹 Clean Bun cache', (opts?: ExecaOptions) => + execa('bun', ['pm', 'cache', 'rm'], {cwd: projectRootDir, ...opts}), + ), + ], + + /** + * Stops Watchman and clears its cache + */ + watchman: (projectRootDir: string) => [ + task('✋ Stop Watchman', (opts?: ExecaOptions) => + execa(isWindows ? 'tskill' : 'killall', ['watchman'], { + cwd: projectRootDir, + ...opts, + }), + ), + task('🧹 Delete Watchman cache', (opts?: ExecaOptions) => + execa('watchman', ['watch-del-all'], {cwd: projectRootDir, ...opts}), + ), + ], + + /** + * Cleans up the Yarn cache + */ + yarn: (projectRootDir: string) => [ + task('🧹 Clean Yarn cache', (opts?: ExecaOptions) => + execa('yarn', ['cache', 'clean'], {cwd: projectRootDir, ...opts}), + ), + ], +}; + +if (isMacOS) { + /** + * Cleans up the local and global CocoaPods cache + */ + tasks.cocoapods = (projectRootDir: string) => [ + // TODO: add project root + task( + '🧹 Clean CocoaPods pod cache', + function removePodCache(opts?: ExecaOptions) { + return execa('bundle', ['exec', 'pod', 'deintegrate'], { + cwd: projectRootDir, + ...opts, + }); + }, + ), + ]; +} + +// +// Internal CLI +// diff --git a/packages/core-cli-utils/private/types.js b/packages/core-cli-utils/private/types.js new file mode 100644 index 00000000000000..7516e059d412d0 --- /dev/null +++ b/packages/core-cli-utils/private/types.js @@ -0,0 +1,15 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +export type Task = { + label: string, + action: () => Promise, +}; diff --git a/packages/core-cli-utils/private/utils.js b/packages/core-cli-utils/private/utils.js new file mode 100644 index 00000000000000..4b80c3e962162b --- /dev/null +++ b/packages/core-cli-utils/private/utils.js @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import type {Task} from './types'; + +import os from 'os'; + +export function task(label: string, action: Task['action']): Task { + return { + label, + action, + }; +} + +export const isWindows = os.platform() === 'win32'; +export const isMacOS = os.platform() === 'darwin'; From 58b45e86a6fd78409dc358e27ae736c95fee9f39 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Mon, 4 Mar 2024 04:47:34 -0800 Subject: [PATCH 071/361] Remove RFC-0759 ram-bundle command from cli (#43292) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43292 The ram-bundle command isn't necessary now that Hermes is our default VM. The RFC specifically calls for the CLI command to be removed [1]. [1] https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md#commands-to-be-removed Changelog: [General][Removed] - RFC-0759 remove ram-bundle command. Reviewed By: NickGerleman, cipolleschi Differential Revision: D54430289 fbshipit-source-id: 49d519c007b739f89ffe9032fec905c56ea49f4a --- packages/community-cli-plugin/README.md | 18 --------- .../src/commands/ram-bundle/index.js | 38 ------------------- .../community-cli-plugin/src/index.flow.js | 1 - packages/react-native/react-native.config.js | 2 - 4 files changed, 59 deletions(-) delete mode 100644 packages/community-cli-plugin/src/commands/ram-bundle/index.js diff --git a/packages/community-cli-plugin/README.md b/packages/community-cli-plugin/README.md index aebbf39d106fcc..12fcffb9c026ff 100644 --- a/packages/community-cli-plugin/README.md +++ b/packages/community-cli-plugin/README.md @@ -69,24 +69,6 @@ npx react-native bundle --entry-file [options] | `--read-global-cache` | Attempt to fetch transformed JS code from the global cache, if configured. Defaults to `false`. | | `--config ` | Path to the CLI configuration file. | -### `ram-bundle` - -Build the [RAM bundle](https://reactnative.dev/docs/ram-bundles-inline-requires) for the provided JavaScript entry file. - -#### Usage - -```sh -npx react-native ram-bundle --entry-file [options] -``` - -#### Options - -Accepts all options supported by [`bundle`](#bundle) and the following: - -| Option | Description | -| - | - | -| `--indexed-ram-bundle` | Force the "Indexed RAM" bundle file format, even when building for Android. | - ## Contributing Changes to this package can be made locally and tested against the `rn-tester` app, per the [Contributing guide](https://reactnative.dev/contributing/overview#contributing-code). During development, this package is automatically run from source with no build step. diff --git a/packages/community-cli-plugin/src/commands/ram-bundle/index.js b/packages/community-cli-plugin/src/commands/ram-bundle/index.js deleted file mode 100644 index eeed0819cfecdc..00000000000000 --- a/packages/community-cli-plugin/src/commands/ram-bundle/index.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @flow strict-local - * @format - * @oncall react_native - */ - -import type {BundleCommandArgs} from '../bundle'; -import type {Command, Config} from '@react-native-community/cli-types'; - -import bundleCommand from '../bundle'; -import buildBundle from '../bundle/buildBundle'; -import metroRamBundle from 'metro/src/shared/output/RamBundle'; - -const ramBundleCommand: Command = { - name: 'ram-bundle', - description: - 'Build the RAM bundle for the provided JavaScript entry file. See https://reactnative.dev/docs/ram-bundles-inline-requires.', - func: (argv: Array, config: Config, args: BundleCommandArgs) => { - return buildBundle(argv, config, args, metroRamBundle); - }, - options: [ - // $FlowFixMe[incompatible-type] options is nonnull - ...bundleCommand.options, - { - name: '--indexed-ram-bundle', - description: - 'Force the "Indexed RAM" bundle file format, even when building for android', - default: false, - }, - ], -}; - -export default ramBundleCommand; diff --git a/packages/community-cli-plugin/src/index.flow.js b/packages/community-cli-plugin/src/index.flow.js index 80adc7e51beb40..e9dbc7adc21380 100644 --- a/packages/community-cli-plugin/src/index.flow.js +++ b/packages/community-cli-plugin/src/index.flow.js @@ -10,7 +10,6 @@ */ export {default as bundleCommand} from './commands/bundle'; -export {default as ramBundleCommand} from './commands/ram-bundle'; export {default as startCommand} from './commands/start'; export {unstable_buildBundleWithConfig} from './commands/bundle/buildBundle'; diff --git a/packages/react-native/react-native.config.js b/packages/react-native/react-native.config.js index 6a8394e8ac1823..64841ed37a7e0d 100644 --- a/packages/react-native/react-native.config.js +++ b/packages/react-native/react-native.config.js @@ -13,7 +13,6 @@ const android = require('@react-native-community/cli-platform-android'); const ios = require('@react-native-community/cli-platform-ios'); const { bundleCommand, - ramBundleCommand, startCommand, } = require('@react-native/community-cli-plugin'); @@ -49,7 +48,6 @@ module.exports = { ...ios.commands, ...android.commands, bundleCommand, - ramBundleCommand, startCommand, codegenCommand, ], From 036f47ebc4cb372e13788c2498dcbf3c88379a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 4 Mar 2024 05:03:39 -0800 Subject: [PATCH 072/361] Add queueMicrotask method to JSI Summary: Changelog: [internal] ## Context Microtasks are an important aspect of JavaScript and they will become increasingly important in the hosts where we're currently using JSI. For example, React Native is going to adopt an event loop processing model similar to the one on the Web, which means it would need the ability to schedule and execute microtasks in every iteration of the loop. See https://github.com/react-native-community/discussions-and-proposals/pull/744 for details. JSI already has a method to execute all pending microtasks (`drainMicrotasks`) but without a method to schedule microtasks this is incomplete. We're currently testing microtasks with Hermes using an internal method to schedule microtasks (`HermesInternal.enqueueJob`) but we need a method in JSI so this also works in other runtimes like JSC and V8. ## Changes This adds the `queueMicrotask` to the Runtime API in JSI so we have symmetric API for microtasks and we can implement the necessary functionality. The expectation for JSI implementations is to queue microtasks from this method and from built-ins like Promises and async functions in the same queue, and not drain that queue until explicitly done via `drainMicrotasks` in JSI. This also modifies Hermes and JSC to provide stubs for those methods, and the actual implementation will be done in following diffs. Reviewed By: neildhar Differential Revision: D54302536 fbshipit-source-id: 25f52f91d7ef1a51687c431d2c7562c373dc72a5 --- packages/react-native/ReactCommon/jsi/jsi/decorator.h | 7 +++++++ packages/react-native/ReactCommon/jsi/jsi/jsi.cpp | 4 ++++ packages/react-native/ReactCommon/jsi/jsi/jsi.h | 7 +++++++ 3 files changed, 18 insertions(+) diff --git a/packages/react-native/ReactCommon/jsi/jsi/decorator.h b/packages/react-native/ReactCommon/jsi/jsi/decorator.h index 7bddd1fad80a52..6f4351a420da69 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/decorator.h +++ b/packages/react-native/ReactCommon/jsi/jsi/decorator.h @@ -126,6 +126,9 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { const std::shared_ptr& js) override { return plain().evaluatePreparedJavaScript(js); } + void queueMicrotask(const jsi::Function& callback) override { + return plain().queueMicrotask(callback); + } bool drainMicrotasks(int maxMicrotasksHint) override { return plain().drainMicrotasks(maxMicrotasksHint); } @@ -544,6 +547,10 @@ class WithRuntimeDecorator : public RuntimeDecorator { Around around{with_}; return RD::evaluatePreparedJavaScript(js); } + void queueMicrotask(const Function& callback) override { + Around around{with_}; + RD::queueMicrotask(callback); + } bool drainMicrotasks(int maxMicrotasksHint) override { Around around{with_}; return RD::drainMicrotasks(maxMicrotasksHint); diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp index 2d1003f1f838b2..bc953a5595766c 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp @@ -87,6 +87,10 @@ NativeState::~NativeState() {} Runtime::~Runtime() {} +void Runtime::queueMicrotask(const jsi::Function& /*callback*/) { + throw JSINativeException("queueMicrotask is not implemented in this runtime"); +} + Instrumentation& Runtime::instrumentation() { class NoInstrumentation : public Instrumentation { std::string getRecordedGCStats() override { diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.h b/packages/react-native/ReactCommon/jsi/jsi/jsi.h index 962dae93609423..d86005e4e379e5 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.h @@ -209,6 +209,13 @@ class JSI_EXPORT Runtime { virtual Value evaluatePreparedJavaScript( const std::shared_ptr& js) = 0; + /// Queues a microtask in the JavaScript VM internal Microtask (a.k.a. Job in + /// ECMA262) queue, to be executed when the host drains microtasks in + /// its event loop implementation. + /// + /// \param callback a function to be executed as a microtask. + virtual void queueMicrotask(const jsi::Function& callback); + /// Drain the JavaScript VM internal Microtask (a.k.a. Job in ECMA262) queue. /// /// \param maxMicrotasksHint a hint to tell an implementation that it should From bd89afa284c1b9e94ec7c33e35f4ce5a96936e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 4 Mar 2024 05:03:39 -0800 Subject: [PATCH 073/361] Implement queueMicrotask and drainMicrotasks in JSC Summary: Changelog: [internal] ## Context We want to enable the new React Native event loop by default for all users on the new RN architecture (on the bridgeless initialization path more concretely), which requires support for microtasks in all the JS engines that the support (Hermes already has it, JSC doesn't). ## Changes This adds initial support for microtasks in JSC, so we can schedule and execute microtasks in this runtime. One limitation about this approach is that, AFAIK, the public API for JSC doesn't allow us to customize its internal microtask queue or specify the method to be used by its built-in `Promise` or native `async function`, so we're forced to continue using a polyfill in that case (which uses `setImmediate` that will be mapped to `queueMicrotask`). Reviewed By: NickGerleman Differential Revision: D54302534 fbshipit-source-id: 47f71620344a81bc6624917f77452106ffbf55a3 --- .../ReactCommon/jsc/JSCRuntime.cpp | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp index c42d4f3008e4a6..f5b5e9210b232d 100644 --- a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp +++ b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp @@ -13,8 +13,8 @@ #include #include #include +#include #include -#include #include #include @@ -51,6 +51,12 @@ class JSCRuntime : public jsi::Runtime { const std::shared_ptr& buffer, const std::string& sourceURL) override; + // If we use this interface to implement microtasks in the host we need to + // polyfill `Promise` to use these methods, because JSC doesn't currently + // support providing a custom queue for its built-in implementation. + // Not doing this would result in a non-compliant behavior, as microtasks + // wouldn't execute in the order in which they were queued. + void queueMicrotask(const jsi::Function& callback) override; bool drainMicrotasks(int maxMicrotasksHint = -1) override; jsi::Object global() override; @@ -265,6 +271,7 @@ class JSCRuntime : public jsi::Runtime { std::atomic ctxInvalid_; std::string desc_; JSValueRef nativeStateSymbol_ = nullptr; + std::deque microtaskQueue_; #ifndef NDEBUG mutable std::atomic objectCounter_; mutable std::atomic symbolCounter_; @@ -378,6 +385,10 @@ JSCRuntime::JSCRuntime(JSGlobalContextRef ctx) } JSCRuntime::~JSCRuntime() { + // We need to clear the microtask queue to remove all references to the + // callbacks, so objectCounter_ would be 0 below. + microtaskQueue_.clear(); + // On shutting down and cleaning up: when JSC is actually torn down, // it calls JSC::Heap::lastChanceToFinalize internally which // finalizes anything left over. But at this point, @@ -434,7 +445,24 @@ jsi::Value JSCRuntime::evaluateJavaScript( return createValue(res); } -bool JSCRuntime::drainMicrotasks(int maxMicrotasksHint) { +void JSCRuntime::queueMicrotask(const jsi::Function& callback) { + microtaskQueue_.emplace_back( + jsi::Value(*this, callback).asObject(*this).asFunction(*this)); +} + +bool JSCRuntime::drainMicrotasks(int /*maxMicrotasksHint*/) { + // Note that new jobs can be enqueued during the draining. + while (!microtaskQueue_.empty()) { + jsi::Function callback = std::move(microtaskQueue_.front()); + + // We need to pop before calling the callback because that might throw. + // When that happens, the host will call `drainMicrotasks` again to execute + // the remaining microtasks, and this one shouldn't run again. + microtaskQueue_.pop_front(); + + callback.call(*this); + } + return true; } From dc254acacececf612c0cba9fdf7becdc23f03371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Mon, 4 Mar 2024 05:03:39 -0800 Subject: [PATCH 074/361] Use new JSI method to queue microtasks in RuntimeSchedulerTest Summary: Changelog: [internal] Now that `jsi::Runtime::queueMicrotask` is available, we can use it instead of calling an internal Hermes API in `RuntimeSchedulerTest`. Reviewed By: christophpurrer Differential Revision: D54416245 fbshipit-source-id: c9cbd3783d9dc1c3df499a7fec7acb6c229ec571 --- .../runtimescheduler/tests/RuntimeSchedulerTest.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp index 292b62c8916990..ef98135ee47482 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp @@ -200,13 +200,7 @@ TEST_P( return jsi::Value::undefined(); }); - // Hermes doesn't expose a C++ API to schedule microtasks, so we just access - // the API that it exposes to JS. - auto global = runtime_->global(); - auto enqueueJobFn = global.getPropertyAsObject(*runtime_, "HermesInternal") - .getPropertyAsFunction(*runtime_, "enqueueJob"); - - enqueueJobFn.call(*runtime_, std::move(microtaskCallback)); + runtime_->queueMicrotask(microtaskCallback); return jsi::Value::undefined(); }); From f57be12977786ea9b8278987c12329d12045f17b Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 4 Mar 2024 07:54:37 -0800 Subject: [PATCH 075/361] Bump packages for next major release (#43132) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43132 Command run: ``` node scripts/releases/set-version 0.75.0-main --skip-react-native-version ``` Changelog: [Internal] Reviewed By: lunaleaps, cipolleschi Differential Revision: D54006327 fbshipit-source-id: 7afe9e7ca3020faf399fdba2221fab8a102c56c7 --- package.json | 4 +-- packages/assets/package.json | 2 +- packages/babel-plugin-codegen/package.json | 4 +-- packages/community-cli-plugin/package.json | 6 ++-- packages/debugger-frontend/package.json | 2 +- packages/dev-middleware/package.json | 4 +-- .../eslint-config-react-native/package.json | 4 +-- .../eslint-plugin-react-native/package.json | 2 +- packages/eslint-plugin-specs/package.json | 4 +-- packages/hermes-inspector-msggen/package.json | 2 +- packages/metro-config/package.json | 6 ++-- packages/normalize-color/package.json | 2 +- packages/polyfills/package.json | 2 +- .../react-native-babel-preset/package.json | 4 +-- .../package.json | 4 +-- packages/react-native-bots/package.json | 2 +- .../package.json | 4 +-- packages/react-native-codegen/package.json | 2 +- .../react-native-gradle-plugin/package.json | 2 +- .../package.json | 9 ++++-- .../react-native-test-renderer/package.json | 30 ++++++++++--------- packages/react-native/package.json | 14 ++++----- packages/react-native/template/package.json | 8 ++--- packages/rn-tester-e2e/package.json | 2 +- packages/rn-tester/package.json | 4 +-- packages/typescript-config/package.json | 2 +- packages/virtualized-lists/package.json | 2 +- 27 files changed, 69 insertions(+), 64 deletions(-) diff --git a/package.json b/package.json index 3d2388850a613e..0bdc71145749af 100644 --- a/package.json +++ b/package.json @@ -59,8 +59,8 @@ "@definitelytyped/dtslint": "^0.0.127", "@jest/create-cache-key-function": "^29.6.3", "@pkgjs/parseargs": "^0.11.0", - "@react-native/metro-babel-transformer": "0.74.0", - "@react-native/metro-config": "0.74.0", + "@react-native/metro-babel-transformer": "0.75.0-main", + "@react-native/metro-config": "0.75.0-main", "@tsconfig/node18": "1.0.1", "@types/react": "^18.0.18", "@typescript-eslint/parser": "^6.7.4", diff --git a/packages/assets/package.json b/packages/assets/package.json index 616930179d1867..7fad03cf151d89 100644 --- a/packages/assets/package.json +++ b/packages/assets/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/assets-registry", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Asset support code for React Native.", "license": "MIT", "repository": { diff --git a/packages/babel-plugin-codegen/package.json b/packages/babel-plugin-codegen/package.json index ca3392302e261e..35dfa20d12549f 100644 --- a/packages/babel-plugin-codegen/package.json +++ b/packages/babel-plugin-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/babel-plugin-codegen", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Babel plugin to generate native module and view manager code for React Native.", "license": "MIT", "repository": { @@ -25,7 +25,7 @@ "index.js" ], "dependencies": { - "@react-native/codegen": "0.74.0" + "@react-native/codegen": "0.75.0-main" }, "devDependencies": { "@babel/core": "^7.20.0" diff --git a/packages/community-cli-plugin/package.json b/packages/community-cli-plugin/package.json index 158abb31c86f9f..c293aa220b5b03 100644 --- a/packages/community-cli-plugin/package.json +++ b/packages/community-cli-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/community-cli-plugin", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Core CLI commands for React Native", "keywords": [ "react-native", @@ -24,8 +24,8 @@ "dependencies": { "@react-native-community/cli-server-api": "13.6.1", "@react-native-community/cli-tools": "13.6.1", - "@react-native/dev-middleware": "0.74.0", - "@react-native/metro-babel-transformer": "0.74.0", + "@react-native/dev-middleware": "0.75.0-main", + "@react-native/metro-babel-transformer": "0.75.0-main", "chalk": "^4.0.0", "execa": "^5.1.1", "metro": "^0.80.3", diff --git a/packages/debugger-frontend/package.json b/packages/debugger-frontend/package.json index 4c100152f8edbf..91de5223c71c4e 100644 --- a/packages/debugger-frontend/package.json +++ b/packages/debugger-frontend/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/debugger-frontend", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Debugger frontend for React Native based on Chrome DevTools", "keywords": [ "react-native", diff --git a/packages/dev-middleware/package.json b/packages/dev-middleware/package.json index f1700a2fcf8760..0554eeff3e9ffc 100644 --- a/packages/dev-middleware/package.json +++ b/packages/dev-middleware/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/dev-middleware", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Dev server middleware for React Native", "keywords": [ "react-native", @@ -23,7 +23,7 @@ ], "dependencies": { "@isaacs/ttlcache": "^1.4.1", - "@react-native/debugger-frontend": "0.74.0", + "@react-native/debugger-frontend": "0.75.0-main", "@rnx-kit/chromium-edge-launcher": "^1.0.0", "chrome-launcher": "^0.15.2", "connect": "^3.6.5", diff --git a/packages/eslint-config-react-native/package.json b/packages/eslint-config-react-native/package.json index 7edb68a00afbe1..6836536e33a81e 100644 --- a/packages/eslint-config-react-native/package.json +++ b/packages/eslint-config-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-config", - "version": "0.74.0", + "version": "0.75.0-main", "description": "ESLint config for React Native", "license": "MIT", "repository": { @@ -22,7 +22,7 @@ "dependencies": { "@babel/core": "^7.20.0", "@babel/eslint-parser": "^7.20.0", - "@react-native/eslint-plugin": "0.74.0", + "@react-native/eslint-plugin": "0.75.0-main", "@typescript-eslint/eslint-plugin": "^6.7.4", "@typescript-eslint/parser": "^6.7.4", "eslint-config-prettier": "^8.5.0", diff --git a/packages/eslint-plugin-react-native/package.json b/packages/eslint-plugin-react-native/package.json index acb35918dd30e1..ff591353bfd087 100644 --- a/packages/eslint-plugin-react-native/package.json +++ b/packages/eslint-plugin-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin", - "version": "0.74.0", + "version": "0.75.0-main", "description": "ESLint rules for @react-native/eslint-config", "license": "MIT", "repository": { diff --git a/packages/eslint-plugin-specs/package.json b/packages/eslint-plugin-specs/package.json index fa04efd48a5717..def4eaa808566e 100644 --- a/packages/eslint-plugin-specs/package.json +++ b/packages/eslint-plugin-specs/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/eslint-plugin-specs", - "version": "0.74.0", + "version": "0.75.0-main", "description": "ESLint rules to validate NativeModule and Component Specs", "license": "MIT", "repository": { @@ -31,7 +31,7 @@ "@babel/eslint-parser": "^7.20.0", "@babel/plugin-transform-flow-strip-types": "^7.20.0", "@babel/preset-flow": "^7.20.0", - "@react-native/codegen": "0.74.0", + "@react-native/codegen": "0.75.0-main", "make-dir": "^2.1.0", "pirates": "^4.0.1", "source-map-support": "0.5.0" diff --git a/packages/hermes-inspector-msggen/package.json b/packages/hermes-inspector-msggen/package.json index 0124f83b5419aa..71a6582d4121e7 100644 --- a/packages/hermes-inspector-msggen/package.json +++ b/packages/hermes-inspector-msggen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/hermes-inspector-msggen", - "version": "0.72.0", + "version": "0.75.0-main", "private": true, "description": "Hermes Inspector Message Generator for React Native", "license": "MIT", diff --git a/packages/metro-config/package.json b/packages/metro-config/package.json index 410f04a50b8952..e9bf94556ed651 100644 --- a/packages/metro-config/package.json +++ b/packages/metro-config/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/metro-config", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Metro configuration for React Native.", "license": "MIT", "repository": { @@ -26,8 +26,8 @@ "dist" ], "dependencies": { - "@react-native/js-polyfills": "0.74.0", - "@react-native/metro-babel-transformer": "0.74.0", + "@react-native/js-polyfills": "0.75.0-main", + "@react-native/metro-babel-transformer": "0.75.0-main", "metro-config": "^0.80.3", "metro-runtime": "^0.80.3" } diff --git a/packages/normalize-color/package.json b/packages/normalize-color/package.json index c489d39b87bc80..b13cc7affc0b0b 100644 --- a/packages/normalize-color/package.json +++ b/packages/normalize-color/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/normalize-colors", - "version": "0.74.1", + "version": "0.75.0-main", "description": "Color normalization for React Native.", "license": "MIT", "repository": { diff --git a/packages/polyfills/package.json b/packages/polyfills/package.json index cadebf8191e007..b9d7cc18c1b4c9 100644 --- a/packages/polyfills/package.json +++ b/packages/polyfills/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/js-polyfills", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Polyfills for React Native.", "license": "MIT", "repository": { diff --git a/packages/react-native-babel-preset/package.json b/packages/react-native-babel-preset/package.json index 74a6f1df7c917d..c96b20adcc0867 100644 --- a/packages/react-native-babel-preset/package.json +++ b/packages/react-native-babel-preset/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/babel-preset", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Babel preset for React Native applications", "main": "src/index.js", "repository": { @@ -54,7 +54,7 @@ "@babel/plugin-transform-typescript": "^7.5.0", "@babel/plugin-transform-unicode-regex": "^7.0.0", "@babel/template": "^7.0.0", - "@react-native/babel-plugin-codegen": "0.74.0", + "@react-native/babel-plugin-codegen": "0.75.0-main", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" }, diff --git a/packages/react-native-babel-transformer/package.json b/packages/react-native-babel-transformer/package.json index 3bac9a7b458bb9..b2f0f0fbc1fb0e 100644 --- a/packages/react-native-babel-transformer/package.json +++ b/packages/react-native-babel-transformer/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/metro-babel-transformer", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Babel transformer for React Native applications.", "main": "src/index.js", "repository": { @@ -16,7 +16,7 @@ "license": "MIT", "dependencies": { "@babel/core": "^7.20.0", - "@react-native/babel-preset": "0.74.0", + "@react-native/babel-preset": "0.75.0-main", "hermes-parser": "0.20.0", "nullthrows": "^1.1.1" }, diff --git a/packages/react-native-bots/package.json b/packages/react-native-bots/package.json index 961bdbd9d6bfab..ce31bbcd28f1e2 100644 --- a/packages/react-native-bots/package.json +++ b/packages/react-native-bots/package.json @@ -1,7 +1,7 @@ { "name": "@react-native/bots", "description": "React Native Bots", - "version": "0.0.0", + "version": "0.75.0-main", "private": true, "license": "MIT", "repository": { diff --git a/packages/react-native-codegen-typescript-test/package.json b/packages/react-native-codegen-typescript-test/package.json index c170d4cedccc8e..7849aa60ce50ef 100644 --- a/packages/react-native-codegen-typescript-test/package.json +++ b/packages/react-native-codegen-typescript-test/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/codegen-typescript-test", - "version": "0.0.1", + "version": "0.75.0-main", "private": true, "description": "TypeScript related unit test for @react-native/codegen", "license": "MIT", @@ -19,7 +19,7 @@ "prepare": "yarn run build" }, "dependencies": { - "@react-native/codegen": "0.74.0" + "@react-native/codegen": "0.75.0-main" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index dabc128e1904c3..98021a606418a0 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/codegen", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Code generation tools for React Native", "license": "MIT", "repository": { diff --git a/packages/react-native-gradle-plugin/package.json b/packages/react-native-gradle-plugin/package.json index 33b450a9e9166c..0c966776e5cf1c 100644 --- a/packages/react-native-gradle-plugin/package.json +++ b/packages/react-native-gradle-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/gradle-plugin", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Gradle Plugin for React Native", "license": "MIT", "repository": { diff --git a/packages/react-native-popup-menu-android/package.json b/packages/react-native-popup-menu-android/package.json index 9be32ece5c1cf1..99f52be3071303 100644 --- a/packages/react-native-popup-menu-android/package.json +++ b/packages/react-native-popup-menu-android/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/popup-menu-android", - "version": "0.74.0", + "version": "0.75.0-main", "description": "PopupMenu for the Android platform", "react-native": "js/PopupMenuAndroid", "source": "js/PopupMenuAndroid", @@ -12,10 +12,13 @@ "!**/__fixtures__", "!**/__mocks__" ], - "keywords": ["react-native", "android"], + "keywords": [ + "react-native", + "android" + ], "license": "MIT", "devDependencies": { - "@react-native/codegen": "*" + "@react-native/codegen": "0.75.0-main" }, "peerDependencies": { "react": "*", diff --git a/packages/react-native-test-renderer/package.json b/packages/react-native-test-renderer/package.json index 4b90093f6fc2cb..3c0da0cc18c6c5 100644 --- a/packages/react-native-test-renderer/package.json +++ b/packages/react-native-test-renderer/package.json @@ -1,16 +1,18 @@ { - "name": "@react-native/test-renderer", - "private": true, - "version": "0.0.0", - "description": "A Test rendering library for React Native", - "license": "MIT", - "devDependencies": { - "@babel/core": "^7.20.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/preset-env": "^7.20.0", - "@babel/preset-flow": "^7.20.0" - }, - "dependencies": {}, - "main": "src/index.js", - "peerDependencies": { "jest": "^29.7.0" } + "name": "@react-native/test-renderer", + "private": true, + "version": "0.75.0-main", + "description": "A Test rendering library for React Native", + "license": "MIT", + "devDependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/preset-env": "^7.20.0", + "@babel/preset-flow": "^7.20.0" + }, + "dependencies": {}, + "main": "src/index.js", + "peerDependencies": { + "jest": "^29.7.0" } +} diff --git a/packages/react-native/package.json b/packages/react-native/package.json index dcd725c23bd5dd..e0101e009268e2 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -101,13 +101,13 @@ "@react-native-community/cli": "13.6.1", "@react-native-community/cli-platform-android": "13.6.1", "@react-native-community/cli-platform-ios": "13.6.1", - "@react-native/assets-registry": "0.74.0", - "@react-native/codegen": "0.74.0", - "@react-native/community-cli-plugin": "0.74.0", - "@react-native/gradle-plugin": "0.74.0", - "@react-native/js-polyfills": "0.74.0", - "@react-native/normalize-colors": "0.74.1", - "@react-native/virtualized-lists": "0.74.0", + "@react-native/assets-registry": "0.75.0-main", + "@react-native/codegen": "0.75.0-main", + "@react-native/community-cli-plugin": "0.75.0-main", + "@react-native/gradle-plugin": "0.75.0-main", + "@react-native/js-polyfills": "0.75.0-main", + "@react-native/normalize-colors": "0.75.0-main", + "@react-native/virtualized-lists": "0.75.0-main", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", diff --git a/packages/react-native/template/package.json b/packages/react-native/template/package.json index 232831747e774e..47fd4a9e6f2aea 100644 --- a/packages/react-native/template/package.json +++ b/packages/react-native/template/package.json @@ -17,10 +17,10 @@ "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", - "@react-native/babel-preset": "0.74.0", - "@react-native/eslint-config": "0.74.0", - "@react-native/metro-config": "0.74.0", - "@react-native/typescript-config": "0.74.0", + "@react-native/babel-preset": "0.75.0-main", + "@react-native/eslint-config": "0.75.0-main", + "@react-native/metro-config": "0.75.0-main", + "@react-native/typescript-config": "0.75.0-main", "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", diff --git a/packages/rn-tester-e2e/package.json b/packages/rn-tester-e2e/package.json index ef06a7f8fe1b87..c0ac765940fff1 100644 --- a/packages/rn-tester-e2e/package.json +++ b/packages/rn-tester-e2e/package.json @@ -1,7 +1,7 @@ { "name": "@react-native/tester-e2e", "private": true, - "version": "0.0.1", + "version": "0.75.0-main", "license": "MIT", "description": "React Native E2E tester app.", "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/rn-tester-e2e", diff --git a/packages/rn-tester/package.json b/packages/rn-tester/package.json index 87ed68d334c9b8..f66b9f6eecf803 100644 --- a/packages/rn-tester/package.json +++ b/packages/rn-tester/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/tester", - "version": "0.0.1", + "version": "0.75.0-main", "private": true, "description": "React Native tester app.", "license": "MIT", @@ -26,7 +26,7 @@ "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "nullthrows": "^1.1.1", - "@react-native/popup-menu-android": "^0.74.0" + "@react-native/popup-menu-android": "0.75.0-main" }, "peerDependencies": { "react": "18.2.0", diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 0ca29efbb837a5..436253cbb29bee 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/typescript-config", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Default TypeScript configuration for React Native apps", "license": "MIT", "repository": { diff --git a/packages/virtualized-lists/package.json b/packages/virtualized-lists/package.json index b05d544bd85d55..3ba3eecb8c6051 100644 --- a/packages/virtualized-lists/package.json +++ b/packages/virtualized-lists/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/virtualized-lists", - "version": "0.74.0", + "version": "0.75.0-main", "description": "Virtualized lists for React Native.", "license": "MIT", "repository": { From 881942a958bdc712ce036163031bf567b5c55d66 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Mon, 4 Mar 2024 08:27:46 -0800 Subject: [PATCH 076/361] avoid merging unrelated props into ShadowNodeFamily::nativeProps (#43305) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43305 changelog: [internal] Originally when I built setNativeProps, I assumed a node is either controlled by handled directly or it is controlled by React. But we can't make sure that's the case, users can do both and control one prop with setNativeProps and the others with React. Additionally, Suspense uses display: none to hide a subtree. Therefore, React controlled props must not be copied into `ShadowNodeFamily::nativeProps_DEPRECATED` Reviewed By: javache Differential Revision: D54453820 fbshipit-source-id: 5b4038f0dd366621d26a92f668d33f27ce60f4b4 --- .../LegacyViewManagerInteropViewProps.cpp | 7 +++-- .../renderer/core/DynamicPropsUtilities.cpp | 7 ++++- .../renderer/core/DynamicPropsUtilities.h | 31 +++++++++++++++++-- .../react/renderer/core/ShadowNode.cpp | 4 ++- .../core/tests/DynamicPropsUtilitiesTest.cpp | 24 +++++++++++--- .../react/renderer/uimanager/UIManager.cpp | 8 +++-- 6 files changed, 67 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp index fe97911c6807db..0b73576a74db02 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/legacyviewmanagerinterop/LegacyViewManagerInteropViewProps.cpp @@ -15,8 +15,9 @@ LegacyViewManagerInteropViewProps::LegacyViewManagerInteropViewProps( const LegacyViewManagerInteropViewProps& sourceProps, const RawProps& rawProps) : ViewProps(context, sourceProps, rawProps), - otherProps( - mergeDynamicProps(sourceProps.otherProps, (folly::dynamic)rawProps)) { -} + otherProps(mergeDynamicProps( + sourceProps.otherProps, + (folly::dynamic)rawProps, + NullValueStrategy::Override)) {} } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.cpp b/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.cpp index e90aa160fd1614..7ec8b8e2ed336e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.cpp @@ -11,7 +11,8 @@ namespace facebook::react { folly::dynamic mergeDynamicProps( const folly::dynamic& source, - const folly::dynamic& patch) { + const folly::dynamic& patch, + NullValueStrategy nullValueStrategy) { auto result = source; if (!result.isObject()) { @@ -25,6 +26,10 @@ folly::dynamic mergeDynamicProps( // Note, here we have to preserve sub-prop objects with `null` value as // an indication for the legacy mounting layer that it needs to clean them up. for (const auto& pair : patch.items()) { + if (nullValueStrategy == NullValueStrategy::Ignore && + source.find(pair.first) == source.items().end()) { + continue; + } result[pair.first] = pair.second; } diff --git a/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.h b/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.h index f5abb9d21e3b00..d642d8cfdba8c7 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.h +++ b/packages/react-native/ReactCommon/react/renderer/core/DynamicPropsUtilities.h @@ -12,13 +12,40 @@ namespace facebook::react { +/* + * Enum defining how missing value in `source` is handled if it is present in + * `patch`. + */ +enum class NullValueStrategy { + /* + * Key in source will be overriden by the matching key in patch. + * + * Example: + * source: {"key": "value"} + * patch: {"key": "new value"} + * returned: {"key": "new value"} + */ + Override, + + /* + * In case key is missing in source, value from patch will be ignored. + * + * Example: + * source: {"key 1": "value 1"} + * patch: {"key": "new value 1", "key 2": "new value 2"} + * returned: {"key": "new value 1"} + */ + Ignore +}; + /* * Accepts two `folly::dynamic` objects as arguments. Both arguments need to * represent a dictionary. It updates `source` with key/value pairs from - * `patch`, overriding existing keys. + * `patch`. */ folly::dynamic mergeDynamicProps( const folly::dynamic& source, - const folly::dynamic& patch); + const folly::dynamic& patch, + NullValueStrategy nullValueStrategy); } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp index d51cb8ff2311a1..e257f39e079c39 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNode.cpp @@ -42,7 +42,9 @@ Props::Shared ShadowNode::propsForClonedShadowNode( if (!hasBeenMounted && sourceNodeHasRawProps && props) { auto& castedProps = const_cast(*props); castedProps.rawProps = mergeDynamicProps( - sourceShadowNode.getProps()->rawProps, props->rawProps); + sourceShadowNode.getProps()->rawProps, + props->rawProps, + NullValueStrategy::Override); return props; } #endif diff --git a/packages/react-native/ReactCommon/react/renderer/core/tests/DynamicPropsUtilitiesTest.cpp b/packages/react-native/ReactCommon/react/renderer/core/tests/DynamicPropsUtilitiesTest.cpp index 1ebb12b3a81cd2..a79767861dda6f 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/tests/DynamicPropsUtilitiesTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/tests/DynamicPropsUtilitiesTest.cpp @@ -24,7 +24,7 @@ TEST(DynamicPropsUtilitiesTest, handleNestedObjects) { map2["style"] = dynamic::object("backgroundColor", "blue")("color", "black"); map2["height"] = 100; - auto result = mergeDynamicProps(map1, map2); + auto result = mergeDynamicProps(map1, map2, NullValueStrategy::Override); EXPECT_TRUE(result["style"].isObject()); EXPECT_TRUE(result["style"]["backgroundColor"].isString()); @@ -42,25 +42,39 @@ TEST(DynamicPropsUtilitiesTest, handleEmptyObject) { dynamic map2 = dynamic::object; map2["height"] = 100; - auto result = mergeDynamicProps(map1, map2); + auto result = mergeDynamicProps(map1, map2, NullValueStrategy::Override); EXPECT_TRUE(result["height"].isInt()); EXPECT_EQ(result["height"], 100); - result = mergeDynamicProps(map1, map2); + result = mergeDynamicProps(map1, map2, NullValueStrategy::Override); EXPECT_TRUE(result["height"].isInt()); EXPECT_EQ(result["height"], 100); } -TEST(DynamicPropsUtilitiesTest, handleNull) { +TEST(DynamicPropsUtilitiesTest, handleNullValue) { dynamic map1 = dynamic::object; map1["height"] = 100; dynamic map2 = dynamic::object; map2["height"] = nullptr; - auto result = mergeDynamicProps(map1, map2); + auto result = mergeDynamicProps(map1, map2, NullValueStrategy::Override); EXPECT_TRUE(result["height"].isNull()); } + +TEST(DynamicPropsUtilitiesTest, testNullValueStrategyIgnore) { + dynamic map1 = dynamic::object; + map1["height"] = 100; + + dynamic map2 = dynamic::object; + map2["width"] = 200; + map2["height"] = 101; + + auto result = mergeDynamicProps(map1, map2, NullValueStrategy::Ignore); + + EXPECT_EQ(result["height"], 101); + EXPECT_TRUE(result["width"].isNull()); +} diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 5cf3e5eeb6ce39..2f5b64cf0dc7f5 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -129,7 +129,9 @@ std::shared_ptr UIManager::cloneNode( // was previously in `nativeProps_DEPRECATED`. family.nativeProps_DEPRECATED = std::make_unique(mergeDynamicProps( - *family.nativeProps_DEPRECATED, (folly::dynamic)rawProps)); + *family.nativeProps_DEPRECATED, + (folly::dynamic)rawProps, + NullValueStrategy::Ignore)); props = componentDescriptor.cloneProps( propsParserContext, @@ -513,7 +515,9 @@ void UIManager::setNativeProps_DEPRECATED( // previously in `nativeProps_DEPRECATED`. family.nativeProps_DEPRECATED = std::make_unique(mergeDynamicProps( - *family.nativeProps_DEPRECATED, (folly::dynamic)rawProps)); + *family.nativeProps_DEPRECATED, + (folly::dynamic)rawProps, + NullValueStrategy::Override)); } else { family.nativeProps_DEPRECATED = std::make_unique((folly::dynamic)rawProps); From 9f85a249fa9e18eae745f103e390b2a8542e8ee9 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Mon, 4 Mar 2024 08:55:00 -0800 Subject: [PATCH 077/361] Link to releases repo for upgrade issues (#43295) Summary: Changelog: [Internal] We're moving upgrade issues to https://github.com/reactwg/react-native-releases/issues/new/choose Pull Request resolved: https://github.com/facebook/react-native/pull/43295 Reviewed By: cortinico, cipolleschi Differential Revision: D54442540 Pulled By: lunaleaps fbshipit-source-id: a079935a290f56d2932c5fc588e96a68e1c13f9a --- .github/ISSUE_TEMPLATE/config.yml | 4 + .../upgrade_regression_form.yml | 133 ------------------ 2 files changed, 4 insertions(+), 133 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/upgrade_regression_form.yml diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3dc8f24718545e..4bc1496d421726 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,9 @@ blank_issues_enabled: false contact_links: + - name: ⬆️ Upgrade - Build Regression + url: https://github.com/reactwg/react-native-releases/issues/new/choose + about: | + If you are upgrading to a new React Native version (stable or pre-release) and encounter a build regression. - name: 🚀 Expo Issue url: https://github.com/expo/expo/issues/new about: | diff --git a/.github/ISSUE_TEMPLATE/upgrade_regression_form.yml b/.github/ISSUE_TEMPLATE/upgrade_regression_form.yml deleted file mode 100644 index ed559395ecb0f8..00000000000000 --- a/.github/ISSUE_TEMPLATE/upgrade_regression_form.yml +++ /dev/null @@ -1,133 +0,0 @@ -name: ⬆️ Upgrade - Build Regression -description: If you are upgrading to a new React Native version (stable or pre-release) and encounter a build regression. -labels: ["Needs: Triage :mag:", "Type: Upgrade Issue"] - -body: - - type: markdown - attributes: - value: "## Upgrade Issues" - - type: markdown - attributes: - value: | - Please use this form to file an issue if you have upgraded or are upgrading to [latest stable release](https://github.com/facebook/react-native/releases/latest) and have experienced a regression (something that used to work in previous version). - - If you're **NOT** upgrading the React Native version, please use this [other bug type](https://github.com/facebook/react-native/issues/new?template=bug_report.yml). - - Before you continue: - * If you're using **Expo** and having problems updating it, [report it here](https://github.com/expo/expo/issues). - * If you're found a problem with our **documentation**, [report it here](https://github.com/facebook/react-native-website/issues/). - * If you're having an issue with **Metro** (the bundler), [report it here](https://github.com/facebook/metro/issues/). - * If you're using an external library, report the issue to the **library first**. - * Please [search for similar issues](https://github.com/facebook/react-native/issues) in our issue tracker. - - Make sure that your issue: - * Have a **valid reproducer** with an [empty project from template](https://github.com/react-native-community/reproducer-react-native). - * Is upgrading to the [**latest stable**](https://github.com/facebook/react-native/releases/) of React Native. - - Due to the extreme number of bugs we receive, we will be looking **ONLY** into issues with a reproducer, and on [supported versions](https://github.com/reactwg/react-native-releases#which-versions-are-currently-supported) of React Native. - - type: input - id: old-version - attributes: - label: Old Version - description: The version of react-native that you're upgrading from. - placeholder: "0.72.0" - validations: - required: true - - type: input - id: new-version - attributes: - label: New Version - description: The version of react-native that you're upgrading to. Bear in mind that only issues that are upgrading to the [latest stable](https://github.com/facebook/react-native/releases/) will be looked into. - placeholder: "0.73.0" - validations: - required: true - - type: textarea - id: description - attributes: - label: Description - description: A clear and concise description of what the bug is. - validations: - required: true - - type: textarea - id: reproduction - attributes: - label: Steps to reproduce - description: The list of steps and commands to reproduce the issue. - placeholder: | - 1. Install the application with `yarn android` - 2. Click on the button on the Home - 3. Notice the crash - validations: - required: true - - type: dropdown - id: platforms - attributes: - label: Affected Platforms - description: Please select which platform you're developing to, and which OS you're using for building. - multiple: true - options: - - Runtime - Android - - Runtime - iOS - - Runtime - Web - - Runtime - Desktop - - Build - MacOS - - Build - Windows - - Build - Linux - - Other (please specify) - validations: - required: true - - type: textarea - id: react-native-info - attributes: - label: Output of `npx react-native info` - description: Run `npx react-native info` in your terminal, copy and paste the results here. - placeholder: | - Paste the output of `npx react-native info` here. The output looks like: - ... - System: - OS: macOS 14.1.1 - CPU: (10) arm64 Apple M1 Max - Memory: 417.81 MB / 64.00 GB - Shell: - version: "5.9" - path: /bin/zsh - Binaries: - Node: ... - version: 18.14.0 - ... - render: text - validations: - required: true - - type: textarea - id: stacktrace - attributes: - label: Stacktrace or Logs - description: Please provide a stacktrace or a log of your crash or failure - render: text - placeholder: | - Paste your stacktraces and logs here. They might look like: - - java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libfabricjni.so caused by: com.facebook.react.fabric.StateWrapperImpl result: 0 - at com.facebook.soloader.SoLoader.g(Unknown Source:341) - at com.facebook.soloader.SoLoader.t(Unknown Source:124) - at com.facebook.soloader.SoLoader.s(Unknown Source:2) - at com.facebook.soloader.SoLoader.q(Unknown Source:42) - at com.facebook.soloader.SoLoader.p(Unknown Source:1) - ... - validations: - required: true - - type: input - id: reproducer - attributes: - label: Reproducer - description: A link to a Expo Snack or a public repository that reproduces this bug, using [this template](https://github.com/react-native-community/reproducer-react-native). Reproducers are **mandatory**. - placeholder: "https://github.com//" - validations: - required: true - - type: textarea - id: extra - attributes: - label: Screenshots and Videos - description: | - Please provide screenshot or a video of your bug if relevant. - Issues with videos and screenshots are more likely to **get prioritized**. From ec928d7a669fa2624bcf7da520041f140dd0fb03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Mon, 4 Mar 2024 10:14:44 -0800 Subject: [PATCH 078/361] feat(RCTAppDelegate): Implement `RCTRootViewFactory` (#42263) Summary: This PR implements `RCTRootViewFactory` a utility class (suggested by cipolleschi) that returns proper RCTRootView based on the current environment state (new arch/old arch/bridgeless). This class aims to preserve background compatibility by implementing a configuration class forwarding necessary class to RCTAppDelegate. ### Brownfield use case This PR leverages the `RCTRootViewFactory` in `RCTAppDelegate` for the default initialization of React Native (greenfield). Here is an example of creating a Brownfield integration (without RCTAppDelegate) using this class (can be later added to docs): 1. Store reference to `rootViewFactory` and to `UIWindow` `AppDelegate.h`: ```objc interface AppDelegate : UIResponder property(nonatomic, strong) UIWindow* window; property(nonatomic, strong) RCTRootViewFactory* rootViewFactory; end ``` 2. Create an initial configuration using `RCTRootViewFactoryConfiguration` and initialize `RCTRootViewFactory` using it. Then you can use the factory to create a new `RCTRootView` without worrying about old arch/new arch/bridgeless. `AppDelegate.mm` ```objc implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Create configuration RCTRootViewFactoryConfiguration *configuration = [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL newArchEnabled:self.fabricEnabled turboModuleEnabled:self.turboModuleEnabled bridgelessEnabled:self.bridgelessEnabled]; // Initialize RCTRootViewFactory self.rootViewFactory = [[RCTRootViewFactory alloc] initWithConfiguration:configuration]; // Create main root view UIView *rootView = [self.rootViewFactory viewWithModuleName:@"RNTesterApp" initialProperties:@{} launchOptions:launchOptions]; // Set main window as you prefer for your Brownfield integration. self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; // Later in the codebase you can initialize more rootView's using rootViewFactory. return YES; } end ``` bypass-github-export-checks ## Changelog: [INTERNAL] [ADDED] - Implement RCTRootViewFactory Pull Request resolved: https://github.com/facebook/react-native/pull/42263 Test Plan: Check if root view is properly created on app initialization Reviewed By: dmytrorykun Differential Revision: D53179625 Pulled By: cipolleschi fbshipit-source-id: 9bc850965ba30d84ad3e67d91dd888f0547c2136 --- .../Libraries/AppDelegate/RCTAppDelegate.h | 13 +- .../Libraries/AppDelegate/RCTAppDelegate.mm | 183 ++++--------- .../AppDelegate/RCTRootViewFactory.h | 123 +++++++++ .../AppDelegate/RCTRootViewFactory.mm | 253 ++++++++++++++++++ .../FlexibleSizeExampleView.mm | 5 +- .../UpdatePropertiesExampleView.mm | 5 +- 6 files changed, 441 insertions(+), 141 deletions(-) create mode 100644 packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h create mode 100644 packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h index d6954f6dbc2ef7..741dfa92f7fcdc 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.h @@ -8,6 +8,7 @@ #import #import #import +#import "RCTRootViewFactory.h" @class RCTBridge; @protocol RCTBridgeDelegate; @@ -58,9 +59,12 @@ NS_ASSUME_NONNULL_BEGIN /// The window object, used to render the UViewControllers @property (nonatomic, strong, nonnull) UIWindow *window; -@property (nonatomic, strong, nullable) RCTBridge *bridge; +@property (nonatomic, nullable) RCTBridge *bridge; @property (nonatomic, strong, nullable) NSString *moduleName; @property (nonatomic, strong, nullable) NSDictionary *initialProps; +@property (nonatomic, strong, nonnull) RCTRootViewFactory *rootViewFactory; + +@property (nonatomic, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; /** * It creates a `RCTBridge` using a delegate and some launch options. @@ -127,18 +131,11 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *)rootViewController; -/// This method controls whether the App will use RuntimeScheduler. Only applicable in the legacy architecture. -/// -/// @return: `YES` to use RuntimeScheduler, `NO` to use JavaScript scheduler. The default value is `YES`. -- (BOOL)runtimeSchedulerEnabled; - /** * The default `RCTColorSpace` for the app. It defaults to `RCTColorSpaceSRGB`. */ @property (nonatomic, readonly) RCTColorSpace defaultColorSpace; -@property (nonatomic, strong) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; - /// This method returns a map of Component Descriptors and Components classes that needs to be registered in the /// new renderer. The Component Descriptor is a string which represent the name used in JS to refer to the native /// component. The default implementation returns an empty dictionary. Subclasses can override this method to register diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 6c464725d87d8d..f4ea71c1c896b8 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -43,83 +43,29 @@ #import #import -@interface RCTAppDelegate () { - std::shared_ptr _reactNativeConfig; - facebook::react::ContextContainer::Shared _contextContainer; -} +@interface RCTAppDelegate () @end -static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled) -{ - NSMutableDictionary *mutableProps = [initialProps mutableCopy] ?: [NSMutableDictionary new]; - return mutableProps; -} - -@interface RCTAppDelegate () { - std::shared_ptr _runtimeScheduler; -} -@end - -@implementation RCTAppDelegate { - RCTHost *_reactHost; -} - -- (instancetype)init -{ - if (self = [super init]) { - _contextContainer = std::make_shared(); - _reactNativeConfig = std::make_shared(); - _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); - } - return self; -} +@implementation RCTAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RCTSetNewArchEnabled([self newArchEnabled]); [RCTColorSpaceUtils applyDefaultColorSpace:self.defaultColorSpace]; - BOOL enableTM = self.turboModuleEnabled; - BOOL fabricEnabled = self.fabricEnabled; - BOOL enableBridgeless = self.bridgelessEnabled; - - NSDictionary *initProps = updateInitialProps([self prepareInitialProps], fabricEnabled); + RCTAppSetupPrepareApp(application, self.turboModuleEnabled); - RCTAppSetupPrepareApp(application, enableTM); + self.rootViewFactory = [self createRCTRootViewFactory]; - UIView *rootView; - if (enableBridgeless) { - // Enable native view config interop only if both bridgeless mode and Fabric is enabled. - RCTSetUseNativeViewConfigsInBridgelessMode(fabricEnabled); + UIView *rootView = [self.rootViewFactory viewWithModuleName:self.moduleName + initialProperties:self.initialProps + launchOptions:launchOptions]; - // Enable TurboModule interop by default in Bridgeless mode - RCTEnableTurboModuleInterop(YES); - RCTEnableTurboModuleInteropBridgeProxy(YES); - - [self createReactHost]; + if (self.newArchEnabled || self.fabricEnabled) { [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; - RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:self.moduleName initialProperties:initProps]; - - RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc] - initWithSurface:surface - sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; - - rootView = (RCTRootView *)surfaceHostingProxyRootView; - rootView.backgroundColor = [UIColor systemBackgroundColor]; - } else { - if (!self.bridge) { - self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; - } - if ([self newArchEnabled]) { - self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge - contextContainer:_contextContainer]; - self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; - - [RCTComponentViewFactory currentComponentViewFactory].thirdPartyFabricComponentsProvider = self; - } - rootView = [self createRootViewWithBridge:self.bridge moduleName:self.moduleName initProps:initProps]; } [self _logWarnIfCreateRootViewWithBridgeIsOverridden]; [self customizeRootView:(RCTRootView *)rootView]; + self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [self createRootViewController]; [self setRootView:rootView toRootViewController:rootViewController]; @@ -142,21 +88,11 @@ - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge return nil; } -- (NSDictionary *)prepareInitialProps -{ - return self.initialProps; -} - - (RCTBridge *)createBridgeWithDelegate:(id)delegate launchOptions:(NSDictionary *)launchOptions { return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions]; } -- (void)customizeRootView:(RCTRootView *)rootView -{ - // Override point for customization after application launch. -} - - (UIView *)createRootViewWithBridge:(RCTBridge *)bridge moduleName:(NSString *)moduleName initProps:(NSDictionary *)initProps @@ -194,9 +130,9 @@ - (void)setRootView:(UIView *)rootView toRootViewController:(UIViewController *) rootViewController.view = rootView; } -- (BOOL)runtimeSchedulerEnabled +- (void)customizeRootView:(RCTRootView *)rootView { - return YES; + // Override point for customization after application launch. } #pragma mark - UISceneDelegate @@ -209,25 +145,6 @@ - (void)windowScene:(UIWindowScene *)windowScene [[NSNotificationCenter defaultCenter] postNotificationName:RCTWindowFrameDidChangeNotification object:self]; } -#pragma mark - RCTCxxBridgeDelegate - -- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge -{ - _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); - if ([self newArchEnabled]) { - std::shared_ptr callInvoker = - std::make_shared(_runtimeScheduler); - RCTTurboModuleManager *turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge - delegate:self - jsInvoker:callInvoker]; - _contextContainer->erase("RuntimeScheduler"); - _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); - return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); - } else { - return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler); - } -} - - (RCTColorSpace)defaultColorSpace { return RCTColorSpaceSRGB; @@ -259,11 +176,33 @@ - (BOOL)bridgelessEnabled return [self newArchEnabled]; } -#pragma mark - RCTComponentViewFactoryComponentProvider +- (NSURL *)bundleURL +{ + [NSException raise:@"RCTAppDelegate::bundleURL not implemented" + format:@"Subclasses must implement a valid getBundleURL method"]; + return nullptr; +} -- (NSDictionary> *)thirdPartyFabricComponents +#pragma mark - Bridge and Bridge Adapter properties + +- (RCTBridge *)bridge { - return @{}; + return self.rootViewFactory.bridge; +} + +- (RCTSurfacePresenterBridgeAdapter *)bridgeAdapter +{ + return self.rootViewFactory.bridgeAdapter; +} + +- (void)setBridge:(RCTBridge *)bridge +{ + self.rootViewFactory.bridge = bridge; +} + +- (void)setBridgeAdapter:(RCTSurfacePresenterBridgeAdapter *)bridgeAdapter +{ + self.rootViewFactory.bridgeAdapter = bridgeAdapter; } #pragma mark - RCTTurboModuleManagerDelegate @@ -299,43 +238,33 @@ - (Class)getModuleClassFromName:(const char *)name return RCTAppSetupDefaultModuleFromClass(moduleClass); } -#pragma mark - New Arch Utilities +#pragma mark - RCTComponentViewFactoryComponentProvider -- (void)createReactHost +- (NSDictionary> *)thirdPartyFabricComponents { - __weak __typeof(self) weakSelf = self; - _reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL] - hostDelegate:nil - turboModuleManagerDelegate:self - jsEngineProvider:^std::shared_ptr() { - return [weakSelf createJSRuntimeFactory]; - }]; - [_reactHost setBundleURLProvider:^NSURL *() { - return [weakSelf bundleURL]; - }]; - [_reactHost setContextContainerHandler:self]; - [_reactHost start]; + return @{}; } -- (std::shared_ptr)createJSRuntimeFactory +- (RCTRootViewFactory *)createRCTRootViewFactory { -#if USE_HERMES - return std::make_shared(_reactNativeConfig, nullptr); -#else - return std::make_shared(); -#endif -} + RCTRootViewFactoryConfiguration *configuration = + [[RCTRootViewFactoryConfiguration alloc] initWithBundleURL:self.bundleURL + newArchEnabled:self.fabricEnabled + turboModuleEnabled:self.turboModuleEnabled + bridgelessEnabled:self.bridgelessEnabled]; -- (void)didCreateContextContainer:(std::shared_ptr)contextContainer -{ - contextContainer->insert("ReactNativeConfig", _reactNativeConfig); -} + __weak __typeof(self) weakSelf = self; + configuration.createRootViewWithBridge = ^UIView *(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps) + { + return [weakSelf createRootViewWithBridge:bridge moduleName:moduleName initProps:initProps]; + }; -- (NSURL *)bundleURL -{ - [NSException raise:@"RCTAppDelegate::bundleURL not implemented" - format:@"Subclasses must implement a valid getBundleURL method"]; - return nullptr; + configuration.createBridgeWithDelegate = ^RCTBridge *(id delegate, NSDictionary *launchOptions) + { + return [weakSelf createBridgeWithDelegate:delegate launchOptions:launchOptions]; + }; + + return [[RCTRootViewFactory alloc] initWithConfiguration:configuration andTurboModuleManagerDelegate:self]; } @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h new file mode 100644 index 00000000000000..5047802ebc5eda --- /dev/null +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +@protocol RCTCxxBridgeDelegate; +@protocol RCTComponentViewFactoryComponentProvider; +@protocol RCTTurboModuleManagerDelegate; +@class RCTBridge; +@class RCTRootView; +@class RCTSurfacePresenterBridgeAdapter; + +NS_ASSUME_NONNULL_BEGIN + +#pragma mark - Blocks' definitions +typedef UIView *_Nonnull ( + ^RCTCreateRootViewWithBridgeBlock)(RCTBridge *bridge, NSString *moduleName, NSDictionary *initProps); +typedef RCTBridge *_Nonnull ( + ^RCTCreateBridgeWithDelegateBlock)(id delegate, NSDictionary *launchOptions); + +#pragma mark - RCTRootViewFactory Configuration +@interface RCTRootViewFactoryConfiguration : NSObject + +/// This property controls whether the App will use the Fabric renderer of the New Architecture or not. +@property (nonatomic, assign, readonly) BOOL fabricEnabled; + +/// This property controls whether React Native's new initialization layer is enabled. +@property (nonatomic, assign, readonly) BOOL bridgelessEnabled; + +/// This method controls whether the `turboModules` feature of the New Architecture is turned on or off +@property (nonatomic, assign, readonly) BOOL turboModuleEnabled; + +/// Return the bundle URL for the main bundle. +@property (nonatomic) NSURL *bundleURL; + +/** + * Use this method to initialize a new instance of `RCTRootViewFactoryConfiguration` by passing a `bundleURL` + * + * Which is the location of the JavaScript source file. When running from the packager + * this should be an absolute URL, e.g. `http://localhost:8081/index.ios.bundle`. + * When running from a locally bundled JS file, this should be a `file://` url + * pointing to a path inside the app resources, e.g. `file://.../main.jsbundle`. + * + */ +- (instancetype)initWithBundleURL:(NSURL *)bundleURL + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled; + +/** + * Block that allows to override logic of creating root view instance. + * It creates a `UIView` starting from a bridge, a module name and a set of initial properties. + * By default, it is invoked using the bridge created by `RCTCreateBridgeWithDelegateBlock` (or the default + * implementation) and the `moduleName` variable comes from `viewWithModuleName:initialProperties:launchOptions` of + * `RCTRootViewFactory`. + * + * @parameter: bridge - an instance of the `RCTBridge` object. + * @parameter: moduleName - the name of the app, used by Metro to resolve the module. + * @parameter: initProps - a set of initial properties. + * + * @returns: a UIView properly configured with a bridge for React Native. + */ +@property (nonatomic, nullable) RCTCreateRootViewWithBridgeBlock createRootViewWithBridge; + +/** + * Block that allows to override default behavior of creating bridge. + * It should return `RCTBridge` using a delegate and some launch options. + * + * By default, it is invoked passing `self` as a delegate. + * + * @parameter: delegate - an object that implements the `RCTBridgeDelegate` protocol. + * @parameter: launchOptions - a dictionary with a set of options. + * + * @returns: a newly created instance of RCTBridge. + */ +@property (nonatomic, nullable) RCTCreateBridgeWithDelegateBlock createBridgeWithDelegate; + +@end + +#pragma mark - RCTRootViewFactory +/** + * The RCTRootViewFactory is an utility class that encapsulates the logic of creating a new RCTRootView based on the + * current state of the environment. It allows you to initialize your app root view for old architecture, new + * architecture and bridgless mode. + * + * This class is used to initalize rootView in RCTAppDelegate, but you can also use it separately. + * + * Create a new instance of this class (make sure to retain it) and call the + * `viewWithModuleName:initialProperties:launchOptions` method to create new RCTRootView. + */ +@interface RCTRootViewFactory : NSObject + +@property (nonatomic, strong, nullable) RCTBridge *bridge; +@property (nonatomic, strong, nullable) RCTSurfacePresenterBridgeAdapter *bridgeAdapter; + +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration + andTurboModuleManagerDelegate:(id)turboModuleManagerDelegate; + +/** + * This method can be used to create new RCTRootViews on demand. + * + * @parameter: moduleName - the name of the app, used by Metro to resolve the module. + * @parameter: initialProperties - a set of initial properties. + * @parameter: moduleName - a dictionary with a set of options. + */ +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties + launchOptions:(NSDictionary *__nullable)launchOptions; + +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *__nullable)initialProperties; + +- (UIView *_Nonnull)viewWithModuleName:(NSString *)moduleName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm new file mode 100644 index 00000000000000..e8ebdefba1dc7e --- /dev/null +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -0,0 +1,253 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "RCTRootViewFactory.h" +#import +#import +#import +#import +#import +#import +#import "RCTAppDelegate.h" +#import "RCTAppSetupUtils.h" + +#if RN_DISABLE_OSS_PLUGIN_HEADER +#import +#else +#import +#endif +#import +#import +#import +#import +#import +#import +#import +#if USE_HERMES +#import +#else +#import +#endif +#import +#import +#import +#import +#import +#import +#import + +static NSString *const kRNConcurrentRoot = @"concurrentRoot"; + +static NSDictionary *updateInitialProps(NSDictionary *initialProps, BOOL isFabricEnabled) +{ + NSMutableDictionary *mutableProps = initialProps != NULL ? [initialProps mutableCopy] : [NSMutableDictionary new]; + // Hardcoding the Concurrent Root as it it not recommended to + // have the concurrentRoot turned off when Fabric is enabled. + mutableProps[kRNConcurrentRoot] = @(isFabricEnabled); + return mutableProps; +} + +@implementation RCTRootViewFactoryConfiguration + +- (instancetype)initWithBundleURL:(NSURL *)bundleURL + newArchEnabled:(BOOL)newArchEnabled + turboModuleEnabled:(BOOL)turboModuleEnabled + bridgelessEnabled:(BOOL)bridgelessEnabled +{ + if (self = [super init]) { + _bundleURL = bundleURL; + _fabricEnabled = newArchEnabled; + _turboModuleEnabled = turboModuleEnabled; + _bridgelessEnabled = bridgelessEnabled; + } + return self; +} + +@end + +@interface RCTRootViewFactory () { + std::shared_ptr _reactNativeConfig; + facebook::react::ContextContainer::Shared _contextContainer; +} +@end + +@interface RCTRootViewFactory () { + std::shared_ptr _runtimeScheduler; +} +@end + +@implementation RCTRootViewFactory { + RCTHost *_reactHost; + RCTRootViewFactoryConfiguration *_configuration; + __weak id _turboModuleManagerDelegate; +} + +- (instancetype)initWithConfiguration:(RCTRootViewFactoryConfiguration *)configuration + andTurboModuleManagerDelegate:(id)turboModuleManagerDelegate +{ + if (self = [super init]) { + _configuration = configuration; + _contextContainer = std::make_shared(); + _reactNativeConfig = std::make_shared(); + _contextContainer->insert("ReactNativeConfig", _reactNativeConfig); + _turboModuleManagerDelegate = turboModuleManagerDelegate; + } + return self; +} + +- (UIView *)viewWithModuleName:(NSString *)moduleName initialProperties:(NSDictionary *)initialProperties +{ + return [self viewWithModuleName:moduleName initialProperties:initialProperties launchOptions:nil]; +} + +- (UIView *)viewWithModuleName:(NSString *)moduleName +{ + return [self viewWithModuleName:moduleName initialProperties:nil launchOptions:nil]; +} + +- (UIView *)viewWithModuleName:(NSString *)moduleName + initialProperties:(NSDictionary *)initialProperties + launchOptions:(NSDictionary *)launchOptions +{ + NSDictionary *initProps = updateInitialProps(initialProperties, self->_configuration.fabricEnabled); + + if (self->_configuration.bridgelessEnabled) { + // Enable native view config interop only if both bridgeless mode and Fabric is enabled. + RCTSetUseNativeViewConfigsInBridgelessMode(self->_configuration.fabricEnabled); + + // Enable TurboModule interop by default in Bridgeless mode + RCTEnableTurboModuleInterop(YES); + RCTEnableTurboModuleInteropBridgeProxy(YES); + + [self createReactHostIfNeeded]; + + RCTFabricSurface *surface = [_reactHost createSurfaceWithModuleName:moduleName initialProperties:initProps]; + + RCTSurfaceHostingProxyRootView *surfaceHostingProxyRootView = [[RCTSurfaceHostingProxyRootView alloc] + initWithSurface:surface + sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; + + return surfaceHostingProxyRootView; + } + + [self createBridgeIfNeeded:launchOptions]; + [self createBridgeAdapterIfNeeded]; + + if (self->_configuration.createRootViewWithBridge != nil) { + return self->_configuration.createRootViewWithBridge(self.bridge, moduleName, initProps); + } + + return [self createRootViewWithBridge:self.bridge moduleName:moduleName initProps:initProps]; +} + +- (RCTBridge *)createBridgeWithDelegate:(id)delegate launchOptions:(NSDictionary *)launchOptions +{ + return [[RCTBridge alloc] initWithDelegate:delegate launchOptions:launchOptions]; +} + +- (UIView *)createRootViewWithBridge:(RCTBridge *)bridge + moduleName:(NSString *)moduleName + initProps:(NSDictionary *)initProps +{ + BOOL enableFabric = self->_configuration.fabricEnabled; + UIView *rootView = RCTAppSetupDefaultRootView(bridge, moduleName, initProps, enableFabric); + + rootView.backgroundColor = [UIColor systemBackgroundColor]; + + return rootView; +} + +#pragma mark - RCTCxxBridgeDelegate +- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge +{ + _runtimeScheduler = std::make_shared(RCTRuntimeExecutorFromBridge(bridge)); + if (RCTIsNewArchEnabled()) { + std::shared_ptr callInvoker = + std::make_shared(_runtimeScheduler); + RCTTurboModuleManager *turboModuleManager = + [[RCTTurboModuleManager alloc] initWithBridge:bridge + delegate:_turboModuleManagerDelegate + jsInvoker:callInvoker]; + _contextContainer->erase("RuntimeScheduler"); + _contextContainer->insert("RuntimeScheduler", _runtimeScheduler); + return RCTAppSetupDefaultJsExecutorFactory(bridge, turboModuleManager, _runtimeScheduler); + } else { + return RCTAppSetupJsExecutorFactoryForOldArch(bridge, _runtimeScheduler); + } +} + +- (void)createBridgeIfNeeded:(NSDictionary *)launchOptions +{ + if (self.bridge != nil) { + return; + } + + if (self->_configuration.createBridgeWithDelegate != nil) { + self.bridge = self->_configuration.createBridgeWithDelegate(self, launchOptions); + } else { + self.bridge = [self createBridgeWithDelegate:self launchOptions:launchOptions]; + } +} + +- (void)createBridgeAdapterIfNeeded +{ + if (!self->_configuration.fabricEnabled || self.bridgeAdapter) { + return; + } + + self.bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:self.bridge + contextContainer:_contextContainer]; + self.bridge.surfacePresenter = self.bridgeAdapter.surfacePresenter; +} + +#pragma mark - New Arch Utilities + +- (void)createReactHostIfNeeded +{ + if (_reactHost) { + return; + } + + __weak __typeof(self) weakSelf = self; + _reactHost = [[RCTHost alloc] initWithBundleURL:[self bundleURL] + hostDelegate:nil + turboModuleManagerDelegate:_turboModuleManagerDelegate + jsEngineProvider:^std::shared_ptr() { + return [weakSelf createJSRuntimeFactory]; + }]; + [_reactHost setBundleURLProvider:^NSURL *() { + return [weakSelf bundleURL]; + }]; + [_reactHost setContextContainerHandler:self]; + [_reactHost start]; +} + +- (std::shared_ptr)createJSRuntimeFactory +{ +#if USE_HERMES + return std::make_shared(_reactNativeConfig, nullptr); +#else + return std::make_shared(); +#endif +} + +- (void)didCreateContextContainer:(std::shared_ptr)contextContainer +{ + contextContainer->insert("ReactNativeConfig", _reactNativeConfig); +} + +- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge +{ + return [self bundleURL]; +} + +- (NSURL *)bundleURL +{ + return self->_configuration.bundleURL; +} + +@end diff --git a/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm b/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm index 489c3a91e33659..c01c39a4f5a2b6 100644 --- a/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm +++ b/packages/rn-tester/RNTester/NativeExampleViews/FlexibleSizeExampleView.mm @@ -46,9 +46,8 @@ - (instancetype)initWithFrame:(CGRect)frame AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; - _resizableRootView = [[RCTRootView alloc] initWithBridge:appDelegate.bridge - moduleName:@"RootViewSizeFlexibilityExampleApp" - initialProperties:@{}]; + _resizableRootView = + (RCTRootView *)[appDelegate.rootViewFactory viewWithModuleName:@"RootViewSizeFlexibilityExampleApp"]; [_resizableRootView setSizeFlexibility:RCTRootViewSizeFlexibilityHeight]; diff --git a/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm b/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm index 9689203576c2cd..5682d7ddead216 100644 --- a/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm +++ b/packages/rn-tester/RNTester/NativeExampleViews/UpdatePropertiesExampleView.mm @@ -41,9 +41,8 @@ - (instancetype)initWithFrame:(CGRect)frame AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; - _rootView = [[RCTRootView alloc] initWithBridge:appDelegate.bridge - moduleName:@"SetPropertiesExampleApp" - initialProperties:@{@"color" : @"beige"}]; + _rootView = (RCTRootView *)[appDelegate.rootViewFactory viewWithModuleName:@"SetPropertiesExampleApp" + initialProperties:@{@"color" : @"beige"}]; _button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; [_button setTitle:@"Native Button" forState:UIControlStateNormal]; From 09c903c43922d83ddae1602751804c34b5aeff86 Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Mon, 4 Mar 2024 14:26:51 -0800 Subject: [PATCH 079/361] fix: [TypeScript] Remove non-existent methods from `` (#43290) Summary: Using the code from `Test Plan` you will see that `ImageBackground` component doesn't have methods that declared on TypeScript side. I checked the source code and there is also nothing: https://github.com/facebook/react-native/blob/d9b0f15c844abce5e97edfd401656d84d0c84133/packages/react-native/Libraries/Image/ImageBackground.js#L47-L69 ```tsx // runtime (React Native 0.73) { "abortPrefetch": undefined, "getSize": undefined, "prefetch": undefined, "queryCache": undefined, "resizeMode": undefined } ``` ## Changelog: [GENERAL] [REMOVED] - Remove non-existent methods from `` component Pull Request resolved: https://github.com/facebook/react-native/pull/43290 Test Plan: ```tsx { if (ref) { console.log(' --- xdebug', { resizeMode: ref.resizeMode, queryCache: ref.queryCache, getSize: ref.getSize, prefetch: ref.prefetch, abortPrefetch: ref.abortPrefetch, }); } }} style={{ width: '100%', height: '100%', }} source={{ uri: 'https://upload.wikimedia.org/wikipedia/commons/8/87/Arturo_Nieto-Dorantes.webp', }} /> ``` Reviewed By: cipolleschi Differential Revision: D54466918 Pulled By: NickGerleman fbshipit-source-id: 39bb555954fd6146f0e99106dbe9c13353191081 --- packages/react-native/Libraries/Image/Image.d.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/packages/react-native/Libraries/Image/Image.d.ts b/packages/react-native/Libraries/Image/Image.d.ts index a8725c419f5c29..9eeb0cbd12fc98 100644 --- a/packages/react-native/Libraries/Image/Image.d.ts +++ b/packages/react-native/Libraries/Image/Image.d.ts @@ -379,16 +379,4 @@ export interface ImageBackgroundProps extends ImagePropsBase { declare class ImageBackgroundComponent extends React.Component {} declare const ImageBackgroundBase: Constructor & typeof ImageBackgroundComponent; -export class ImageBackground extends ImageBackgroundBase { - resizeMode: ImageResizeMode; - getSize( - uri: string, - success: (width: number, height: number) => void, - failure: (error: any) => void, - ): any; - prefetch(url: string): any; - abortPrefetch?(requestId: number): void; - queryCache?( - urls: string[], - ): Promise<{[url: string]: 'memory' | 'disk' | 'disk/memory'}>; -} +export class ImageBackground extends ImageBackgroundBase {} From 923d4abd7b8144424ad0c4f57d7bd11f905d4a34 Mon Sep 17 00:00:00 2001 From: Sam Zhou Date: Mon, 4 Mar 2024 17:10:51 -0800 Subject: [PATCH 080/361] Update hermes-parser and related packages in fbsource to 0.20.1 (#43317) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43317 Bump hermes-parser and related packages to [0.20.1](https://github.com/facebook/hermes/blob/main/tools/hermes-parser/js/CHANGELOG.md). Changelog: [internal] Reviewed By: pieterv Differential Revision: D54510131 fbshipit-source-id: 064d2078e85e465552dccf5c1368e49707c3aeef --- package.json | 8 +- .../package.json | 2 +- packages/react-native-codegen/package.json | 4 +- yarn.lock | 74 +++++++++---------- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/package.json b/package.json index 0bdc71145749af..1b5e63d46e3a40 100644 --- a/package.json +++ b/package.json @@ -87,11 +87,11 @@ "eslint-plugin-react-native": "^4.0.0", "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", - "flow-api-translator": "0.20.0", + "flow-api-translator": "0.20.1", "flow-bin": "^0.229.2", "glob": "^7.1.1", - "hermes-eslint": "0.20.0", - "hermes-transform": "0.20.0", + "hermes-eslint": "0.20.1", + "hermes-transform": "0.20.1", "inquirer": "^7.1.0", "jest": "^29.6.3", "jest-junit": "^10.0.0", @@ -104,7 +104,7 @@ "node-fetch": "^2.2.0", "nullthrows": "^1.1.1", "prettier": "2.8.8", - "prettier-plugin-hermes-parser": "0.20.0", + "prettier-plugin-hermes-parser": "0.20.1", "react": "18.2.0", "react-test-renderer": "18.2.0", "rimraf": "^3.0.2", diff --git a/packages/react-native-babel-transformer/package.json b/packages/react-native-babel-transformer/package.json index b2f0f0fbc1fb0e..301ee835ec6bad 100644 --- a/packages/react-native-babel-transformer/package.json +++ b/packages/react-native-babel-transformer/package.json @@ -17,7 +17,7 @@ "dependencies": { "@babel/core": "^7.20.0", "@react-native/babel-preset": "0.75.0-main", - "hermes-parser": "0.20.0", + "hermes-parser": "0.20.1", "nullthrows": "^1.1.1" }, "peerDependencies": { diff --git a/packages/react-native-codegen/package.json b/packages/react-native-codegen/package.json index 98021a606418a0..64be2aef7041ce 100644 --- a/packages/react-native-codegen/package.json +++ b/packages/react-native-codegen/package.json @@ -31,7 +31,7 @@ "dependencies": { "@babel/parser": "^7.20.0", "glob": "^7.1.1", - "hermes-parser": "0.20.0", + "hermes-parser": "0.20.1", "invariant": "^2.2.4", "jscodeshift": "^0.14.0", "mkdirp": "^0.5.1", @@ -49,7 +49,7 @@ "@babel/plugin-transform-flow-strip-types": "^7.20.0", "@babel/preset-env": "^7.20.0", "chalk": "^4.0.0", - "hermes-estree": "0.20.0", + "hermes-estree": "0.20.1", "micromatch": "^4.0.4", "prettier": "2.8.8", "rimraf": "^3.0.2", diff --git a/yarn.lock b/yarn.lock index 0818cd058c339e..f702dabecf3a7e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5137,18 +5137,18 @@ flatted@^3.1.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.2.tgz#64bfed5cb68fe3ca78b3eb214ad97b63bedce561" integrity sha512-JaTY/wtrcSyvXJl4IMFHPKyFur1sE9AUqc0QnhOaJ0CxHtAoIV8pYDzeEfAaNEtGkOfq4gr3LBFmdXW5mOQFnA== -flow-api-translator@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/flow-api-translator/-/flow-api-translator-0.20.0.tgz#43f8efed80da1c01f52f96c224fbbce9477792a7" - integrity sha512-51Fvqnn1VFA98guXk4R39TTz1SCVP3A/pIldXqgXcwW4OGGBK9XFwo73TdE0+rYxqRHVg0HWpM7IaRvDrWPiJw== +flow-api-translator@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/flow-api-translator/-/flow-api-translator-0.20.1.tgz#22d2be2f95edc6c397d00c0bf41d419a2eae35ba" + integrity sha512-RY/flm0omS6LjKna93HUUtx2bUf9qTX9i90RtUdZoVSB7u41nEAebmyM+mpOPsNqvCEIHQxxXs/22/PkQW1OCw== dependencies: "@babel/code-frame" "^7.16.0" "@typescript-eslint/visitor-keys" "^5.42.0" flow-enums-runtime "^0.0.6" - hermes-eslint "0.20.0" - hermes-estree "0.20.0" - hermes-parser "0.20.0" - hermes-transform "0.20.0" + hermes-eslint "0.20.1" + hermes-estree "0.20.1" + hermes-parser "0.20.1" + hermes-transform "0.20.1" flow-bin@^0.229.2: version "0.229.2" @@ -5537,14 +5537,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hermes-eslint@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/hermes-eslint/-/hermes-eslint-0.20.0.tgz#b34f6ced2134423b05d394794b34a57c47290476" - integrity sha512-XVNfDSsU/mgbEkhv1afIIrzi131tou1N/paq7PhbExXM/XEzcLKRgrV4l61ODy8moK3tfiZ9WLb6A0pDuwaCNA== +hermes-eslint@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/hermes-eslint/-/hermes-eslint-0.20.1.tgz#4a731b47a6d169bbd4514aaa74bd812fd90f3554" + integrity sha512-EhdvFV6RkPIJvbqN8oqFZO1oF4NlPWMjhMjCWkUJX1YL1MZMfkF7nSdx6RKTq6xK17yo+Bgv88L21xuH9GtRpw== dependencies: esrecurse "^4.3.0" - hermes-estree "0.20.0" - hermes-parser "0.20.0" + hermes-estree "0.20.1" + hermes-parser "0.20.1" hermes-estree@0.17.0: version "0.17.0" @@ -5556,10 +5556,10 @@ hermes-estree@0.18.2: resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.18.2.tgz#fd450fa1659cf074ceaa2ddeeb21674f3b2342f3" integrity sha512-KoLsoWXJ5o81nit1wSyEZnWUGy9cBna9iYMZBR7skKh7okYAYKqQ9/OczwpMHn/cH0hKDyblulGsJ7FknlfVxQ== -hermes-estree@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.20.0.tgz#f8d7be10495274bfeb02c8b43d511a5ace19f7e7" - integrity sha512-TbBq98tclEfJE3NatmWtSMk51RXKvvBlaJqm/XVsJlP5mkXNrDx5FUTCoN221/cyQ4PcoJw/aRELbi0QeAw6Bg== +hermes-estree@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.20.1.tgz#0b9a544cf883a779a8e1444b915fa365bef7f72d" + integrity sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg== hermes-parser@0.17.0: version "0.17.0" @@ -5575,12 +5575,12 @@ hermes-parser@0.18.2: dependencies: hermes-estree "0.18.2" -hermes-parser@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.20.0.tgz#71fe1130a2bb12bec1091b3fedc5301b8745bb26" - integrity sha512-vYTT4KeXAa6WmolPl++QLvcBi86ao5i9jJ4JCLX5s1c9eC1Xf/9AY/RUlKl9KY66Sg2uyuHE9A5BqbUT+hbbaA== +hermes-parser@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.20.1.tgz#ad10597b99f718b91e283f81cbe636c50c3cff92" + integrity sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA== dependencies: - hermes-estree "0.20.0" + hermes-estree "0.20.1" hermes-profile-transformer@^0.0.6: version "0.0.6" @@ -5589,17 +5589,17 @@ hermes-profile-transformer@^0.0.6: dependencies: source-map "^0.7.3" -hermes-transform@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.20.0.tgz#b5879e982e6a64606ab6e9287842156ea07bd872" - integrity sha512-Q1dqaXJvJP6NAzek3z0bmK24M+Vn2jXsXIk+nau/PJQeH0Z5SwjcTUsZUOELdcMzBjtYG3xbM/pGMcg2/eMjCQ== +hermes-transform@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.20.1.tgz#910bd0ea7cc58eca4c0acadb413d779b70dd3803" + integrity sha512-gpetyzAQvuLXVWIk8/I2A/ei/5+o8eT+QuSGd8FcWpXoYxVkYjVKLVNE9xKLsEkk2wQ1tXODY5OeOZoaz9jL7Q== dependencies: "@babel/code-frame" "^7.16.0" esquery "^1.4.0" flow-enums-runtime "^0.0.6" - hermes-eslint "0.20.0" - hermes-estree "0.20.0" - hermes-parser "0.20.0" + hermes-eslint "0.20.1" + hermes-estree "0.20.1" + hermes-parser "0.20.1" homedir-polyfill@^1.0.0, homedir-polyfill@^1.0.1: version "1.0.3" @@ -7878,14 +7878,14 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier-plugin-hermes-parser@0.20.0: - version "0.20.0" - resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.20.0.tgz#32a7b46901fd8c93aabffb93f2cec8ae7ea6a5d5" - integrity sha512-IzUrpE5eP61N7aeLGXNqBbqz4BzzvRi0v6B5a4Yn/5QqSs/HPZvWXTNK9z4svur01ZJezFIYwy5psb6R3YpVJg== +prettier-plugin-hermes-parser@0.20.1: + version "0.20.1" + resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.20.1.tgz#a5f395ae77170813e631f4538c9ef29311b4db1d" + integrity sha512-T6dfa1++ckTxd3MbLxS6sTv1T3yvTu1drahNt3g34hyCzSwYTKTByocLyhd1A9j9uCUlIPD+ogum7+i1h3+CEw== dependencies: - hermes-estree "0.20.0" - hermes-parser "0.20.0" - prettier-plugin-hermes-parser "0.20.0" + hermes-estree "0.20.1" + hermes-parser "0.20.1" + prettier-plugin-hermes-parser "0.20.1" prettier@2.8.8: version "2.8.8" From 73664f576aaa472d5c8fb2a02e0ddd017bbb2ea4 Mon Sep 17 00:00:00 2001 From: Saad Najmi Date: Mon, 4 Mar 2024 18:51:17 -0800 Subject: [PATCH 081/361] feat(iOS): Implement cursor style prop (#43078) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Implement the cursor style prop for iOS (and consequently, visionOS), as described in this RFC: https://github.com/react-native-community/discussions-and-proposals/pull/750 See related PR in React Native macOS, where we target macOS and visionOS (not running in iPad compatibility mode) with the same change: https://github.com/microsoft/react-native-macos/pull/2080 Docs update: https://github.com/facebook/react-native-website/pull/4033 ## Changelog: [IOS] [ADDED] - Implement cursor style prop Pull Request resolved: https://github.com/facebook/react-native/pull/43078 Test Plan: See the added example page, running on iOS with the new architecture enabled. This also runs the same on the old architecture. https://github.com/facebook/react-native/assets/6722175/2af60a0c-1c1f-45c4-8d66-a20f6d5815df See the example page running on all three apple platforms. The JS is slightly different because: 1. The "macOS Cursors" example is not part of this PR but the one in React Native macOS. 2. This PR (and exapmple) has went though a bunch of iterations and It got hard taking videos of every change 😅 https://github.com/facebook/react-native/assets/6722175/7775ba7c-8624-4873-a735-7665b94b7233 ## Notes - React Native macOS added the cursor prop to View with https://github.com/microsoft/react-native-macos/pull/760 and Text with https://github.com/microsoft/react-native-macos/pull/1469 . Much of the implementation comes from there. - Due to an Apple bug, as of iOS 17.4 Beta 4, the shape of the iOS cursor hover effect doesn't render in the correct bounds (but it does on visionOS). I've worked around it with an ifdef. The result is that the hover effect will work on iOS and visionOS, but not iPad apps running in compatibility mode on visionOS. Reviewed By: NickGerleman Differential Revision: D54512945 Pulled By: vincentriemer fbshipit-source-id: 699e3a01a901f55a466a2c1a19f667aede5aab80 --- .../View/ReactNativeStyleAttributes.js | 1 + .../Libraries/StyleSheet/StyleSheetTypes.d.ts | 4 + .../Libraries/StyleSheet/StyleSheetTypes.js | 3 + .../__snapshots__/public-api-test.js.snap | 2 + packages/react-native/React/Base/RCTConvert.h | 3 + .../react-native/React/Base/RCTConvert.mm | 9 ++ .../View/RCTViewComponentView.mm | 30 +++++ packages/react-native/React/Views/RCTCursor.h | 13 ++ packages/react-native/React/Views/RCTView.h | 3 + packages/react-native/React/Views/RCTView.m | 28 ++++ .../react-native/React/Views/RCTViewManager.m | 2 + .../components/view/BaseViewProps.cpp | 9 ++ .../renderer/components/view/BaseViewProps.h | 2 + .../components/view/ViewShadowNode.cpp | 2 +- .../renderer/components/view/conversions.h | 22 ++++ .../renderer/components/view/primitives.h | 2 + .../js/examples/Cursor/CursorExample.js | 124 ++++++++++++++++++ .../rn-tester/js/utils/RNTesterList.ios.js | 4 + 18 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 packages/react-native/React/Views/RCTCursor.h create mode 100644 packages/rn-tester/js/examples/Cursor/CursorExample.js diff --git a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js index e870c99355d1e0..e0c82a319f3756 100644 --- a/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js +++ b/packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js @@ -144,6 +144,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = { borderTopLeftRadius: true, borderTopRightRadius: true, borderTopStartRadius: true, + cursor: true, opacity: true, pointerEvents: true, diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts index 5a9121be11765f..f4a99256313845 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -27,6 +27,8 @@ export type DimensionValue = type AnimatableNumericValue = number | Animated.AnimatedNode; type AnimatableStringValue = string | Animated.AnimatedNode; +export type CursorValue = 'auto' | 'pointer'; + /** * Flex Prop Types * @see https://reactnative.dev/docs/flexbox @@ -274,6 +276,7 @@ export interface ViewStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle { * Controls whether the View can be the target of touch events. */ pointerEvents?: 'box-none' | 'none' | 'box-only' | 'auto' | undefined; + cursor?: CursorValue | undefined; } export type FontVariant = @@ -403,4 +406,5 @@ export interface ImageStyle extends FlexStyle, ShadowStyleIOS, TransformsStyle { tintColor?: ColorValue | undefined; opacity?: AnimatableNumericValue | undefined; objectFit?: 'cover' | 'contain' | 'fill' | 'scale-down' | undefined; + cursor?: CursorValue | undefined; } diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index c39bcb97ea3ca5..59a7afc81d8c3d 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -37,6 +37,8 @@ export type EdgeInsetsValue = { export type DimensionValue = number | string | 'auto' | AnimatedNode | null; export type AnimatableNumericValue = number | AnimatedNode; +export type CursorValue = 'auto' | 'pointer'; + /** * React Native's layout system is based on Flexbox and is powered both * on iOS and Android by an open source project called `Yoga`: @@ -729,6 +731,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ opacity?: AnimatableNumericValue, elevation?: number, pointerEvents?: 'auto' | 'none' | 'box-none' | 'box-only', + cursor?: CursorValue, }>; export type ____ViewStyle_Internal = $ReadOnly<{ diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 54740e29317cee..edf3153cfa18ff 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -7428,6 +7428,7 @@ export type EdgeInsetsValue = { }; export type DimensionValue = number | string | \\"auto\\" | AnimatedNode | null; export type AnimatableNumericValue = number | AnimatedNode; +export type CursorValue = \\"auto\\" | \\"pointer\\"; type ____LayoutStyle_Internal = $ReadOnly<{ display?: \\"none\\" | \\"flex\\", width?: DimensionValue, @@ -7578,6 +7579,7 @@ export type ____ViewStyle_InternalCore = $ReadOnly<{ opacity?: AnimatableNumericValue, elevation?: number, pointerEvents?: \\"auto\\" | \\"none\\" | \\"box-none\\" | \\"box-only\\", + cursor?: CursorValue, }>; export type ____ViewStyle_Internal = $ReadOnly<{ ...____ViewStyle_InternalCore, diff --git a/packages/react-native/React/Base/RCTConvert.h b/packages/react-native/React/Base/RCTConvert.h index e8db7a07623fa3..8b819fda89e602 100644 --- a/packages/react-native/React/Base/RCTConvert.h +++ b/packages/react-native/React/Base/RCTConvert.h @@ -11,6 +11,7 @@ #import #import #import +#import #import #import #import @@ -89,6 +90,8 @@ typedef NSURL RCTFileURL; + (UIBarStyle)UIBarStyle:(id)json __deprecated; #endif ++ (RCTCursor)RCTCursor:(id)json; + + (CGFloat)CGFloat:(id)json; + (CGPoint)CGPoint:(id)json; + (CGSize)CGSize:(id)json; diff --git a/packages/react-native/React/Base/RCTConvert.mm b/packages/react-native/React/Base/RCTConvert.mm index 2d2775f50f39bf..fb5e43c6d2edff 100644 --- a/packages/react-native/React/Base/RCTConvert.mm +++ b/packages/react-native/React/Base/RCTConvert.mm @@ -545,6 +545,15 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC UIBarStyleDefault, integerValue) +RCT_ENUM_CONVERTER( + RCTCursor, + (@{ + @"auto" : @(RCTCursorAuto), + @"pointer" : @(RCTCursorPointer), + }), + RCTCursorAuto, + integerValue) + static void convertCGStruct(const char *type, NSArray *fields, CGFloat *result, id json) { NSUInteger count = fields.count; diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index a015c450ee21b7..6bdfb69e171a29 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -257,6 +257,11 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & self.layer.doubleSided = newViewProps.backfaceVisibility == BackfaceVisibility::Visible; } + // `cursor` + if (oldViewProps.cursor != newViewProps.cursor) { + needsInvalidateLayer = YES; + } + // `shouldRasterize` if (oldViewProps.shouldRasterize != newViewProps.shouldRasterize) { self.layer.shouldRasterize = newViewProps.shouldRasterize; @@ -592,6 +597,31 @@ - (void)invalidateLayer layer.shadowPath = nil; } + // Stage 1.5. Cursor / Hover Effects + if (@available(iOS 17.0, *)) { + UIHoverStyle *hoverStyle = nil; + if (_props->cursor == Cursor::Pointer) { + const RCTCornerInsets cornerInsets = + RCTGetCornerInsets(RCTCornerRadiiFromBorderRadii(borderMetrics.borderRadii), UIEdgeInsetsZero); +#if TARGET_OS_IOS + // Due to an Apple bug, it seems on iOS, UIShapes made with `[UIShape shapeWithBezierPath:]` + // evaluate their shape on the superviews' coordinate space. This leads to the hover shape + // rendering incorrectly on iOS, iOS apps in compatibility mode on visionOS, but not on visionOS. + // To work around this, for iOS, we can calculate the border path based on `view.frame` (the + // superview's coordinate space) instead of view.bounds. + CGPathRef borderPath = RCTPathCreateWithRoundedRect(self.frame, cornerInsets, NULL); +#else // TARGET_OS_VISION + CGPathRef borderPath = RCTPathCreateWithRoundedRect(self.bounds, cornerInsets, NULL); +#endif + UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:borderPath]; + CGPathRelease(borderPath); + UIShape *shape = [UIShape shapeWithBezierPath:bezierPath]; + + hoverStyle = [UIHoverStyle styleWithEffect:[UIHoverAutomaticEffect effect] shape:shape]; + } + [self setHoverStyle:hoverStyle]; + } + // Stage 2. Border Rendering const bool useCoreAnimationBorderRendering = borderMetrics.borderColors.isUniform() && borderMetrics.borderWidths.isUniform() && diff --git a/packages/react-native/React/Views/RCTCursor.h b/packages/react-native/React/Views/RCTCursor.h new file mode 100644 index 00000000000000..63fcb3e123e390 --- /dev/null +++ b/packages/react-native/React/Views/RCTCursor.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +typedef NS_ENUM(NSInteger, RCTCursor) { + RCTCursorAuto, + RCTCursorPointer, +}; diff --git a/packages/react-native/React/Views/RCTView.h b/packages/react-native/React/Views/RCTView.h index 200d8b451bf59e..8abda6e8538d79 100644 --- a/packages/react-native/React/Views/RCTView.h +++ b/packages/react-native/React/Views/RCTView.h @@ -10,6 +10,7 @@ #import #import #import +#import #import extern const UIAccessibilityTraits SwitchAccessibilityTrait; @@ -120,6 +121,8 @@ extern const UIAccessibilityTraits SwitchAccessibilityTrait; */ @property (nonatomic, assign) UIEdgeInsets hitTestEdgeInsets; +@property (nonatomic, assign) RCTCursor cursor; + /** * (Experimental and unused for Paper) Pointer event handlers. */ diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index 6e6f9cd2761035..292956e268a723 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -136,6 +136,7 @@ - (instancetype)initWithFrame:(CGRect)frame _borderCurve = RCTBorderCurveCircular; _borderStyle = RCTBorderStyleSolid; _hitTestEdgeInsets = UIEdgeInsetsZero; + _cursor = RCTCursorAuto; _backgroundColor = super.backgroundColor; } @@ -796,6 +797,8 @@ - (void)displayLayer:(CALayer *)layer RCTUpdateShadowPathForView(self); + RCTUpdateHoverStyleForView(self); + const RCTCornerRadii cornerRadii = [self cornerRadii]; const UIEdgeInsets borderInsets = [self bordersAsInsets]; const RCTBorderColors borderColors = [self borderColorsWithTraitCollection:self.traitCollection]; @@ -891,6 +894,31 @@ static void RCTUpdateShadowPathForView(RCTView *view) } } +static void RCTUpdateHoverStyleForView(RCTView *view) +{ + if (@available(iOS 17.0, *)) { + UIHoverStyle *hoverStyle = nil; + if ([view cursor] == RCTCursorPointer) { + const RCTCornerRadii cornerRadii = [view cornerRadii]; + const RCTCornerInsets cornerInsets = RCTGetCornerInsets(cornerRadii, UIEdgeInsetsZero); +#if TARGET_OS_IOS + // Due to an Apple bug, it seems on iOS, `[UIShape shapeWithBezierPath:]` needs to + // be calculated in the superviews' coordinate space (view.frame). This is not true + // on other platforms like visionOS. + CGPathRef borderPath = RCTPathCreateWithRoundedRect(view.frame, cornerInsets, NULL); +#else // TARGET_OS_VISION + CGPathRef borderPath = RCTPathCreateWithRoundedRect(view.bounds, cornerInsets, NULL); +#endif + UIBezierPath *bezierPath = [UIBezierPath bezierPathWithCGPath:borderPath]; + CGPathRelease(borderPath); + UIShape *shape = [UIShape shapeWithBezierPath:bezierPath]; + + hoverStyle = [UIHoverStyle styleWithEffect:[UIHoverHighlightEffect effect] shape:shape]; + } + [view setHoverStyle:hoverStyle]; + } +} + - (void)updateClippingForLayer:(CALayer *)layer { CALayer *mask = nil; diff --git a/packages/react-native/React/Views/RCTViewManager.m b/packages/react-native/React/Views/RCTViewManager.m index 66c449d7e81a00..0a0126545bde5f 100644 --- a/packages/react-native/React/Views/RCTViewManager.m +++ b/packages/react-native/React/Views/RCTViewManager.m @@ -13,6 +13,7 @@ #import "RCTBridge.h" #import "RCTConvert+Transform.h" #import "RCTConvert.h" +#import "RCTCursor.h" #import "RCTLog.h" #import "RCTShadowView.h" #import "RCTUIManager.h" @@ -195,6 +196,7 @@ - (RCTShadowView *)shadowView RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor) RCT_REMAP_VIEW_PROPERTY(backfaceVisibility, layer.doubleSided, css_backface_visibility_t) +RCT_EXPORT_VIEW_PROPERTY(cursor, RCTCursor) RCT_REMAP_VIEW_PROPERTY(opacity, alpha, CGFloat) RCT_REMAP_VIEW_PROPERTY(shadowColor, layer.shadowColor, CGColor) RCT_REMAP_VIEW_PROPERTY(shadowOffset, layer.shadowOffset, CGSize) diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp index 3d55f25c38cb9c..358fb3773ebf99 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.cpp @@ -140,6 +140,14 @@ BaseViewProps::BaseViewProps( "shadowRadius", sourceProps.shadowRadius, {})), + cursor( + CoreFeatures::enablePropIteratorSetter ? sourceProps.cursor + : convertRawProp( + context, + rawProps, + "cursor", + sourceProps.cursor, + {})), transform( CoreFeatures::enablePropIteratorSetter ? sourceProps.transform : convertRawProp( @@ -281,6 +289,7 @@ void BaseViewProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(collapsable); RAW_SET_PROP_SWITCH_CASE_BASIC(removeClippedSubviews); RAW_SET_PROP_SWITCH_CASE_BASIC(experimental_layoutConformance); + RAW_SET_PROP_SWITCH_CASE_BASIC(cursor); // events field VIEW_EVENT_CASE(PointerEnter); VIEW_EVENT_CASE(PointerEnterCapture); diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h index 5bacae92232f3d..73cf45387e871c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/BaseViewProps.h @@ -52,6 +52,8 @@ class BaseViewProps : public YogaStylableProps, public AccessibilityProps { Float shadowOpacity{}; Float shadowRadius{3}; + Cursor cursor{}; + // Transform Transform transform{}; TransformOrigin transformOrigin{ diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp index fe11e92e1a5771..9c92eac7ccc9e9 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/ViewShadowNode.cpp @@ -60,7 +60,7 @@ void ViewShadowNode::initialize() noexcept { viewProps.accessibilityElementsHidden || viewProps.accessibilityViewIsModal || viewProps.importantForAccessibility != ImportantForAccessibility::Auto || - viewProps.removeClippedSubviews || + viewProps.removeClippedSubviews || viewProps.cursor != Cursor::Auto || HostPlatformViewTraitsInitializer::formsStackingContext(viewProps); bool formsView = formsStackingContext || diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index aa6fb367daab7d..bbd9f46cfafa6a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -705,6 +705,28 @@ inline void fromRawValue( react_native_expect(false); } +inline void fromRawValue( + const PropsParserContext& context, + const RawValue& value, + Cursor& result) { + result = Cursor::Auto; + react_native_expect(value.hasType()); + if (!value.hasType()) { + return; + } + auto stringValue = (std::string)value; + if (stringValue == "auto") { + result = Cursor::Auto; + return; + } + if (stringValue == "pointer") { + result = Cursor::Pointer; + return; + } + LOG(ERROR) << "Could not parse Cursor:" << stringValue; + react_native_expect(false); +} + inline void fromRawValue( const PropsParserContext& /*context*/, const RawValue& value, diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h b/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h index 162f2292cc6a64..09f98979517a13 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h @@ -91,6 +91,8 @@ enum class BorderCurve : uint8_t { Circular, Continuous }; enum class BorderStyle : uint8_t { Solid, Dotted, Dashed }; +enum class Cursor : uint8_t { Auto, Pointer }; + enum class LayoutConformance : uint8_t { Undefined, Classic, Strict }; template diff --git a/packages/rn-tester/js/examples/Cursor/CursorExample.js b/packages/rn-tester/js/examples/Cursor/CursorExample.js new file mode 100644 index 00000000000000..77936112305aff --- /dev/null +++ b/packages/rn-tester/js/examples/Cursor/CursorExample.js @@ -0,0 +1,124 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +'use strict'; + +const React = require('react'); +const {StyleSheet, Text, View} = require('react-native'); + +const styles = StyleSheet.create({ + invisibleBox: { + width: 100, + height: 100, + }, + box: { + width: 100, + height: 100, + borderWidth: 2, + }, + circle: { + width: 100, + height: 100, + borderWidth: 2, + borderRadius: 100, + }, + halfcircle: { + width: 100, + height: 100, + borderWidth: 2, + borderTopStartRadius: 100, + borderBottomStartRadius: 100, + }, + solid: { + backgroundColor: 'blue', + }, + pointer: { + cursor: 'pointer', + }, + row: { + flexDirection: 'row', + flexWrap: 'wrap', + gap: 10, + }, + centerContent: { + justifyContent: 'center', + alignItems: 'center', + }, +}); + +function CursorExampleAuto() { + return ( + + + + + + + + + ); +} + +function CursorExamplePointer() { + return ( + + + + + + + + + ); +} + +function CursorExamplePointer() { + return ( + + + + + + + + + ); +} + +function CursorExampleViewFlattening() { + return ( + + + pointer + + + ); +} + +exports.title = 'Cursor'; +exports.category = 'UI'; +exports.description = + 'Demonstrates setting a cursor, which affects the appearance when a pointer is over the View.'; +exports.examples = [ + { + title: 'Default', + description: "Cursor: 'auto' or no cursor set ", + render: CursorExampleAuto, + }, + { + title: 'Pointer', + description: 'cursor: pointer', + render: CursorExamplePointer, + }, + { + title: 'View flattening', + description: 'Views with a cursor do not get flattened', + render: CursorExampleViewFlattening, + }, +]; diff --git a/packages/rn-tester/js/utils/RNTesterList.ios.js b/packages/rn-tester/js/utils/RNTesterList.ios.js index fa0587ccd1454c..4dbcabd8b3f728 100644 --- a/packages/rn-tester/js/utils/RNTesterList.ios.js +++ b/packages/rn-tester/js/utils/RNTesterList.ios.js @@ -195,6 +195,10 @@ const APIs: Array = ([ key: 'CrashExample', module: require('../examples/Crash/CrashExample'), }, + { + key: 'CursorExample', + module: require('../examples/Cursor/CursorExample'), + }, { key: 'DevSettings', module: require('../examples/DevSettings/DevSettingsExample'), From 0dc5c5f1f43701f396d2eb49bbabd2bfd2338cf4 Mon Sep 17 00:00:00 2001 From: Ryan Linton Date: Mon, 4 Mar 2024 19:07:53 -0800 Subject: [PATCH 082/361] Update bridge to handle long values (#43158) Summary: This adds support for 64 bit integer (long) values to the Android bridge. Per the wide gamut color [RFC](https://github.com/react-native-community/discussions-and-proposals/pull/738) Android encodes wide gamut colors as long values so we need to update the bridge to support 64 bit integers as well since these classes will soon receive those values from native. ## Changelog: [ANDROID] [ADDED] - Update bridge to handle long values Pull Request resolved: https://github.com/facebook/react-native/pull/43158 Test Plan: I added tests where I could for long types and truncation. I would like to add tests for ReadableNativeArray and ReadableNativeMap but I'm not sure how to go about mocking HybridData. Reviewed By: cipolleschi Differential Revision: D54276496 Pulled By: NickGerleman fbshipit-source-id: 1e71b5283f662748beef1bdb34d9c86099baecb0 --- .../ReactAndroid/api/ReactAndroid.api | 12 ++++ .../facebook/react/bridge/JavaOnlyArray.java | 15 ++++- .../facebook/react/bridge/JavaOnlyMap.java | 12 ++++ .../facebook/react/bridge/ReadableArray.java | 2 + .../facebook/react/bridge/ReadableMap.java | 2 + .../react/bridge/ReadableNativeArray.java | 5 ++ .../react/bridge/ReadableNativeMap.java | 5 ++ .../facebook/react/bridge/WritableArray.java | 2 + .../facebook/react/bridge/WritableMap.java | 2 + .../react/bridge/WritableNativeArray.java | 3 + .../react/bridge/WritableNativeMap.java | 3 + .../react/bridge/JavaOnlyArrayTest.kt | 20 +++++-- .../facebook/react/bridge/JavaOnlyMapTest.kt | 55 +++++++++++++++++++ 13 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyMapTest.kt diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index d1144df5d315b5..d2437b2c8a25a4 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -823,6 +823,7 @@ public class com/facebook/react/bridge/JavaOnlyArray : com/facebook/react/bridge public fun getDouble (I)D public fun getDynamic (I)Lcom/facebook/react/bridge/Dynamic; public fun getInt (I)I + public fun getLong (I)J public fun getMap (I)Lcom/facebook/react/bridge/ReadableMap; public fun getString (I)Ljava/lang/String; public fun getType (I)Lcom/facebook/react/bridge/ReadableType; @@ -833,6 +834,7 @@ public class com/facebook/react/bridge/JavaOnlyArray : com/facebook/react/bridge public fun pushBoolean (Z)V public fun pushDouble (D)V public fun pushInt (I)V + public fun pushLong (J)V public fun pushMap (Lcom/facebook/react/bridge/ReadableMap;)V public fun pushNull ()V public fun pushString (Ljava/lang/String;)V @@ -853,6 +855,7 @@ public class com/facebook/react/bridge/JavaOnlyMap : com/facebook/react/bridge/R public fun getDynamic (Ljava/lang/String;)Lcom/facebook/react/bridge/Dynamic; public fun getEntryIterator ()Ljava/util/Iterator; public fun getInt (Ljava/lang/String;)I + public fun getLong (Ljava/lang/String;)J public fun getMap (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableMap; public fun getString (Ljava/lang/String;)Ljava/lang/String; public fun getType (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableType; @@ -866,6 +869,7 @@ public class com/facebook/react/bridge/JavaOnlyMap : com/facebook/react/bridge/R public fun putBoolean (Ljava/lang/String;Z)V public fun putDouble (Ljava/lang/String;D)V public fun putInt (Ljava/lang/String;I)V + public fun putLong (Ljava/lang/String;J)V public fun putMap (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V public fun putNull (Ljava/lang/String;)V public fun putString (Ljava/lang/String;Ljava/lang/String;)V @@ -1326,6 +1330,7 @@ public abstract interface class com/facebook/react/bridge/ReadableArray { public abstract fun getDouble (I)D public abstract fun getDynamic (I)Lcom/facebook/react/bridge/Dynamic; public abstract fun getInt (I)I + public abstract fun getLong (I)J public abstract fun getMap (I)Lcom/facebook/react/bridge/ReadableMap; public abstract fun getString (I)Ljava/lang/String; public abstract fun getType (I)Lcom/facebook/react/bridge/ReadableType; @@ -1341,6 +1346,7 @@ public abstract interface class com/facebook/react/bridge/ReadableMap { public abstract fun getDynamic (Ljava/lang/String;)Lcom/facebook/react/bridge/Dynamic; public abstract fun getEntryIterator ()Ljava/util/Iterator; public abstract fun getInt (Ljava/lang/String;)I + public abstract fun getLong (Ljava/lang/String;)J public abstract fun getMap (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableMap; public abstract fun getString (Ljava/lang/String;)Ljava/lang/String; public abstract fun getType (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableType; @@ -1365,6 +1371,7 @@ public class com/facebook/react/bridge/ReadableNativeArray : com/facebook/react/ public fun getDynamic (I)Lcom/facebook/react/bridge/Dynamic; public fun getInt (I)I public static fun getJNIPassCounter ()I + public fun getLong (I)J public synthetic fun getMap (I)Lcom/facebook/react/bridge/ReadableMap; public fun getMap (I)Lcom/facebook/react/bridge/ReadableNativeMap; public fun getString (I)Ljava/lang/String; @@ -1385,6 +1392,7 @@ public class com/facebook/react/bridge/ReadableNativeMap : com/facebook/react/br public fun getEntryIterator ()Ljava/util/Iterator; public fun getInt (Ljava/lang/String;)I public static fun getJNIPassCounter ()I + public fun getLong (Ljava/lang/String;)J public synthetic fun getMap (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableMap; public fun getMap (Ljava/lang/String;)Lcom/facebook/react/bridge/ReadableNativeMap; public fun getString (Ljava/lang/String;)Ljava/lang/String; @@ -1480,6 +1488,7 @@ public abstract interface class com/facebook/react/bridge/WritableArray : com/fa public abstract fun pushBoolean (Z)V public abstract fun pushDouble (D)V public abstract fun pushInt (I)V + public abstract fun pushLong (J)V public abstract fun pushMap (Lcom/facebook/react/bridge/ReadableMap;)V public abstract fun pushNull ()V public abstract fun pushString (Ljava/lang/String;)V @@ -1492,6 +1501,7 @@ public abstract interface class com/facebook/react/bridge/WritableMap : com/face public abstract fun putBoolean (Ljava/lang/String;Z)V public abstract fun putDouble (Ljava/lang/String;D)V public abstract fun putInt (Ljava/lang/String;I)V + public abstract fun putLong (Ljava/lang/String;J)V public abstract fun putMap (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V public abstract fun putNull (Ljava/lang/String;)V public abstract fun putString (Ljava/lang/String;Ljava/lang/String;)V @@ -1503,6 +1513,7 @@ public class com/facebook/react/bridge/WritableNativeArray : com/facebook/react/ public fun pushBoolean (Z)V public fun pushDouble (D)V public fun pushInt (I)V + public fun pushLong (J)V public fun pushMap (Lcom/facebook/react/bridge/ReadableMap;)V public fun pushNull ()V public fun pushString (Ljava/lang/String;)V @@ -1516,6 +1527,7 @@ public class com/facebook/react/bridge/WritableNativeMap : com/facebook/react/br public fun putBoolean (Ljava/lang/String;Z)V public fun putDouble (Ljava/lang/String;D)V public fun putInt (Ljava/lang/String;I)V + public fun putLong (Ljava/lang/String;J)V public fun putMap (Ljava/lang/String;Lcom/facebook/react/bridge/ReadableMap;)V public fun putNull (Ljava/lang/String;)V public fun putString (Ljava/lang/String;Ljava/lang/String;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyArray.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyArray.java index f81766a4c0243d..8f63d7a2add58d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyArray.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyArray.java @@ -96,6 +96,11 @@ public int getInt(int index) { return ((Number) mBackingList.get(index)).intValue(); } + @Override + public long getLong(int index) { + return ((Number) mBackingList.get(index)).longValue(); + } + @Override public @Nullable String getString(int index) { return (String) mBackingList.get(index); @@ -129,7 +134,10 @@ public ReadableMap getMap(int index) { return ReadableType.Null; } else if (object instanceof Boolean) { return ReadableType.Boolean; - } else if (object instanceof Double || object instanceof Float || object instanceof Integer) { + } else if (object instanceof Double + || object instanceof Float + || object instanceof Integer + || object instanceof Long) { return ReadableType.Number; } else if (object instanceof String) { return ReadableType.String; @@ -156,6 +164,11 @@ public void pushInt(int value) { mBackingList.add(new Double(value)); } + @Override + public void pushLong(long value) { + mBackingList.add(value); + } + @Override public void pushString(@Nullable String value) { mBackingList.add(value); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyMap.java index ccce30a7d60e36..d54cb797fbc943 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/JavaOnlyMap.java @@ -7,6 +7,8 @@ package com.facebook.react.bridge; +import static androidx.core.util.Preconditions.checkNotNull; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.HashMap; @@ -110,6 +112,11 @@ public int getInt(@NonNull String name) { return ((Number) mBackingMap.get(name)).intValue(); } + @Override + public long getLong(@NonNull String name) { + return ((Number) checkNotNull(mBackingMap.get(name))).longValue(); + } + @Override public String getString(@NonNull String name) { return (String) mBackingMap.get(name); @@ -190,6 +197,11 @@ public void putInt(@NonNull String key, int value) { mBackingMap.put(key, new Double(value)); } + @Override + public void putLong(@NonNull String key, long value) { + mBackingMap.put(key, value); + } + @Override public void putString(@NonNull String key, @Nullable String value) { mBackingMap.put(key, value); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java index 26a88911b30cae..9a5e84aaeae848 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableArray.java @@ -26,6 +26,8 @@ public interface ReadableArray { int getInt(int index); + long getLong(int index); + @NonNull String getString(int index); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java index a3bae65f7224c4..3dcc141a8cc232 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableMap.java @@ -29,6 +29,8 @@ public interface ReadableMap { int getInt(@NonNull String name); + long getLong(@NonNull String name); + @Nullable String getString(@NonNull String name); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java index 1a117a6b46928c..2f74df2334cac6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java @@ -97,6 +97,11 @@ public int getInt(int index) { return ((Double) getLocalArray()[index]).intValue(); } + @Override + public long getLong(int index) { + return ((Long) getLocalArray()[index]).longValue(); + } + @Override public @NonNull String getString(int index) { return (String) getLocalArray()[index]; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java index 0ade85c10090f1..7e796f7cdaf7f5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java @@ -160,6 +160,11 @@ public int getInt(@NonNull String name) { return getValue(name, Double.class).intValue(); } + @Override + public long getLong(@NonNull String name) { + return getValue(name, Long.class).longValue(); + } + @Override public @Nullable String getString(@NonNull String name) { return getNullableValue(name, String.class); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableArray.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableArray.java index 8ec699c3970ed9..0b7cb17f69487c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableArray.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableArray.java @@ -20,6 +20,8 @@ public interface WritableArray extends ReadableArray { void pushInt(int value); + void pushLong(long value); + void pushString(@Nullable String value); void pushArray(@Nullable ReadableArray array); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableMap.java index 1f6ec6500970f1..a7ef7818f51bb5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableMap.java @@ -21,6 +21,8 @@ public interface WritableMap extends ReadableMap { void putInt(@NonNull String key, int value); + void putLong(@NonNull String key, long value); + void putString(@NonNull String key, @Nullable String value); void putArray(@NonNull String key, @Nullable ReadableArray value); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java index 46a2c8d9e67e34..06ad5650e11c45 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeArray.java @@ -38,6 +38,9 @@ public WritableNativeArray() { @Override public native void pushInt(int value); + @Override + public native void pushLong(long value); + @Override public native void pushString(@Nullable String value); diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java index 809cc9127f555e..228b3065de7a39 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java @@ -32,6 +32,9 @@ public class WritableNativeMap extends ReadableNativeMap implements WritableMap @Override public native void putInt(@NonNull String key, int value); + @Override + public native void putLong(@NonNull String key, long value); + @Override public native void putNull(@NonNull String key); diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyArrayTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyArrayTest.kt index 46fbb1f67668d5..33f749862dd192 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyArrayTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyArrayTest.kt @@ -15,15 +15,23 @@ class JavaOnlyArrayTest { @Test fun testGetType() { val values = - JavaOnlyArray.of(1, 2f, 3.0, "4", false, JavaOnlyArray.of(), JavaOnlyMap.of(), null) + JavaOnlyArray.of(1, 2f, 3.0, 4L, "5", false, JavaOnlyArray.of(), JavaOnlyMap.of(), null) assertThat(values.getType(0)).isEqualTo(ReadableType.Number) assertThat(values.getType(1)).isEqualTo(ReadableType.Number) assertThat(values.getType(2)).isEqualTo(ReadableType.Number) - assertThat(values.getType(3)).isEqualTo(ReadableType.String) - assertThat(values.getType(4)).isEqualTo(ReadableType.Boolean) - assertThat(values.getType(5)).isEqualTo(ReadableType.Array) - assertThat(values.getType(6)).isEqualTo(ReadableType.Map) - assertThat(values.getType(7)).isEqualTo(ReadableType.Null) + assertThat(values.getType(3)).isEqualTo(ReadableType.Number) + assertThat(values.getType(4)).isEqualTo(ReadableType.String) + assertThat(values.getType(5)).isEqualTo(ReadableType.Boolean) + assertThat(values.getType(6)).isEqualTo(ReadableType.Array) + assertThat(values.getType(7)).isEqualTo(ReadableType.Map) + assertThat(values.getType(8)).isEqualTo(ReadableType.Null) + } + + @Test + fun testLongValueNotTruncated() { + val values = JavaOnlyArray.of(1125899906842623L) + + assertThat(values.getLong(0)).isEqualTo(1125899906842623L) } } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyMapTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyMapTest.kt new file mode 100644 index 00000000000000..4596b712bbe7de --- /dev/null +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/bridge/JavaOnlyMapTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.bridge + +import org.assertj.core.api.Assertions.assertThat +import org.junit.Test + +/** Tests for [JavaOnlyMap] */ +class JavaOnlyMapTest { + @Test + fun testGetType() { + val values = + JavaOnlyMap.of( + "int", + 1, + "float", + 2f, + "double", + 3.0, + "long", + 4L, + "string", + "5", + "boolean", + false, + "array", + JavaOnlyArray.of(), + "map", + JavaOnlyMap.of(), + "null", + null) + + assertThat(values.getType("int")).isEqualTo(ReadableType.Number) + assertThat(values.getType("float")).isEqualTo(ReadableType.Number) + assertThat(values.getType("double")).isEqualTo(ReadableType.Number) + assertThat(values.getType("long")).isEqualTo(ReadableType.Number) + assertThat(values.getType("string")).isEqualTo(ReadableType.String) + assertThat(values.getType("boolean")).isEqualTo(ReadableType.Boolean) + assertThat(values.getType("array")).isEqualTo(ReadableType.Array) + assertThat(values.getType("map")).isEqualTo(ReadableType.Map) + assertThat(values.getType("null")).isEqualTo(ReadableType.Null) + } + + @Test + fun testLongValueNotTruncated() { + val values = JavaOnlyMap.of("long", 1125899906842623L) + + assertThat(values.getLong("long")).isEqualTo(1125899906842623L) + } +} From bd6550192d7eb58489c5c9b1d01af907dd0ce5b0 Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Mon, 4 Mar 2024 21:52:16 -0800 Subject: [PATCH 083/361] Changelog for 0.74.0-rc.2 (#43315) Summary: Changelog: [Internal] - Changelog for 0.74.0-rc.2 Pull Request resolved: https://github.com/facebook/react-native/pull/43315 Reviewed By: christophpurrer Differential Revision: D54511031 Pulled By: lunaleaps fbshipit-source-id: d82144b1f828462ee483ffdcbb8d1c0d1d83ee50 --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1501e9f85f6d9..1ec7976b9fe596 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,38 @@ # Changelog +## v0.74.0-rc.2 + +### Changed + +#### Android specific + +- Rename `PopupMenuAndroidNativeComponent.js` to `PopupMenuAndroidNativeComponent.android.js` ([fcabb2ad21](https://github.com/facebook/react-native/commit/fcabb2ad21b2c17f4e0d40b0637c22ba84568038) by [@cipolleschi](https://github.com/cipolleschi)) + +#### iOS specific + +- Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE ([f7644be6d4](https://github.com/facebook/react-native/commit/f7644be6d4d79b72c26f740cf5ac021dfd5fedc0) by [@cipolleschi](https://github.com/cipolleschi)) + +### Deprecated + +#### iOS specific + +- Deprecate `getSurfacePresenter` and `getModuleRegistry` for `surfacePresenter` and moduleRegistry` props. ([c3b0a8f162](https://github.com/facebook/react-native/commit/c3b0a8f1626939cf5c7b3864a5acf9d3dad26fb3) by [@cipolleschi](https://github.com/cipolleschi)) + +### Removed + +#### Android specific + +- Move PopupMenu out of React Native core ([8bced4b29d](https://github.com/facebook/react-native/commit/8bced4b29db9b41a68ef726df81449a399eff604) by [@RSNara](https://github.com/RSNara)) + +### Fixed + +- Re-enable listing Hermes debugger targets in chrome://inspect, broken in 0.74 RC ([4cfac8eea6](https://github.com/facebook/react-native/commit/4cfac8eea63129059559f0a65c038dfe95e12d7c) by [@motiz88](https://github.com/motiz88)) + +#### iOS specific + +- Properly warn about `createRootViewWithBridge` being deprecated ([a1197695fc](https://github.com/facebook/react-native/commit/a1197695fc7dd7750001dc60853fd19f162dc69e) by [@okwasniewski](https://github.com/okwasniewski)) +- Codegen correctly handles react-native.config.js. ([f5d5d9d284](https://github.com/facebook/react-native/commit/f5d5d9d284fae2bce42c9202bbfcf948e6a9ed37) by [@dmytrorykun](https://github.com/dmytrorykun)) + ## v0.74.0-rc.1 ### Added From f043c832d102701947a75f2208a2f02856180c84 Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Tue, 5 Mar 2024 03:43:32 -0800 Subject: [PATCH 084/361] chore: [Github Actions] Update actions/stale to the latest version (#43312) Summary: - Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: actions/stale@v5. For more information see: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/. - from last run: https://github.com/facebook/react-native/actions/runs/8136278191 ## Changelog: [INTERNAL] [CHANGED] - [Github Actions] Update actions/stale to the latest version Pull Request resolved: https://github.com/facebook/react-native/pull/43312 Test Plan: Run workflow once Reviewed By: cortinico Differential Revision: D54506678 Pulled By: arushikesarwani94 fbshipit-source-id: 530ed1f0ff5571ee124bc78bac11c6584a9af60c --- .github/workflows/stale-bot.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml index 168ee6fa314cae..97b6c783cde94e 100644 --- a/.github/workflows/stale-bot.yml +++ b/.github/workflows/stale-bot.yml @@ -10,7 +10,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} days-before-stale: 180 @@ -27,7 +27,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: ascending: true repo-token: ${{ secrets.GITHUB_TOKEN }} @@ -45,7 +45,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: repo-token: ${{ secrets.GITHUB_TOKEN }} any-of-labels: 'Needs: Author Feedback' @@ -63,7 +63,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@v5 + - uses: actions/stale@v9 with: ascending: true repo-token: ${{ secrets.GITHUB_TOKEN }} From f3ce7cd76ee4f1772e2623c87b21bbbcb1edbc27 Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Tue, 5 Mar 2024 04:03:30 -0800 Subject: [PATCH 085/361] feature(dev-middleware): add inspector proxy `nativeNetworkInspection` target capabilty flag (#43310) Summary: This adds the `nativeNetworkInspection` target capability flag, to enable/disable the proxy-side network inspection handling. ## Changelog: [GENERAL][ADDED] Add inspector proxy `nativeNetworkInspection` target capability flag Pull Request resolved: https://github.com/facebook/react-native/pull/43310 Test Plan: Once this lands, and is published through `react-native/dev-middleware`, we (Expo) can disable the proxy-side network inspection handling. See https://github.com/expo/expo/pull/27425/commits/1a1b601a29fbc5766628238db7259121689f6cd6 on PR expo/expo#27425 Reviewed By: christophpurrer, motiz88 Differential Revision: D54486516 Pulled By: huntie fbshipit-source-id: cc151349c816fb3866d3ec07af1a29a5f4ff9b00 --- packages/dev-middleware/src/inspector-proxy/types.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/dev-middleware/src/inspector-proxy/types.js b/packages/dev-middleware/src/inspector-proxy/types.js index f4994a812c4830..a89bfc9a914d57 100644 --- a/packages/dev-middleware/src/inspector-proxy/types.js +++ b/packages/dev-middleware/src/inspector-proxy/types.js @@ -30,6 +30,13 @@ export type TargetCapabilityFlags = $ReadOnly<{ * In the proxy, this disables source fetching emulation and host rewrites. */ nativeSourceCodeFetching?: boolean, + + /** + * The target supports native network inspection. + * + * In the proxy, this disables intercepting and storing network requests. + */ + nativeNetworkInspection?: boolean, }>; // Page information received from the device. New page is created for From 244fe286a0bb3a1874fe778fbc65ecc9f1184534 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 5 Mar 2024 04:10:44 -0800 Subject: [PATCH 086/361] Make queueMicrotask pure virtual (#43311) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43311 X-link: https://github.com/facebook/hermes/pull/1337 Changelog: [internal] We've done this in a separate diff because the changes in Hermes don't propagate immediately to the React Native repository. We need to land the changes in JSI and Hermes first (in a backwards-compatible way) and then land this in a separate commit to make the method mandatory. Reviewed By: neildhar Differential Revision: D54413830 fbshipit-source-id: 3b89fe0e6697b0019544b73daa89d932db97b63a --- packages/react-native/ReactCommon/jsi/jsi/jsi.cpp | 4 ---- packages/react-native/ReactCommon/jsi/jsi/jsi.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp index bc953a5595766c..2d1003f1f838b2 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.cpp @@ -87,10 +87,6 @@ NativeState::~NativeState() {} Runtime::~Runtime() {} -void Runtime::queueMicrotask(const jsi::Function& /*callback*/) { - throw JSINativeException("queueMicrotask is not implemented in this runtime"); -} - Instrumentation& Runtime::instrumentation() { class NoInstrumentation : public Instrumentation { std::string getRecordedGCStats() override { diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.h b/packages/react-native/ReactCommon/jsi/jsi/jsi.h index d86005e4e379e5..d77255f61a86c7 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.h @@ -214,7 +214,7 @@ class JSI_EXPORT Runtime { /// its event loop implementation. /// /// \param callback a function to be executed as a microtask. - virtual void queueMicrotask(const jsi::Function& callback); + virtual void queueMicrotask(const jsi::Function& callback) = 0; /// Drain the JavaScript VM internal Microtask (a.k.a. Job in ECMA262) queue. /// From 74595907a2b70a600522a8be3d4e3f48f0eb414c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 5 Mar 2024 04:10:44 -0800 Subject: [PATCH 087/361] Add JSI test for queueMicrotask and drainMicrotasks (#43309) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43309 Changelog: [internal] X-link: https://github.com/facebook/hermes/pull/1336 Add JSI test verifying the behavior of `queueMicrotask` and `drainMicrotasks` in the runtimes that support them. Reviewed By: neildhar Differential Revision: D54484771 fbshipit-source-id: e8c0c8e05215d59a0a8c86161452642c41bcdbd7 --- .../ReactCommon/jsi/jsi/test/testlib.cpp | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp index 8291d428b357a8..d9090bdb2aac65 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp +++ b/packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp @@ -1358,6 +1358,38 @@ TEST_P(JSITest, JSErrorTest) { JSIException); } +TEST_P(JSITest, MicrotasksTest) { + try { + rt.global().setProperty(rt, "globalValue", String::createFromAscii(rt, "")); + + auto microtask1 = + function("function microtask1() { globalValue += 'hello'; }"); + auto microtask2 = + function("function microtask2() { globalValue += ' world' }"); + + rt.queueMicrotask(microtask1); + rt.queueMicrotask(microtask2); + + EXPECT_EQ( + rt.global().getProperty(rt, "globalValue").asString(rt).utf8(rt), ""); + + rt.drainMicrotasks(); + + EXPECT_EQ( + rt.global().getProperty(rt, "globalValue").asString(rt).utf8(rt), + "hello world"); + + // Microtasks shouldn't run again + rt.drainMicrotasks(); + + EXPECT_EQ( + rt.global().getProperty(rt, "globalValue").asString(rt).utf8(rt), + "hello world"); + } catch (const JSINativeException& ex) { + // queueMicrotask() is unimplemented by some runtimes, ignore such failures. + } +} + //---------------------------------------------------------------------- // Test that multiple levels of delegation in DecoratedHostObjects works. From 3222805b4f35d2864764d9e7554aabfbd2954172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 5 Mar 2024 06:02:38 -0800 Subject: [PATCH 088/361] Simplify logic in queueMicrotask (#43324) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43324 Changelog: [internal] Reviewed By: sammy-SC Differential Revision: D54537050 fbshipit-source-id: b7400fd5f39817e6cdcd791beea192919d79b3b0 --- packages/react-native/ReactCommon/jsc/JSCRuntime.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp index f5b5e9210b232d..33f7db44d3a76c 100644 --- a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp +++ b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp @@ -446,8 +446,7 @@ jsi::Value JSCRuntime::evaluateJavaScript( } void JSCRuntime::queueMicrotask(const jsi::Function& callback) { - microtaskQueue_.emplace_back( - jsi::Value(*this, callback).asObject(*this).asFunction(*this)); + microtaskQueue_.emplace_back(callback.getFunction(*this)); } bool JSCRuntime::drainMicrotasks(int /*maxMicrotasksHint*/) { From 42cab1488c3322bb4424d609f9703ec491a9b6ca Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Tue, 5 Mar 2024 06:18:37 -0800 Subject: [PATCH 089/361] Fix E2E template install in CI jobs (#43323) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43323 This fixes a seemingly pre-existent misconfiguration within our `test_ios_template` E2E test setup in CircleCI. **Background** We call `npx react-native-community/cli init` with the `--skip-install` flag, as part of the bootstrapping logic in `scripts/e2e/init-template-e2e.js`. This is necessary because we later want to explicitly call `npm install` with a custom `--registry` for our locally mirrored packages (via Verdaccio). For some reason, we were observing unexpected differences when this was run under CircleCI: 1. Runs `yarn init` 2. Runs a `yarn add` (unknown pkg) {F1464781818} https://app.circleci.com/pipelines/github/facebook/react-native/42725/workflows/f648468b-e916-4501-887d-ad293aa6fccf/jobs/1398950 This is causing a Yarn-based install ahead of where we want — ignoring the `--skip-install` flag. *I'm still unsure on the exact LOC cause in CLI* (but most likely, it's around the Yarn v3 move). **Impact of this fix** - The above meant that, when we were bootstrapping `test_ios_template` previously, packages weren't being read from Verdaccio, but **instead from npm** — using the `"0.74.0"` versions from the *previous branch cut* ❌. - After D54006327, this behaviour became breaking 💀 — since for the 0.74 -> 0.75 cut, we no longer physically published `"0.75.0-main"` (new format) packages to npm. **This change** I'm passing `--pm npm` to `npx react-native-community/cli init` to skip around any Yarn behaviour. This appears to have removed the erroneous `yarn` invocations ✅. Changelog: [Internal] bypass-github-export-checks Reviewed By: cortinico, cipolleschi Differential Revision: D54536848 fbshipit-source-id: 473b11924955f5787c82a6c81d4527d77b810aa5 --- scripts/e2e/init-template-e2e.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/e2e/init-template-e2e.js b/scripts/e2e/init-template-e2e.js index 5c042185a6623b..96df007a19ca23 100644 --- a/scripts/e2e/init-template-e2e.js +++ b/scripts/e2e/init-template-e2e.js @@ -121,8 +121,8 @@ async function initNewProjectFromSource( --directory ${directory} \ --template ${templatePath} \ --verbose \ - --skip-install \ - --yarn-config-options npmRegistryServer="${VERDACCIO_SERVER_URL}"`, + --pm npm \ + --skip-install`, { // Avoid loading packages/react-native/react-native.config.js cwd: REPO_ROOT, From 1df38129337168d2968f4172a10b23bb88ab4c95 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 5 Mar 2024 06:32:45 -0800 Subject: [PATCH 090/361] Document extended RuntimeTargetDelegate lifetime requirements Summary: Changelog: [Internal] NOTE: This is a documentation-only diff. Documents that the caller of `InstanceTarget::registerRuntime()` is required to keep the `RuntimeTargetDelegate&` valid longer than previously stated. Rather than merely outliving the `RuntimeTarget` object ( = past `unregisterRuntime()`), the delegate must also remain valid while any JS is being executed in the underlying runtime. Proof that this requirement is already met by the existing integrations: * In Bridgeless, `RuntimeTargetDelegate` is implemented by [`JSRuntime`](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h#L20). JS execution via the `RuntimeExecutor` happens [here](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp#L70), while a [strong reference to the `JSRuntime`](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp#L66) is in scope. * In Bridge, `RuntimeTargetDelegate` is implemented by [`JSExecutor`](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/cxxreact/JSExecutor.h#L58). JS execution via the `RuntimeExecutor` happens [here](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/cxxreact/Instance.cpp#L253), while a (necessarily valid) non-owning [pointer to the `JSExecutor`](https://github.com/facebook/react-native/blob/9f85a249fa9e18eae745f103e390b2a8542e8ee9/packages/react-native/ReactCommon/cxxreact/Instance.cpp#L247) is in scope. bypass-github-export-checks Reviewed By: huntie Differential Revision: D54493456 fbshipit-source-id: c8dc11b0696e20b5fe9f3e16bb7591be0b3b6157 --- .../jsinspector-modern/InstanceTarget.h | 13 +++++++++++++ .../jsinspector-modern/RuntimeTarget.h | 16 +++++++++------- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h index 101433c8b2779f..e9ec51b12db339 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceTarget.h @@ -70,9 +70,22 @@ class InstanceTarget : public EnableExecutorFromThis { FrontendChannel channel, SessionState& sessionState); + /** + * Registers a JS runtime with this InstanceTarget. \returns a reference to + * the created RuntimeTarget, which is owned by the \c InstanceTarget. All the + * requirements of \c RuntimeTarget::create must be met. + */ RuntimeTarget& registerRuntime( RuntimeTargetDelegate& delegate, RuntimeExecutor executor); + + /** + * Unregisters a JS runtime from this InstanceTarget. This destroys the \c + * RuntimeTarget, and it is no longer valid to use. Note that the \c + * RuntimeTargetDelegate& initially provided to \c registerRuntime may + * continue to be used as long as JavaScript execution continues in the + * runtime. + */ void unregisterRuntime(RuntimeTarget& runtime); private: diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h index 0e1160a7109f02..9960c170f03852 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h @@ -77,15 +77,15 @@ class JSINSPECTOR_EXPORT RuntimeTarget : public EnableExecutorFromThis { public: /** - * Constructs a new RuntimeTarget. The caller must call setExecutor - * immediately afterwards. * \param executionContextDescription A description of the execution context * represented by this runtime. This is used for disambiguating the * source/destination of CDP messages when there are multiple runtimes * (concurrently or over the life of a Host). * \param delegate The object that will receive events from this target. The - * caller is responsible for - * ensuring that the delegate outlives this object. + * caller is responsible for ensuring that the delegate outlives this object + * AND that it remains valid for as long as the JS runtime is executing any + * code, even if the \c RuntimeTarget itself is destroyed. The delegate SHOULD + * be the object that owns the underlying jsi::Runtime, if any. * \param jsExecutor A RuntimeExecutor that can be used to schedule work on * the JS runtime's thread. The executor's queue should be empty when * RuntimeTarget is constructed (i.e. anything scheduled during the @@ -127,9 +127,11 @@ class JSINSPECTOR_EXPORT RuntimeTarget * represented by this runtime. This is used for disambiguating the * source/destination of CDP messages when there are multiple runtimes * (concurrently or over the life of a Host). - * \param delegate The object that will receive events from this target. - * The caller is responsible for ensuring that the delegate outlives this - * object. + * \param delegate The object that will receive events from this target. The + * caller is responsible for ensuring that the delegate outlives this object + * AND that it remains valid for as long as the JS runtime is executing any + * code, even if the \c RuntimeTarget itself is destroyed. The delegate SHOULD + * be the object that owns the underlying jsi::Runtime, if any. * \param jsExecutor A RuntimeExecutor that can be used to schedule work on * the JS runtime's thread. The executor's queue should be empty when * RuntimeTarget is constructed (i.e. anything scheduled during the From cdb2ff9cfef10714534e606c065f4024ffb08d23 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Tue, 5 Mar 2024 07:11:51 -0800 Subject: [PATCH 091/361] chore: bump @react-native/core-cli-utils @ 0.75.0-main Summary: Bump the version to match RN. Changelog: [Internal] Reviewed By: huntie Differential Revision: D54538812 fbshipit-source-id: a2e8225ea02fb1e7a69b3b20436c821a857ca1e2 --- packages/core-cli-utils/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json index 64ffab0912f117..f6bc2e855bba85 100644 --- a/packages/core-cli-utils/package.json +++ b/packages/core-cli-utils/package.json @@ -1,6 +1,6 @@ { "name": "@react-native/core-cli-utils", - "version": "0.74.0", + "version": "0.75.0-main", "description": "React Native CLI library for Frameworks to build on", "main": "index.js", "license": "MIT", From 87692454774d797cd3d7f26a0c31d53a4c90cfdd Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Tue, 5 Mar 2024 07:31:22 -0800 Subject: [PATCH 092/361] Allow ReactCommon/Folly to be used in Swift libraries (DEFINES_MODULE) (#43327) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43327 ## Summary Swift Pods require the use of [modular headers](https://blog.cocoapods.org/CocoaPods-1.5.0/) to be statically linked. To interop with Objective-C modules, you need to make the Objective-C module "define a Module", that is modular header export. This is already the case for a few podspecs so they can be consumed in Swift libraries, but `ReactCommon` and `RCT-Folly` don't do this yet and therefore this breaks in a few libraries of mine, for example see this issue: https://github.com/mrousavy/react-native-vision-camera/issues/195. If I were to include `ReactCommon` or `RCT-Folly` in my Swift library's podspec, the following error arises: ``` [!] The following Swift pods cannot yet be integrated as static libraries: The Swift pod `VisionCamera` depends upon `RCT-Folly`, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set `use_modular_headers!` globally in your Podfile, or specify `:modular_headers => true` for particular dependencies. ``` So this PR fixes this issue by allowing Swift libraries to consume the `ReactCommon` and `RCT-Folly` podspecs since they now export modular headers. ## Changelog [General] [Fixed] - Expose Modular Headers for `ReactCommon` podspec [General] [Fixed] - Expose Modular Headers for `RCT-Folly` podspec Pull Request resolved: https://github.com/facebook/react-native/pull/31858 Test Plan: * Add s.dependency "ReactCommon" or RCT-Folly to a Swift pod and see what happens. (See https://github.com/mrousavy/react-native-vision-camera/pull/273) Reviewed By: dmytrorykun Differential Revision: D54539127 Pulled By: cipolleschi fbshipit-source-id: 2291cc0c8d6675521b220b02ef0c3c6a3e73be38 --- packages/react-native/ReactCommon/ReactCommon.podspec | 1 + packages/react-native/third-party-podspecs/RCT-Folly.podspec | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/react-native/ReactCommon/ReactCommon.podspec b/packages/react-native/ReactCommon/ReactCommon.podspec index 0b6f175895de6e..599e3f97a1c6c7 100644 --- a/packages/react-native/ReactCommon/ReactCommon.podspec +++ b/packages/react-native/ReactCommon/ReactCommon.podspec @@ -36,6 +36,7 @@ Pod::Spec.new do |s| s.compiler_flags = folly_compiler_flags + ' ' + boost_compiler_flags s.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/RCT-Folly\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\" \"$(PODS_ROOT)/Headers/Private/React-Core\"", "USE_HEADERMAP" => "YES", + "DEFINES_MODULE" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "GCC_WARN_PEDANTIC" => "YES" } if ENV['USE_FRAMEWORKS'] diff --git a/packages/react-native/third-party-podspecs/RCT-Folly.podspec b/packages/react-native/third-party-podspecs/RCT-Folly.podspec index eb2d9b4ed8cb85..ccc10a5b47ccef 100644 --- a/packages/react-native/third-party-podspecs/RCT-Folly.podspec +++ b/packages/react-native/third-party-podspecs/RCT-Folly.podspec @@ -81,6 +81,7 @@ Pod::Spec.new do |spec| 'folly/system/*.h', spec.libraries = "c++abi" # NOTE Apple-only: Keep c++abi here due to https://github.com/react-native-community/releases/issues/251 spec.pod_target_xcconfig = { "USE_HEADERMAP" => "NO", + "DEFINES_MODULE" => "YES", "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)\" \"$(PODS_ROOT)/boost\" \"$(PODS_ROOT)/DoubleConversion\" \"$(PODS_ROOT)/fmt/include\"", # In dynamic framework (use_frameworks!) mode, ignore the unused and undefined boost symbols when generating the library. From 1387725aabd42e02646899a36a2f76731268191c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Tue, 5 Mar 2024 07:58:47 -0800 Subject: [PATCH 093/361] fix: add compiler conditional to hover style (#43331) Summary: Commit https://github.com/facebook/react-native/commit/73664f576aaa472d5c8fb2a02e0ddd017bbb2ea4 broke two jobs in CircleCI that we run using Xcode 14.3.1 because the commit introduced some types that are available only to iOS 17. The code was wrapped around if(available()) statement, but this does not compile out the code. It is a runtime check and the code needs to build anyway. This takes effect at compile time as well. However, unlike with #available, the method must type check and compile. The code will always be emitted into your binary: however, it will only be used when the binary is executed on platforms that meet the availability requirements. source: [forums.swift.org/t/if-vs-available-vs-if-available/40266/2](https://forums.swift.org/t/if-vs-available-vs-if-available/40266/2) This change should fix it, introducing some compile time pragmas that removes the code if we build with older versions of Xcode ## Changelog: [IOS] [ADDED] - Compiler conditionals for hover style (cursor: pointer) Pull Request resolved: https://github.com/facebook/react-native/pull/43331 Test Plan: CI Green Reviewed By: dmytrorykun Differential Revision: D54540520 Pulled By: cipolleschi fbshipit-source-id: 943ac479062e11969efa7645ec0ead26c6866374 --- .../Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm | 2 ++ packages/react-native/React/Views/RCTView.m | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 6bdfb69e171a29..8b9f511d89aa57 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -597,6 +597,7 @@ - (void)invalidateLayer layer.shadowPath = nil; } +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */ // Stage 1.5. Cursor / Hover Effects if (@available(iOS 17.0, *)) { UIHoverStyle *hoverStyle = nil; @@ -621,6 +622,7 @@ - (void)invalidateLayer } [self setHoverStyle:hoverStyle]; } +#endif // Stage 2. Border Rendering const bool useCoreAnimationBorderRendering = diff --git a/packages/react-native/React/Views/RCTView.m b/packages/react-native/React/Views/RCTView.m index 292956e268a723..3a8658100332fe 100644 --- a/packages/react-native/React/Views/RCTView.m +++ b/packages/react-native/React/Views/RCTView.m @@ -896,6 +896,7 @@ static void RCTUpdateShadowPathForView(RCTView *view) static void RCTUpdateHoverStyleForView(RCTView *view) { +#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */ if (@available(iOS 17.0, *)) { UIHoverStyle *hoverStyle = nil; if ([view cursor] == RCTCursorPointer) { @@ -917,6 +918,7 @@ static void RCTUpdateHoverStyleForView(RCTView *view) } [view setHoverStyle:hoverStyle]; } +#endif } - (void)updateClippingForLayer:(CALayer *)layer From 9aeb9f2f94536155c2f1e1c815e0b5fa18a2b9f3 Mon Sep 17 00:00:00 2001 From: Riccardo Cipolleschi Date: Tue, 5 Mar 2024 09:37:26 -0800 Subject: [PATCH 094/361] Allow the app to control the Activity Indicator in Bridgeless mode (#43195) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43195 Right now, the activity indicator is automatically hidden when the view is ready to be shown in bridgeless mode. There is no way to prevent that the activity indicator is automatically removed. In OSS, we have libraries (e.g.: `react-native-bootsplash`) that will allow the app to control when and how dismiss the splashscreen, but due to the current automatic behavior on Bridgeless, they stopped working. ***Note:** In the previous implementation, they were working because instead of using the `loadingView` property, they were adding the splashscreen view on top of the existing one. However, with the lazy behavior of the bridgeless mode, this is not working anymore because the RCTMountingManager [expect not to have any subview](https://www.internalfb.com/code/fbsource/[6962fa457dbc74ab3a760cf6090d9643c6748781]/xplat/js/react-native-github/packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm?lines=176) when the first surface is mounted.* ## Changelog [iOS][Added] - Allow the activityIndicator to be controlled from JS in bridgeless mode Reviewed By: philIip Differential Revision: D54191856 fbshipit-source-id: 14738032f04adf7eaf7d200d889acd752aed0ed3 --- .../RCTSurfaceHostingView.h | 7 +++++++ .../RCTSurfaceHostingView.mm | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.h b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.h index 47096221a7df62..3de4c5898c1558 100644 --- a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.h +++ b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.h @@ -56,6 +56,13 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, nullable) RCTSurfaceHostingViewActivityIndicatorViewFactory activityIndicatorViewFactory; +/** + * When set to `YES`, the activity indicator is not automatically hidden when the Surface stage changes. + * In this scenario, users should invoke `hideActivityIndicator` to remove it. + * + * @param disabled: if `YES`, the auto-hide is disabled. Otherwise the loading view will be hidden automatically + */ +- (void)disableActivityIndicatorAutoHide:(BOOL)disabled; @end NS_ASSUME_NONNULL_END diff --git a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.mm b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.mm index 78f991eecfb091..cb4ebeba3f97f4 100644 --- a/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.mm +++ b/packages/react-native/React/Base/Surface/SurfaceHostingView/RCTSurfaceHostingView.mm @@ -24,6 +24,7 @@ @implementation RCTSurfaceHostingView { UIView *_Nullable _activityIndicatorView; UIView *_Nullable _surfaceView; RCTSurfaceStage _stage; + BOOL _autoHideDisabled; } RCT_NOT_IMPLEMENTED(-(instancetype)init) @@ -36,6 +37,7 @@ - (instancetype)initWithSurface:(id)surface if (self = [super initWithFrame:CGRectZero]) { _surface = surface; _sizeMeasureMode = sizeMeasureMode; + _autoHideDisabled = NO; _surface.delegate = self; _stage = surface.stage; @@ -124,6 +126,10 @@ - (void)setSizeMeasureMode:(RCTSurfaceSizeMeasureMode)sizeMeasureMode _sizeMeasureMode = sizeMeasureMode; [self _invalidateLayout]; } +- (void)disableActivityIndicatorAutoHide:(BOOL)disabled +{ + _autoHideDisabled = disabled; +} #pragma mark - isActivityIndicatorViewVisible @@ -162,7 +168,16 @@ - (void)setIsSurfaceViewVisible:(BOOL)visible _surfaceView = _surface.view; _surfaceView.frame = self.bounds; _surfaceView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; - [self addSubview:_surfaceView]; + if (_activityIndicatorView && _autoHideDisabled) { + // The activity indicator is still showing and the surface is set to + // prevent the auto hide. This means that the application will take care of + // hiding it when it's ready. + // Let's add the surfaceView below the activity indicator so it's ready once + // the activity indicator is hidden. + [self insertSubview:_surfaceView belowSubview:_activityIndicatorView]; + } else { + [self addSubview:_surfaceView]; + } } else { [_surfaceView removeFromSuperview]; _surfaceView = nil; @@ -204,7 +219,7 @@ - (void)_invalidateLayout - (void)_updateViews { self.isSurfaceViewVisible = RCTSurfaceStageIsRunning(_stage); - self.isActivityIndicatorViewVisible = RCTSurfaceStageIsPreparing(_stage); + self.isActivityIndicatorViewVisible = _autoHideDisabled || RCTSurfaceStageIsPreparing(_stage); } - (void)didMoveToWindow From b5117520fcee1e2ffcb52a0a1ebe30634df1545c Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Tue, 5 Mar 2024 17:27:23 -0800 Subject: [PATCH 095/361] Enforce sorting of feature flag definitions (#43329) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43329 Improve maintainability of this file, in particular reducing the probability of a merge conflict for new entries. Changelog: [Internal] Reviewed By: rubennorte Differential Revision: D54539469 fbshipit-source-id: dc2fca42b4490d87c532b21043b0855d8d1a894d --- .../featureflags/ReactNativeFeatureFlags.kt | 38 ++++---- .../ReactNativeFeatureFlagsCxxAccessor.kt | 70 +++++++------- .../ReactNativeFeatureFlagsCxxInterop.kt | 16 ++-- .../ReactNativeFeatureFlagsDefaults.kt | 16 ++-- .../ReactNativeFeatureFlagsLocalAccessor.kt | 80 ++++++++-------- .../ReactNativeFeatureFlagsProvider.kt | 16 ++-- .../JReactNativeFeatureFlagsCxxInterop.cpp | 92 +++++++++--------- .../JReactNativeFeatureFlagsCxxInterop.h | 20 ++-- .../featureflags/ReactNativeFeatureFlags.cpp | 30 +++--- .../featureflags/ReactNativeFeatureFlags.h | 34 +++---- .../ReactNativeFeatureFlagsAccessor.cpp | 92 +++++++++--------- .../ReactNativeFeatureFlagsAccessor.h | 18 ++-- .../ReactNativeFeatureFlagsDefaults.h | 20 ++-- .../ReactNativeFeatureFlagsProvider.h | 10 +- .../NativeReactNativeFeatureFlags.cpp | 34 +++---- .../NativeReactNativeFeatureFlags.h | 16 ++-- .../ReactNativeFeatureFlags.config.js | 94 ++++++++++--------- .../NativeReactNativeFeatureFlags.js | 10 +- .../featureflags/ReactNativeFeatureFlags.js | 60 ++++++------ 19 files changed, 388 insertions(+), 378 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 487f43d409c9a4..dd048b337de86c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6d6fd79bdd221b3aeed0057ac756ee92>> */ /** @@ -35,46 +35,40 @@ public object ReactNativeFeatureFlags { public fun commonTestFlag(): Boolean = accessor.commonTestFlag() /** - * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). - */ - @JvmStatic - public fun enableBackgroundExecutor(): Boolean = accessor.enableBackgroundExecutor() - - /** - * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. */ @JvmStatic - public fun useModernRuntimeScheduler(): Boolean = accessor.useModernRuntimeScheduler() + public fun batchRenderingUpdatesInEventLoop(): Boolean = accessor.batchRenderingUpdatesInEventLoop() /** - * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). */ @JvmStatic - public fun enableMicrotasks(): Boolean = accessor.enableMicrotasks() + public fun enableBackgroundExecutor(): Boolean = accessor.enableBackgroundExecutor() /** - * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). */ @JvmStatic - public fun batchRenderingUpdatesInEventLoop(): Boolean = accessor.batchRenderingUpdatesInEventLoop() + public fun enableCustomDrawOrderFabric(): Boolean = accessor.enableCustomDrawOrderFabric() /** - * Uses new, deduplicated logic for constructing Android Spannables from text fragments + * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix */ @JvmStatic - public fun enableSpannableBuildingUnification(): Boolean = accessor.enableSpannableBuildingUnification() + public fun enableFixForClippedSubviewsCrash(): Boolean = accessor.enableFixForClippedSubviewsCrash() /** - * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). */ @JvmStatic - public fun enableCustomDrawOrderFabric(): Boolean = accessor.enableCustomDrawOrderFabric() + public fun enableMicrotasks(): Boolean = accessor.enableMicrotasks() /** - * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix + * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ @JvmStatic - public fun enableFixForClippedSubviewsCrash(): Boolean = accessor.enableFixForClippedSubviewsCrash() + public fun enableSpannableBuildingUnification(): Boolean = accessor.enableSpannableBuildingUnification() /** * Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes. @@ -88,6 +82,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun inspectorEnableModernCDPRegistry(): Boolean = accessor.inspectorEnableModernCDPRegistry() + /** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ + @JvmStatic + public fun useModernRuntimeScheduler(): Boolean = accessor.useModernRuntimeScheduler() + /** * Overrides the feature flags with the ones provided by the given provider * (generally one that extends `ReactNativeFeatureFlagsDefaults`). diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index 3e38e9f251cbd8..a791381d81b5ed 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<11824621ee7ca5dbdf2f09bdf1a1f983>> + * @generated SignedSource<<45776de0416f833eed9bb84d6b7d1052>> */ /** @@ -21,15 +21,15 @@ package com.facebook.react.internal.featureflags public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccessor { private var commonTestFlagCache: Boolean? = null - private var enableBackgroundExecutorCache: Boolean? = null - private var useModernRuntimeSchedulerCache: Boolean? = null - private var enableMicrotasksCache: Boolean? = null private var batchRenderingUpdatesInEventLoopCache: Boolean? = null - private var enableSpannableBuildingUnificationCache: Boolean? = null + private var enableBackgroundExecutorCache: Boolean? = null private var enableCustomDrawOrderFabricCache: Boolean? = null private var enableFixForClippedSubviewsCrashCache: Boolean? = null + private var enableMicrotasksCache: Boolean? = null + private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null + private var useModernRuntimeSchedulerCache: Boolean? = null override fun commonTestFlag(): Boolean { var cached = commonTestFlagCache @@ -40,6 +40,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun batchRenderingUpdatesInEventLoop(): Boolean { + var cached = batchRenderingUpdatesInEventLoopCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.batchRenderingUpdatesInEventLoop() + batchRenderingUpdatesInEventLoopCache = cached + } + return cached + } + override fun enableBackgroundExecutor(): Boolean { var cached = enableBackgroundExecutorCache if (cached == null) { @@ -49,29 +58,29 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } - override fun useModernRuntimeScheduler(): Boolean { - var cached = useModernRuntimeSchedulerCache + override fun enableCustomDrawOrderFabric(): Boolean { + var cached = enableCustomDrawOrderFabricCache if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.useModernRuntimeScheduler() - useModernRuntimeSchedulerCache = cached + cached = ReactNativeFeatureFlagsCxxInterop.enableCustomDrawOrderFabric() + enableCustomDrawOrderFabricCache = cached } return cached } - override fun enableMicrotasks(): Boolean { - var cached = enableMicrotasksCache + override fun enableFixForClippedSubviewsCrash(): Boolean { + var cached = enableFixForClippedSubviewsCrashCache if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.enableMicrotasks() - enableMicrotasksCache = cached + cached = ReactNativeFeatureFlagsCxxInterop.enableFixForClippedSubviewsCrash() + enableFixForClippedSubviewsCrashCache = cached } return cached } - override fun batchRenderingUpdatesInEventLoop(): Boolean { - var cached = batchRenderingUpdatesInEventLoopCache + override fun enableMicrotasks(): Boolean { + var cached = enableMicrotasksCache if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.batchRenderingUpdatesInEventLoop() - batchRenderingUpdatesInEventLoopCache = cached + cached = ReactNativeFeatureFlagsCxxInterop.enableMicrotasks() + enableMicrotasksCache = cached } return cached } @@ -85,24 +94,6 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } - override fun enableCustomDrawOrderFabric(): Boolean { - var cached = enableCustomDrawOrderFabricCache - if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.enableCustomDrawOrderFabric() - enableCustomDrawOrderFabricCache = cached - } - return cached - } - - override fun enableFixForClippedSubviewsCrash(): Boolean { - var cached = enableFixForClippedSubviewsCrashCache - if (cached == null) { - cached = ReactNativeFeatureFlagsCxxInterop.enableFixForClippedSubviewsCrash() - enableFixForClippedSubviewsCrashCache = cached - } - return cached - } - override fun inspectorEnableCxxInspectorPackagerConnection(): Boolean { var cached = inspectorEnableCxxInspectorPackagerConnectionCache if (cached == null) { @@ -121,6 +112,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun useModernRuntimeScheduler(): Boolean { + var cached = useModernRuntimeSchedulerCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.useModernRuntimeScheduler() + useModernRuntimeSchedulerCache = cached + } + return cached + } + override fun override(provider: ReactNativeFeatureFlagsProvider): Unit = ReactNativeFeatureFlagsCxxInterop.override(provider as Any) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index d3518e6cba082d..84daf0216d615d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -30,24 +30,24 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun commonTestFlag(): Boolean - @DoNotStrip @JvmStatic public external fun enableBackgroundExecutor(): Boolean - - @DoNotStrip @JvmStatic public external fun useModernRuntimeScheduler(): Boolean - - @DoNotStrip @JvmStatic public external fun enableMicrotasks(): Boolean - @DoNotStrip @JvmStatic public external fun batchRenderingUpdatesInEventLoop(): Boolean - @DoNotStrip @JvmStatic public external fun enableSpannableBuildingUnification(): Boolean + @DoNotStrip @JvmStatic public external fun enableBackgroundExecutor(): Boolean @DoNotStrip @JvmStatic public external fun enableCustomDrawOrderFabric(): Boolean @DoNotStrip @JvmStatic public external fun enableFixForClippedSubviewsCrash(): Boolean + @DoNotStrip @JvmStatic public external fun enableMicrotasks(): Boolean + + @DoNotStrip @JvmStatic public external fun enableSpannableBuildingUnification(): Boolean + @DoNotStrip @JvmStatic public external fun inspectorEnableCxxInspectorPackagerConnection(): Boolean @DoNotStrip @JvmStatic public external fun inspectorEnableModernCDPRegistry(): Boolean + @DoNotStrip @JvmStatic public external fun useModernRuntimeScheduler(): Boolean + @DoNotStrip @JvmStatic public external fun override(provider: Any) @DoNotStrip @JvmStatic public external fun dangerouslyReset() diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index e75ba65f44d08b..9c3cdc1da857fd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<4f72683fb2a832d5b77ee2cb37343526>> */ /** @@ -25,21 +25,21 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun commonTestFlag(): Boolean = false - override fun enableBackgroundExecutor(): Boolean = false - - override fun useModernRuntimeScheduler(): Boolean = false - - override fun enableMicrotasks(): Boolean = false - override fun batchRenderingUpdatesInEventLoop(): Boolean = false - override fun enableSpannableBuildingUnification(): Boolean = false + override fun enableBackgroundExecutor(): Boolean = false override fun enableCustomDrawOrderFabric(): Boolean = false override fun enableFixForClippedSubviewsCrash(): Boolean = false + override fun enableMicrotasks(): Boolean = false + + override fun enableSpannableBuildingUnification(): Boolean = false + override fun inspectorEnableCxxInspectorPackagerConnection(): Boolean = false override fun inspectorEnableModernCDPRegistry(): Boolean = false + + override fun useModernRuntimeScheduler(): Boolean = false } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 2fcc689a55e16c..8f318b3a8eaec8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<63356ad414e641eae11ca07b1a876fd3>> + * @generated SignedSource<<5fd54183222961f5557dbe0ac111a6ec>> */ /** @@ -25,15 +25,15 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private val accessedFeatureFlags = mutableSetOf() private var commonTestFlagCache: Boolean? = null - private var enableBackgroundExecutorCache: Boolean? = null - private var useModernRuntimeSchedulerCache: Boolean? = null - private var enableMicrotasksCache: Boolean? = null private var batchRenderingUpdatesInEventLoopCache: Boolean? = null - private var enableSpannableBuildingUnificationCache: Boolean? = null + private var enableBackgroundExecutorCache: Boolean? = null private var enableCustomDrawOrderFabricCache: Boolean? = null private var enableFixForClippedSubviewsCrashCache: Boolean? = null + private var enableMicrotasksCache: Boolean? = null + private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null + private var useModernRuntimeSchedulerCache: Boolean? = null override fun commonTestFlag(): Boolean { var cached = commonTestFlagCache @@ -45,36 +45,6 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } - override fun enableBackgroundExecutor(): Boolean { - var cached = enableBackgroundExecutorCache - if (cached == null) { - cached = currentProvider.enableBackgroundExecutor() - accessedFeatureFlags.add("enableBackgroundExecutor") - enableBackgroundExecutorCache = cached - } - return cached - } - - override fun useModernRuntimeScheduler(): Boolean { - var cached = useModernRuntimeSchedulerCache - if (cached == null) { - cached = currentProvider.useModernRuntimeScheduler() - accessedFeatureFlags.add("useModernRuntimeScheduler") - useModernRuntimeSchedulerCache = cached - } - return cached - } - - override fun enableMicrotasks(): Boolean { - var cached = enableMicrotasksCache - if (cached == null) { - cached = currentProvider.enableMicrotasks() - accessedFeatureFlags.add("enableMicrotasks") - enableMicrotasksCache = cached - } - return cached - } - override fun batchRenderingUpdatesInEventLoop(): Boolean { var cached = batchRenderingUpdatesInEventLoopCache if (cached == null) { @@ -85,12 +55,12 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } - override fun enableSpannableBuildingUnification(): Boolean { - var cached = enableSpannableBuildingUnificationCache + override fun enableBackgroundExecutor(): Boolean { + var cached = enableBackgroundExecutorCache if (cached == null) { - cached = currentProvider.enableSpannableBuildingUnification() - accessedFeatureFlags.add("enableSpannableBuildingUnification") - enableSpannableBuildingUnificationCache = cached + cached = currentProvider.enableBackgroundExecutor() + accessedFeatureFlags.add("enableBackgroundExecutor") + enableBackgroundExecutorCache = cached } return cached } @@ -115,6 +85,26 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableMicrotasks(): Boolean { + var cached = enableMicrotasksCache + if (cached == null) { + cached = currentProvider.enableMicrotasks() + accessedFeatureFlags.add("enableMicrotasks") + enableMicrotasksCache = cached + } + return cached + } + + override fun enableSpannableBuildingUnification(): Boolean { + var cached = enableSpannableBuildingUnificationCache + if (cached == null) { + cached = currentProvider.enableSpannableBuildingUnification() + accessedFeatureFlags.add("enableSpannableBuildingUnification") + enableSpannableBuildingUnificationCache = cached + } + return cached + } + override fun inspectorEnableCxxInspectorPackagerConnection(): Boolean { var cached = inspectorEnableCxxInspectorPackagerConnectionCache if (cached == null) { @@ -135,6 +125,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun useModernRuntimeScheduler(): Boolean { + var cached = useModernRuntimeSchedulerCache + if (cached == null) { + cached = currentProvider.useModernRuntimeScheduler() + accessedFeatureFlags.add("useModernRuntimeScheduler") + useModernRuntimeSchedulerCache = cached + } + return cached + } + override fun override(provider: ReactNativeFeatureFlagsProvider) { if (accessedFeatureFlags.isNotEmpty()) { val accessedFeatureFlagsStr = accessedFeatureFlags.joinToString(separator = ", ") { it } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 2d4561cc3e6420..30d0298638f42d 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -25,21 +25,21 @@ import com.facebook.proguard.annotations.DoNotStrip public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun commonTestFlag(): Boolean - @DoNotStrip public fun enableBackgroundExecutor(): Boolean - - @DoNotStrip public fun useModernRuntimeScheduler(): Boolean - - @DoNotStrip public fun enableMicrotasks(): Boolean - @DoNotStrip public fun batchRenderingUpdatesInEventLoop(): Boolean - @DoNotStrip public fun enableSpannableBuildingUnification(): Boolean + @DoNotStrip public fun enableBackgroundExecutor(): Boolean @DoNotStrip public fun enableCustomDrawOrderFabric(): Boolean @DoNotStrip public fun enableFixForClippedSubviewsCrash(): Boolean + @DoNotStrip public fun enableMicrotasks(): Boolean + + @DoNotStrip public fun enableSpannableBuildingUnification(): Boolean + @DoNotStrip public fun inspectorEnableCxxInspectorPackagerConnection(): Boolean @DoNotStrip public fun inspectorEnableModernCDPRegistry(): Boolean + + @DoNotStrip public fun useModernRuntimeScheduler(): Boolean } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 15061428a2a2df..d8d1c6994186ff 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5b40c18d94331e9ec3fdd1a8814b1292>> */ /** @@ -45,45 +45,39 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } - bool enableBackgroundExecutor() override { - static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableBackgroundExecutor"); - return method(javaProvider_); - } - - bool useModernRuntimeScheduler() override { + bool batchRenderingUpdatesInEventLoop() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useModernRuntimeScheduler"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("batchRenderingUpdatesInEventLoop"); return method(javaProvider_); } - bool enableMicrotasks() override { + bool enableBackgroundExecutor() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableMicrotasks"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableBackgroundExecutor"); return method(javaProvider_); } - bool batchRenderingUpdatesInEventLoop() override { + bool enableCustomDrawOrderFabric() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("batchRenderingUpdatesInEventLoop"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableCustomDrawOrderFabric"); return method(javaProvider_); } - bool enableSpannableBuildingUnification() override { + bool enableFixForClippedSubviewsCrash() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableSpannableBuildingUnification"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFixForClippedSubviewsCrash"); return method(javaProvider_); } - bool enableCustomDrawOrderFabric() override { + bool enableMicrotasks() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableCustomDrawOrderFabric"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableMicrotasks"); return method(javaProvider_); } - bool enableFixForClippedSubviewsCrash() override { + bool enableSpannableBuildingUnification() override { static const auto method = - getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableFixForClippedSubviewsCrash"); + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableSpannableBuildingUnification"); return method(javaProvider_); } @@ -99,6 +93,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool useModernRuntimeScheduler() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useModernRuntimeScheduler"); + return method(javaProvider_); + } + private: jni::global_ref javaProvider_; }; @@ -108,24 +108,29 @@ bool JReactNativeFeatureFlagsCxxInterop::commonTestFlag( return ReactNativeFeatureFlags::commonTestFlag(); } +bool JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableBackgroundExecutor( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableBackgroundExecutor(); } -bool JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler( +bool JReactNativeFeatureFlagsCxxInterop::enableCustomDrawOrderFabric( facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::useModernRuntimeScheduler(); + return ReactNativeFeatureFlags::enableCustomDrawOrderFabric(); } -bool JReactNativeFeatureFlagsCxxInterop::enableMicrotasks( +bool JReactNativeFeatureFlagsCxxInterop::enableFixForClippedSubviewsCrash( facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::enableMicrotasks(); + return ReactNativeFeatureFlags::enableFixForClippedSubviewsCrash(); } -bool JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop( +bool JReactNativeFeatureFlagsCxxInterop::enableMicrotasks( facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); + return ReactNativeFeatureFlags::enableMicrotasks(); } bool JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification( @@ -133,16 +138,6 @@ bool JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification( return ReactNativeFeatureFlags::enableSpannableBuildingUnification(); } -bool JReactNativeFeatureFlagsCxxInterop::enableCustomDrawOrderFabric( - facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::enableCustomDrawOrderFabric(); -} - -bool JReactNativeFeatureFlagsCxxInterop::enableFixForClippedSubviewsCrash( - facebook::jni::alias_ref /*unused*/) { - return ReactNativeFeatureFlags::enableFixForClippedSubviewsCrash(); -} - bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableCxxInspectorPackagerConnection( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection(); @@ -153,6 +148,11 @@ bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry( return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); } +bool JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::useModernRuntimeScheduler(); +} + void JReactNativeFeatureFlagsCxxInterop::override( facebook::jni::alias_ref /*unused*/, jni::alias_ref provider) { @@ -173,33 +173,33 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "commonTestFlag", JReactNativeFeatureFlagsCxxInterop::commonTestFlag), - makeNativeMethod( - "enableBackgroundExecutor", - JReactNativeFeatureFlagsCxxInterop::enableBackgroundExecutor), - makeNativeMethod( - "useModernRuntimeScheduler", - JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler), - makeNativeMethod( - "enableMicrotasks", - JReactNativeFeatureFlagsCxxInterop::enableMicrotasks), makeNativeMethod( "batchRenderingUpdatesInEventLoop", JReactNativeFeatureFlagsCxxInterop::batchRenderingUpdatesInEventLoop), makeNativeMethod( - "enableSpannableBuildingUnification", - JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification), + "enableBackgroundExecutor", + JReactNativeFeatureFlagsCxxInterop::enableBackgroundExecutor), makeNativeMethod( "enableCustomDrawOrderFabric", JReactNativeFeatureFlagsCxxInterop::enableCustomDrawOrderFabric), makeNativeMethod( "enableFixForClippedSubviewsCrash", JReactNativeFeatureFlagsCxxInterop::enableFixForClippedSubviewsCrash), + makeNativeMethod( + "enableMicrotasks", + JReactNativeFeatureFlagsCxxInterop::enableMicrotasks), + makeNativeMethod( + "enableSpannableBuildingUnification", + JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification), makeNativeMethod( "inspectorEnableCxxInspectorPackagerConnection", JReactNativeFeatureFlagsCxxInterop::inspectorEnableCxxInspectorPackagerConnection), makeNativeMethod( "inspectorEnableModernCDPRegistry", JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry), + makeNativeMethod( + "useModernRuntimeScheduler", + JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler), }); } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index ff7881e09e417c..800e3eb93b9336 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<514446a9fd1351df1f7f3b307de54b56>> */ /** @@ -33,25 +33,22 @@ class JReactNativeFeatureFlagsCxxInterop static bool commonTestFlag( facebook::jni::alias_ref); - static bool enableBackgroundExecutor( - facebook::jni::alias_ref); - - static bool useModernRuntimeScheduler( + static bool batchRenderingUpdatesInEventLoop( facebook::jni::alias_ref); - static bool enableMicrotasks( + static bool enableBackgroundExecutor( facebook::jni::alias_ref); - static bool batchRenderingUpdatesInEventLoop( + static bool enableCustomDrawOrderFabric( facebook::jni::alias_ref); - static bool enableSpannableBuildingUnification( + static bool enableFixForClippedSubviewsCrash( facebook::jni::alias_ref); - static bool enableCustomDrawOrderFabric( + static bool enableMicrotasks( facebook::jni::alias_ref); - static bool enableFixForClippedSubviewsCrash( + static bool enableSpannableBuildingUnification( facebook::jni::alias_ref); static bool inspectorEnableCxxInspectorPackagerConnection( @@ -60,6 +57,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool inspectorEnableModernCDPRegistry( facebook::jni::alias_ref); + static bool useModernRuntimeScheduler( + facebook::jni::alias_ref); + static void override( facebook::jni::alias_ref, jni::alias_ref provider); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index caec5678dd7b3c..a28c548a112616 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<82f226df2b3824d03b755a042b20bec5>> + * @generated SignedSource<<59573653a5f37505d9a52ac76a9dbcff>> */ /** @@ -25,24 +25,12 @@ bool ReactNativeFeatureFlags::commonTestFlag() { return getAccessor().commonTestFlag(); } -bool ReactNativeFeatureFlags::enableBackgroundExecutor() { - return getAccessor().enableBackgroundExecutor(); -} - -bool ReactNativeFeatureFlags::useModernRuntimeScheduler() { - return getAccessor().useModernRuntimeScheduler(); -} - -bool ReactNativeFeatureFlags::enableMicrotasks() { - return getAccessor().enableMicrotasks(); -} - bool ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop() { return getAccessor().batchRenderingUpdatesInEventLoop(); } -bool ReactNativeFeatureFlags::enableSpannableBuildingUnification() { - return getAccessor().enableSpannableBuildingUnification(); +bool ReactNativeFeatureFlags::enableBackgroundExecutor() { + return getAccessor().enableBackgroundExecutor(); } bool ReactNativeFeatureFlags::enableCustomDrawOrderFabric() { @@ -53,6 +41,14 @@ bool ReactNativeFeatureFlags::enableFixForClippedSubviewsCrash() { return getAccessor().enableFixForClippedSubviewsCrash(); } +bool ReactNativeFeatureFlags::enableMicrotasks() { + return getAccessor().enableMicrotasks(); +} + +bool ReactNativeFeatureFlags::enableSpannableBuildingUnification() { + return getAccessor().enableSpannableBuildingUnification(); +} + bool ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection() { return getAccessor().inspectorEnableCxxInspectorPackagerConnection(); } @@ -61,6 +57,10 @@ bool ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry() { return getAccessor().inspectorEnableModernCDPRegistry(); } +bool ReactNativeFeatureFlags::useModernRuntimeScheduler() { + return getAccessor().useModernRuntimeScheduler(); +} + void ReactNativeFeatureFlags::override( std::unique_ptr provider) { getAccessor().override(std::move(provider)); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 8f82ea192014c9..8bab08ca93bdf0 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3bfae310dfd28040f4b80d1a1df8b7b3>> + * @generated SignedSource<<036e7f3ee4def5b955ed61c707bbc8f8>> */ /** @@ -38,41 +38,36 @@ class ReactNativeFeatureFlags { */ static bool commonTestFlag(); + /** + * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + */ + static bool batchRenderingUpdatesInEventLoop(); + /** * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). */ static bool enableBackgroundExecutor(); /** - * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). */ - static bool useModernRuntimeScheduler(); + static bool enableCustomDrawOrderFabric(); /** - * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix */ - static bool enableMicrotasks(); + static bool enableFixForClippedSubviewsCrash(); /** - * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). */ - static bool batchRenderingUpdatesInEventLoop(); + static bool enableMicrotasks(); /** * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ static bool enableSpannableBuildingUnification(); - /** - * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). - */ - static bool enableCustomDrawOrderFabric(); - - /** - * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix - */ - static bool enableFixForClippedSubviewsCrash(); - /** * Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes. */ @@ -83,6 +78,11 @@ class ReactNativeFeatureFlags { */ static bool inspectorEnableModernCDPRegistry(); + /** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ + static bool useModernRuntimeScheduler(); + /** * Overrides the feature flags with the ones provided by the given provider * (generally one that extends `ReactNativeFeatureFlagsDefaults`). diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index d46d461bfd4261..c5754efb760729 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2154292f89306f25289583537833a065>> + * @generated SignedSource<> */ /** @@ -47,8 +47,8 @@ bool ReactNativeFeatureFlagsAccessor::commonTestFlag() { return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::enableBackgroundExecutor() { - auto flagValue = enableBackgroundExecutor_.load(); +bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() { + auto flagValue = batchRenderingUpdatesInEventLoop_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -56,17 +56,17 @@ bool ReactNativeFeatureFlagsAccessor::enableBackgroundExecutor() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(1, "enableBackgroundExecutor"); + markFlagAsAccessed(1, "batchRenderingUpdatesInEventLoop"); - flagValue = currentProvider_->enableBackgroundExecutor(); - enableBackgroundExecutor_ = flagValue; + flagValue = currentProvider_->batchRenderingUpdatesInEventLoop(); + batchRenderingUpdatesInEventLoop_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { - auto flagValue = useModernRuntimeScheduler_.load(); +bool ReactNativeFeatureFlagsAccessor::enableBackgroundExecutor() { + auto flagValue = enableBackgroundExecutor_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -74,17 +74,17 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(2, "useModernRuntimeScheduler"); + markFlagAsAccessed(2, "enableBackgroundExecutor"); - flagValue = currentProvider_->useModernRuntimeScheduler(); - useModernRuntimeScheduler_ = flagValue; + flagValue = currentProvider_->enableBackgroundExecutor(); + enableBackgroundExecutor_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { - auto flagValue = enableMicrotasks_.load(); +bool ReactNativeFeatureFlagsAccessor::enableCustomDrawOrderFabric() { + auto flagValue = enableCustomDrawOrderFabric_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -92,17 +92,17 @@ bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(3, "enableMicrotasks"); + markFlagAsAccessed(3, "enableCustomDrawOrderFabric"); - flagValue = currentProvider_->enableMicrotasks(); - enableMicrotasks_ = flagValue; + flagValue = currentProvider_->enableCustomDrawOrderFabric(); + enableCustomDrawOrderFabric_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() { - auto flagValue = batchRenderingUpdatesInEventLoop_.load(); +bool ReactNativeFeatureFlagsAccessor::enableFixForClippedSubviewsCrash() { + auto flagValue = enableFixForClippedSubviewsCrash_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -110,17 +110,17 @@ bool ReactNativeFeatureFlagsAccessor::batchRenderingUpdatesInEventLoop() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(4, "batchRenderingUpdatesInEventLoop"); + markFlagAsAccessed(4, "enableFixForClippedSubviewsCrash"); - flagValue = currentProvider_->batchRenderingUpdatesInEventLoop(); - batchRenderingUpdatesInEventLoop_ = flagValue; + flagValue = currentProvider_->enableFixForClippedSubviewsCrash(); + enableFixForClippedSubviewsCrash_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::enableSpannableBuildingUnification() { - auto flagValue = enableSpannableBuildingUnification_.load(); +bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { + auto flagValue = enableMicrotasks_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -128,17 +128,17 @@ bool ReactNativeFeatureFlagsAccessor::enableSpannableBuildingUnification() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(5, "enableSpannableBuildingUnification"); + markFlagAsAccessed(5, "enableMicrotasks"); - flagValue = currentProvider_->enableSpannableBuildingUnification(); - enableSpannableBuildingUnification_ = flagValue; + flagValue = currentProvider_->enableMicrotasks(); + enableMicrotasks_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::enableCustomDrawOrderFabric() { - auto flagValue = enableCustomDrawOrderFabric_.load(); +bool ReactNativeFeatureFlagsAccessor::enableSpannableBuildingUnification() { + auto flagValue = enableSpannableBuildingUnification_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -146,17 +146,17 @@ bool ReactNativeFeatureFlagsAccessor::enableCustomDrawOrderFabric() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(6, "enableCustomDrawOrderFabric"); + markFlagAsAccessed(6, "enableSpannableBuildingUnification"); - flagValue = currentProvider_->enableCustomDrawOrderFabric(); - enableCustomDrawOrderFabric_ = flagValue; + flagValue = currentProvider_->enableSpannableBuildingUnification(); + enableSpannableBuildingUnification_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::enableFixForClippedSubviewsCrash() { - auto flagValue = enableFixForClippedSubviewsCrash_.load(); +bool ReactNativeFeatureFlagsAccessor::inspectorEnableCxxInspectorPackagerConnection() { + auto flagValue = inspectorEnableCxxInspectorPackagerConnection_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -164,17 +164,17 @@ bool ReactNativeFeatureFlagsAccessor::enableFixForClippedSubviewsCrash() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "enableFixForClippedSubviewsCrash"); + markFlagAsAccessed(7, "inspectorEnableCxxInspectorPackagerConnection"); - flagValue = currentProvider_->enableFixForClippedSubviewsCrash(); - enableFixForClippedSubviewsCrash_ = flagValue; + flagValue = currentProvider_->inspectorEnableCxxInspectorPackagerConnection(); + inspectorEnableCxxInspectorPackagerConnection_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::inspectorEnableCxxInspectorPackagerConnection() { - auto flagValue = inspectorEnableCxxInspectorPackagerConnection_.load(); +bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { + auto flagValue = inspectorEnableModernCDPRegistry_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -182,17 +182,17 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableCxxInspectorPackagerConnect // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "inspectorEnableCxxInspectorPackagerConnection"); + markFlagAsAccessed(8, "inspectorEnableModernCDPRegistry"); - flagValue = currentProvider_->inspectorEnableCxxInspectorPackagerConnection(); - inspectorEnableCxxInspectorPackagerConnection_ = flagValue; + flagValue = currentProvider_->inspectorEnableModernCDPRegistry(); + inspectorEnableModernCDPRegistry_ = flagValue; } return flagValue.value(); } -bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { - auto flagValue = inspectorEnableModernCDPRegistry_.load(); +bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { + auto flagValue = useModernRuntimeScheduler_.load(); if (!flagValue.has_value()) { // This block is not exclusive but it is not necessary. @@ -200,10 +200,10 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "inspectorEnableModernCDPRegistry"); + markFlagAsAccessed(9, "useModernRuntimeScheduler"); - flagValue = currentProvider_->inspectorEnableModernCDPRegistry(); - inspectorEnableModernCDPRegistry_ = flagValue; + flagValue = currentProvider_->useModernRuntimeScheduler(); + useModernRuntimeScheduler_ = flagValue; } return flagValue.value(); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index b177bfe53b6b33..700ff2a6d67bf8 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<95487968b66d40e1ec53936b06084931>> + * @generated SignedSource<<2fa6a12c1d9b10483d8e2e23125d231e>> */ /** @@ -32,15 +32,15 @@ class ReactNativeFeatureFlagsAccessor { ReactNativeFeatureFlagsAccessor(); bool commonTestFlag(); - bool enableBackgroundExecutor(); - bool useModernRuntimeScheduler(); - bool enableMicrotasks(); bool batchRenderingUpdatesInEventLoop(); - bool enableSpannableBuildingUnification(); + bool enableBackgroundExecutor(); bool enableCustomDrawOrderFabric(); bool enableFixForClippedSubviewsCrash(); + bool enableMicrotasks(); + bool enableSpannableBuildingUnification(); bool inspectorEnableCxxInspectorPackagerConnection(); bool inspectorEnableModernCDPRegistry(); + bool useModernRuntimeScheduler(); void override(std::unique_ptr provider); @@ -54,15 +54,15 @@ class ReactNativeFeatureFlagsAccessor { std::array, 10> accessedFeatureFlags_; std::atomic> commonTestFlag_; - std::atomic> enableBackgroundExecutor_; - std::atomic> useModernRuntimeScheduler_; - std::atomic> enableMicrotasks_; std::atomic> batchRenderingUpdatesInEventLoop_; - std::atomic> enableSpannableBuildingUnification_; + std::atomic> enableBackgroundExecutor_; std::atomic> enableCustomDrawOrderFabric_; std::atomic> enableFixForClippedSubviewsCrash_; + std::atomic> enableMicrotasks_; + std::atomic> enableSpannableBuildingUnification_; std::atomic> inspectorEnableCxxInspectorPackagerConnection_; std::atomic> inspectorEnableModernCDPRegistry_; + std::atomic> useModernRuntimeScheduler_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index ce2aadae3b63ce..32d4954b1ce726 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4832483bb3648380f2bb9312311f579c>> + * @generated SignedSource<<927bc1410a5baadf3a4005e50067c4df>> */ /** @@ -31,39 +31,39 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } - bool enableBackgroundExecutor() override { + bool batchRenderingUpdatesInEventLoop() override { return false; } - bool useModernRuntimeScheduler() override { + bool enableBackgroundExecutor() override { return false; } - bool enableMicrotasks() override { + bool enableCustomDrawOrderFabric() override { return false; } - bool batchRenderingUpdatesInEventLoop() override { + bool enableFixForClippedSubviewsCrash() override { return false; } - bool enableSpannableBuildingUnification() override { + bool enableMicrotasks() override { return false; } - bool enableCustomDrawOrderFabric() override { + bool enableSpannableBuildingUnification() override { return false; } - bool enableFixForClippedSubviewsCrash() override { + bool inspectorEnableCxxInspectorPackagerConnection() override { return false; } - bool inspectorEnableCxxInspectorPackagerConnection() override { + bool inspectorEnableModernCDPRegistry() override { return false; } - bool inspectorEnableModernCDPRegistry() override { + bool useModernRuntimeScheduler() override { return false; } }; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index f6f55b5fc15e4a..eb29ae858fe8cd 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<74b4ca674d50bda5fb18d74568024399>> */ /** @@ -26,15 +26,15 @@ class ReactNativeFeatureFlagsProvider { virtual ~ReactNativeFeatureFlagsProvider() = default; virtual bool commonTestFlag() = 0; - virtual bool enableBackgroundExecutor() = 0; - virtual bool useModernRuntimeScheduler() = 0; - virtual bool enableMicrotasks() = 0; virtual bool batchRenderingUpdatesInEventLoop() = 0; - virtual bool enableSpannableBuildingUnification() = 0; + virtual bool enableBackgroundExecutor() = 0; virtual bool enableCustomDrawOrderFabric() = 0; virtual bool enableFixForClippedSubviewsCrash() = 0; + virtual bool enableMicrotasks() = 0; + virtual bool enableSpannableBuildingUnification() = 0; virtual bool inspectorEnableCxxInspectorPackagerConnection() = 0; virtual bool inspectorEnableModernCDPRegistry() = 0; + virtual bool useModernRuntimeScheduler() = 0; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 47dc35f1f8bdf1..a12c50f8b7eab4 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<003a5e1b1e52d504e9cd29583b475041>> + * @generated SignedSource<<1a785df8b045c1340d3139bd85add42b>> */ /** @@ -42,24 +42,29 @@ bool NativeReactNativeFeatureFlags::commonTestFlag( return ReactNativeFeatureFlags::commonTestFlag(); } +bool NativeReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); +} + bool NativeReactNativeFeatureFlags::enableBackgroundExecutor( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableBackgroundExecutor(); } -bool NativeReactNativeFeatureFlags::useModernRuntimeScheduler( +bool NativeReactNativeFeatureFlags::enableCustomDrawOrderFabric( jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::useModernRuntimeScheduler(); + return ReactNativeFeatureFlags::enableCustomDrawOrderFabric(); } -bool NativeReactNativeFeatureFlags::enableMicrotasks( +bool NativeReactNativeFeatureFlags::enableFixForClippedSubviewsCrash( jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::enableMicrotasks(); + return ReactNativeFeatureFlags::enableFixForClippedSubviewsCrash(); } -bool NativeReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop( +bool NativeReactNativeFeatureFlags::enableMicrotasks( jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::batchRenderingUpdatesInEventLoop(); + return ReactNativeFeatureFlags::enableMicrotasks(); } bool NativeReactNativeFeatureFlags::enableSpannableBuildingUnification( @@ -67,16 +72,6 @@ bool NativeReactNativeFeatureFlags::enableSpannableBuildingUnification( return ReactNativeFeatureFlags::enableSpannableBuildingUnification(); } -bool NativeReactNativeFeatureFlags::enableCustomDrawOrderFabric( - jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::enableCustomDrawOrderFabric(); -} - -bool NativeReactNativeFeatureFlags::enableFixForClippedSubviewsCrash( - jsi::Runtime& /*runtime*/) { - return ReactNativeFeatureFlags::enableFixForClippedSubviewsCrash(); -} - bool NativeReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection(); @@ -87,4 +82,9 @@ bool NativeReactNativeFeatureFlags::inspectorEnableModernCDPRegistry( return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); } +bool NativeReactNativeFeatureFlags::useModernRuntimeScheduler( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::useModernRuntimeScheduler(); +} + } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 33f7fcfa68782b..840f4a959f208f 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<26be12cc19ed1a9cd2dbdab684594204>> + * @generated SignedSource<> */ /** @@ -38,23 +38,23 @@ class NativeReactNativeFeatureFlags bool commonTestFlag(jsi::Runtime& runtime); - bool enableBackgroundExecutor(jsi::Runtime& runtime); - - bool useModernRuntimeScheduler(jsi::Runtime& runtime); - - bool enableMicrotasks(jsi::Runtime& runtime); - bool batchRenderingUpdatesInEventLoop(jsi::Runtime& runtime); - bool enableSpannableBuildingUnification(jsi::Runtime& runtime); + bool enableBackgroundExecutor(jsi::Runtime& runtime); bool enableCustomDrawOrderFabric(jsi::Runtime& runtime); bool enableFixForClippedSubviewsCrash(jsi::Runtime& runtime); + bool enableMicrotasks(jsi::Runtime& runtime); + + bool enableSpannableBuildingUnification(jsi::Runtime& runtime); + bool inspectorEnableCxxInspectorPackagerConnection(jsi::Runtime& runtime); bool inspectorEnableModernCDPRegistry(jsi::Runtime& runtime); + + bool useModernRuntimeScheduler(jsi::Runtime& runtime); }; } // namespace facebook::react diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index ef91f0f6e352c5..1719eceb11d4b0 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -8,103 +8,113 @@ * @format */ +/* eslint sort-keys: 'error' */ + import type {FeatureFlagDefinitions} from './types'; -const definitions: FeatureFlagDefinitions = { +// These flags are only used in tests for the feature flags system +const testDefinitions: FeatureFlagDefinitions = { common: { - // This is only used in unit tests for the feature flags system. commonTestFlag: { - description: 'Common flag for testing. Do NOT modify.', - defaultValue: false, - }, - - enableBackgroundExecutor: { - description: - 'Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used).', - defaultValue: false, - }, - useModernRuntimeScheduler: { - description: - 'When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread.', defaultValue: false, + description: 'Common flag for testing. Do NOT modify.', }, - enableMicrotasks: { - description: - 'Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).', + }, + jsOnly: { + jsOnlyTestFlag: { defaultValue: false, + description: 'JS-only flag for testing. Do NOT modify.', }, + }, +}; + +const definitions: FeatureFlagDefinitions = { + common: { + ...testDefinitions.common, + batchRenderingUpdatesInEventLoop: { + defaultValue: false, description: 'When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop.', - defaultValue: false, }, - enableSpannableBuildingUnification: { - description: - 'Uses new, deduplicated logic for constructing Android Spannables from text fragments', + enableBackgroundExecutor: { defaultValue: false, + description: + 'Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used).', }, enableCustomDrawOrderFabric: { + defaultValue: false, description: 'When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture).', - defaultValue: false, }, enableFixForClippedSubviewsCrash: { + defaultValue: false, description: 'Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix', + }, + enableMicrotasks: { defaultValue: false, + description: + 'Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).', + }, + enableSpannableBuildingUnification: { + defaultValue: false, + description: + 'Uses new, deduplicated logic for constructing Android Spannables from text fragments', }, inspectorEnableCxxInspectorPackagerConnection: { + defaultValue: false, description: 'Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes.', - defaultValue: false, }, inspectorEnableModernCDPRegistry: { + defaultValue: false, description: 'Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes.', + }, + useModernRuntimeScheduler: { defaultValue: false, + description: + 'When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread.', }, }, jsOnly: { - // This is only used in unit tests for the feature flags system. - jsOnlyTestFlag: { - description: 'JS-only flag for testing. Do NOT modify.', - defaultValue: false, - }, + ...testDefinitions.jsOnly, - isLayoutAnimationEnabled: { - description: - 'Function used to enable / disabled Layout Animations in React Native.', - defaultValue: true, - }, animatedShouldDebounceQueueFlush: { + defaultValue: false, description: 'Enables an experimental flush-queue debouncing in Animated.js.', - defaultValue: false, }, animatedShouldUseSingleOp: { + defaultValue: false, description: 'Enables an experimental mega-operation for Animated.js that replaces many calls to native with a single call into native, to reduce JSI/JNI traffic.', - defaultValue: false, }, enableAccessToHostTreeInFabric: { + defaultValue: false, description: 'Enables access to the host tree in Fabric using DOM-compatible APIs.', - defaultValue: false, + }, + isLayoutAnimationEnabled: { + defaultValue: true, + description: + 'Function used to enable / disabled Layout Animations in React Native.', }, shouldUseAnimatedObjectForTransform: { + defaultValue: false, description: 'Enables use of AnimatedObject for animating transform values.', - defaultValue: false, - }, - shouldUseSetNativePropsInFabric: { - description: 'Enables use of setNativeProps in JS driven animations.', - defaultValue: true, }, shouldUseRemoveClippedSubviewsAsDefaultOnIOS: { + defaultValue: false, description: 'removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android', - defaultValue: false, + }, + shouldUseSetNativePropsInFabric: { + defaultValue: true, + description: 'Enables use of setNativeProps in JS driven animations.', }, }, }; diff --git a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js index 93243673eba9d2..67bfc466894e12 100644 --- a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8509d5ee87efb5aa8da7efcd2085d0a2>> + * @generated SignedSource<> * @flow strict-local */ @@ -24,15 +24,15 @@ import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModule export interface Spec extends TurboModule { +commonTestFlag?: () => boolean; - +enableBackgroundExecutor?: () => boolean; - +useModernRuntimeScheduler?: () => boolean; - +enableMicrotasks?: () => boolean; +batchRenderingUpdatesInEventLoop?: () => boolean; - +enableSpannableBuildingUnification?: () => boolean; + +enableBackgroundExecutor?: () => boolean; +enableCustomDrawOrderFabric?: () => boolean; +enableFixForClippedSubviewsCrash?: () => boolean; + +enableMicrotasks?: () => boolean; + +enableSpannableBuildingUnification?: () => boolean; +inspectorEnableCxxInspectorPackagerConnection?: () => boolean; +inspectorEnableModernCDPRegistry?: () => boolean; + +useModernRuntimeScheduler?: () => boolean; } const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get( diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 214dc80c030845..6c5ab2458d1c93 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7c83d5613c3be517efe48378e6356e79>> + * @generated SignedSource<> * @flow strict-local */ @@ -27,13 +27,13 @@ import { export type ReactNativeFeatureFlagsJsOnly = { jsOnlyTestFlag: Getter, - isLayoutAnimationEnabled: Getter, animatedShouldDebounceQueueFlush: Getter, animatedShouldUseSingleOp: Getter, enableAccessToHostTreeInFabric: Getter, + isLayoutAnimationEnabled: Getter, shouldUseAnimatedObjectForTransform: Getter, - shouldUseSetNativePropsInFabric: Getter, shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter, + shouldUseSetNativePropsInFabric: Getter, }; export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial; @@ -41,15 +41,15 @@ export type ReactNativeFeatureFlagsJsOnlyOverrides = Partial, - enableBackgroundExecutor: Getter, - useModernRuntimeScheduler: Getter, - enableMicrotasks: Getter, batchRenderingUpdatesInEventLoop: Getter, - enableSpannableBuildingUnification: Getter, + enableBackgroundExecutor: Getter, enableCustomDrawOrderFabric: Getter, enableFixForClippedSubviewsCrash: Getter, + enableMicrotasks: Getter, + enableSpannableBuildingUnification: Getter, inspectorEnableCxxInspectorPackagerConnection: Getter, inspectorEnableModernCDPRegistry: Getter, + useModernRuntimeScheduler: Getter, } /** @@ -57,11 +57,6 @@ export type ReactNativeFeatureFlags = { */ export const jsOnlyTestFlag: Getter = createJavaScriptFlagGetter('jsOnlyTestFlag', false); -/** - * Function used to enable / disabled Layout Animations in React Native. - */ -export const isLayoutAnimationEnabled: Getter = createJavaScriptFlagGetter('isLayoutAnimationEnabled', true); - /** * Enables an experimental flush-queue debouncing in Animated.js. */ @@ -78,14 +73,14 @@ export const animatedShouldUseSingleOp: Getter = createJavaScriptFlagGe export const enableAccessToHostTreeInFabric: Getter = createJavaScriptFlagGetter('enableAccessToHostTreeInFabric', false); /** - * Enables use of AnimatedObject for animating transform values. + * Function used to enable / disabled Layout Animations in React Native. */ -export const shouldUseAnimatedObjectForTransform: Getter = createJavaScriptFlagGetter('shouldUseAnimatedObjectForTransform', false); +export const isLayoutAnimationEnabled: Getter = createJavaScriptFlagGetter('isLayoutAnimationEnabled', true); /** - * Enables use of setNativeProps in JS driven animations. + * Enables use of AnimatedObject for animating transform values. */ -export const shouldUseSetNativePropsInFabric: Getter = createJavaScriptFlagGetter('shouldUseSetNativePropsInFabric', true); +export const shouldUseAnimatedObjectForTransform: Getter = createJavaScriptFlagGetter('shouldUseAnimatedObjectForTransform', false); /** * removeClippedSubviews prop will be used as the default in FlatList on iOS to match Android @@ -93,29 +88,22 @@ export const shouldUseSetNativePropsInFabric: Getter = createJavaScript export const shouldUseRemoveClippedSubviewsAsDefaultOnIOS: Getter = createJavaScriptFlagGetter('shouldUseRemoveClippedSubviewsAsDefaultOnIOS', false); /** - * Common flag for testing. Do NOT modify. - */ -export const commonTestFlag: Getter = createNativeFlagGetter('commonTestFlag', false); -/** - * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). - */ -export const enableBackgroundExecutor: Getter = createNativeFlagGetter('enableBackgroundExecutor', false); -/** - * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + * Enables use of setNativeProps in JS driven animations. */ -export const useModernRuntimeScheduler: Getter = createNativeFlagGetter('useModernRuntimeScheduler', false); +export const shouldUseSetNativePropsInFabric: Getter = createJavaScriptFlagGetter('shouldUseSetNativePropsInFabric', true); + /** - * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + * Common flag for testing. Do NOT modify. */ -export const enableMicrotasks: Getter = createNativeFlagGetter('enableMicrotasks', false); +export const commonTestFlag: Getter = createNativeFlagGetter('commonTestFlag', false); /** * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. */ export const batchRenderingUpdatesInEventLoop: Getter = createNativeFlagGetter('batchRenderingUpdatesInEventLoop', false); /** - * Uses new, deduplicated logic for constructing Android Spannables from text fragments + * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). */ -export const enableSpannableBuildingUnification: Getter = createNativeFlagGetter('enableSpannableBuildingUnification', false); +export const enableBackgroundExecutor: Getter = createNativeFlagGetter('enableBackgroundExecutor', false); /** * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). */ @@ -124,6 +112,14 @@ export const enableCustomDrawOrderFabric: Getter = createNativeFlagGett * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix */ export const enableFixForClippedSubviewsCrash: Getter = createNativeFlagGetter('enableFixForClippedSubviewsCrash', false); +/** + * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). + */ +export const enableMicrotasks: Getter = createNativeFlagGetter('enableMicrotasks', false); +/** + * Uses new, deduplicated logic for constructing Android Spannables from text fragments + */ +export const enableSpannableBuildingUnification: Getter = createNativeFlagGetter('enableSpannableBuildingUnification', false); /** * Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes. */ @@ -132,6 +128,10 @@ export const inspectorEnableCxxInspectorPackagerConnection: Getter = cr * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ export const inspectorEnableModernCDPRegistry: Getter = createNativeFlagGetter('inspectorEnableModernCDPRegistry', false); +/** + * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. + */ +export const useModernRuntimeScheduler: Getter = createNativeFlagGetter('useModernRuntimeScheduler', false); /** * Overrides the feature flags with the provided methods. From 702aa25870754a6d35a1f857d37591586ba61168 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 6 Mar 2024 02:12:50 -0800 Subject: [PATCH 096/361] JsiIntegrationTest: Assert that optionals have values before dereferencing them Summary: Changelog: [Internal] Use a gtest assertion to avoid running into an exception (which has worse diagnostics) when dereferencing an `optional` value that's expected to be non-empty. bypass-github-export-checks Reviewed By: huntie Differential Revision: D54578843 fbshipit-source-id: e0269542f80045f02876bda06cb584b6c68e50cd --- .../jsinspector-modern/tests/JsiIntegrationTest.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index 9379e2af7c3158..4c4ff8b475abc3 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -285,6 +285,7 @@ TYPED_TEST(JsiIntegrationPortableTest, AddBinding) { "id": 1, "method": "Runtime.enable" })"); + ASSERT_TRUE(executionContextInfo->has_value()); auto executionContextId = executionContextInfo->value()["params"]["context"]["id"]; @@ -334,6 +335,7 @@ TYPED_TEST(JsiIntegrationPortableTest, AddedBindingSurvivesReload) { "id": 1, "method": "Runtime.enable" })"); + ASSERT_TRUE(executionContextInfo->has_value()); auto executionContextId = executionContextInfo->value()["params"]["context"]["id"]; @@ -490,6 +492,7 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { "id": 1, "method": "Runtime.enable" })"); + ASSERT_TRUE(executionContextInfo->has_value()); auto executionContextId = executionContextInfo->value()["params"]["context"]["id"].getInt(); @@ -568,6 +571,8 @@ TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { }; //# sourceURL=breakpointTest.js )"); + ASSERT_TRUE(breakpointInfo->has_value()); + ASSERT_TRUE(scriptInfo->has_value()); EXPECT_EQ( breakpointInfo->value()["params"]["location"]["scriptId"], scriptInfo->value()["params"]["scriptId"]); From 1caa0a9ea96e3e7f9cabc70654016ffb97a3df91 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 6 Mar 2024 02:18:48 -0800 Subject: [PATCH 097/361] Refactor Hermes CDP integrations into HermesRuntimeTargetDelegate (#43326) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43326 Changelog: [Internal] Extracts the common parts of `HermesJSRuntime` (Bridgeless) and `HermesExecutor` (Bridge) that pertain to integration with the modern CDP backend into a new `HermesRuntimeTargetDelegate` class. This also makes the `HermesRuntimeAgentDelegate` class fully private. As a followup, we *might* want to change `JSRuntime` and `JSExecutor` so they don't *implement* `RuntimeTargetDelegate` but are required to expose a `RuntimeTargetDelegate& getRuntimeTargetDelegate()` method instead. That would remove some of the boilerplate required for our current "aggregation" approach. Reviewed By: huntie Differential Revision: D54537844 fbshipit-source-id: f8c51fda0dbf28add1daeb95c991a34670f6854f --- .../hermes/executor/HermesExecutorFactory.cpp | 33 ++----- .../hermes/executor/HermesExecutorFactory.h | 4 +- .../chrome/HermesRuntimeTargetDelegate.cpp | 97 +++++++++++++++++++ .../chrome/HermesRuntimeTargetDelegate.h | 58 +++++++++++ .../JsiIntegrationTestHermesEngineAdapter.cpp | 19 ++-- .../JsiIntegrationTestHermesEngineAdapter.h | 2 + .../react/runtime/hermes/HermesInstance.cpp | 32 ++---- 7 files changed, 183 insertions(+), 62 deletions(-) create mode 100644 packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp create mode 100644 packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp index 4b1414253d38c3..163e044b83515e 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include @@ -253,9 +252,10 @@ HermesExecutor::HermesExecutor( RuntimeInstaller runtimeInstaller, HermesRuntime& hermesRuntime) : JSIExecutor(runtime, delegate, timeoutInvoker, runtimeInstaller), - jsQueue_(jsQueue), runtime_(runtime), - hermesRuntime_(hermesRuntime) {} + targetDelegate_( + std::shared_ptr(runtime_, &hermesRuntime), + std::move(jsQueue)) {} std::unique_ptr HermesExecutor::createAgentDelegate( @@ -265,28 +265,11 @@ HermesExecutor::createAgentDelegate( previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& executionContextDescription) { - std::shared_ptr hermesRuntimeShared(runtime_, &hermesRuntime_); - return std::unique_ptr( - new jsinspector_modern::HermesRuntimeAgentDelegate( - frontendChannel, - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - hermesRuntimeShared, - [jsQueueWeak = std::weak_ptr(jsQueue_), - runtimeWeak = std::weak_ptr(runtime_)](auto fn) { - auto jsQueue = jsQueueWeak.lock(); - if (!jsQueue) { - return; - } - jsQueue->runOnQueue([runtimeWeak, fn]() { - auto runtime = runtimeWeak.lock(); - if (!runtime) { - return; - } - fn(*runtime); - }); - })); + return targetDelegate_.createAgentDelegate( + std::move(frontendChannel), + sessionState, + std::move(previouslyExportedState), + executionContextDescription); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h index 689a58f7f0592e..f28e982fd43638 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include #include @@ -65,9 +66,8 @@ class HermesExecutor : public JSIExecutor { private: JSIScopedTimeoutInvoker timeoutInvoker_; - std::shared_ptr jsQueue_; std::shared_ptr runtime_; - hermes::HermesRuntime& hermesRuntime_; + jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp new file mode 100644 index 00000000000000..8f1719c3399907 --- /dev/null +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "HermesRuntimeTargetDelegate.h" +#include "HermesRuntimeAgentDelegate.h" + +#include + +using namespace facebook::hermes; + +namespace facebook::react::jsinspector_modern { + +class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { + public: + Impl( + std::shared_ptr hermesRuntime, + std::shared_ptr jsMessageQueueThread) + : Impl( + hermesRuntime, + [msgQueueThreadWeak = std::weak_ptr(jsMessageQueueThread), + runtimeWeak = std::weak_ptr(hermesRuntime)](auto fn) { + auto msgQueueThread = msgQueueThreadWeak.lock(); + if (!msgQueueThread) { + return; + } + msgQueueThread->runOnQueue([runtimeWeak, fn]() { + auto runtime = runtimeWeak.lock(); + if (!runtime) { + return; + } + fn(*runtime); + }); + }) {} + + Impl( + std::shared_ptr hermesRuntime, + RuntimeExecutor runtimeExecutor) + : runtime_(std::move(hermesRuntime)), + runtimeExecutor_(std::move(runtimeExecutor)) {} + + // RuntimeTargetDelegate methods + + std::unique_ptr createAgentDelegate( + FrontendChannel frontendChannel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription) override { + return std::unique_ptr(new HermesRuntimeAgentDelegate( + frontendChannel, + sessionState, + std::move(previouslyExportedState), + executionContextDescription, + runtime_, + runtimeExecutor_)); + } + + private: + std::shared_ptr runtime_; + RuntimeExecutor runtimeExecutor_; +}; + +HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( + std::shared_ptr hermesRuntime, + std::shared_ptr jsMessageQueueThread) + : impl_(std::make_unique( + std::move(hermesRuntime), + std::move(jsMessageQueueThread))) {} + +HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( + std::shared_ptr hermesRuntime, + RuntimeExecutor runtimeExecutor) + : impl_(std::make_unique( + std::move(hermesRuntime), + std::move(runtimeExecutor))) {} + +HermesRuntimeTargetDelegate::~HermesRuntimeTargetDelegate() = default; + +std::unique_ptr +HermesRuntimeTargetDelegate::createAgentDelegate( + FrontendChannel frontendChannel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription) { + return impl_->createAgentDelegate( + frontendChannel, + sessionState, + std::move(previouslyExportedState), + executionContextDescription); +} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h new file mode 100644 index 00000000000000..3703b16917d99b --- /dev/null +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include +#include +#include + +#include + +namespace facebook::react::jsinspector_modern { + +/** + * A RuntimeTargetDelegate that enables debugging a Hermes runtime over CDP. + */ +class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { + public: + /** + * Creates a HermesRuntimeTargetDelegate for the given runtime and message + * queue thread. + */ + HermesRuntimeTargetDelegate( + std::shared_ptr hermesRuntime, + std::shared_ptr jsMessageQueueThread); + + /** + * Creates a HermesRuntimeTargetDelegate for the given runtime and executor. + */ + HermesRuntimeTargetDelegate( + std::shared_ptr hermesRuntime, + RuntimeExecutor runtimeExecutor); + + ~HermesRuntimeTargetDelegate() override; + + // RuntimeTargetDelegate methods + + std::unique_ptr createAgentDelegate( + jsinspector_modern::FrontendChannel frontendChannel, + jsinspector_modern::SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const jsinspector_modern::ExecutionContextDescription& + executionContextDescription) override; + + private: + class Impl; + + std::unique_ptr impl_; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp index 57efca34257a2e..d5ad319f5bca45 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp @@ -7,8 +7,6 @@ #include -#include - #include "JsiIntegrationTestHermesEngineAdapter.h" using facebook::hermes::makeHermesRuntime; @@ -17,7 +15,9 @@ namespace facebook::react::jsinspector_modern { JsiIntegrationTestHermesEngineAdapter::JsiIntegrationTestHermesEngineAdapter( folly::Executor& jsExecutor) - : runtime_{hermes::makeHermesRuntime()}, jsExecutor_{jsExecutor} {} + : runtime_{hermes::makeHermesRuntime()}, + jsExecutor_{jsExecutor}, + targetDelegate_(runtime_, getRuntimeExecutor()) {} std::unique_ptr JsiIntegrationTestHermesEngineAdapter::createAgentDelegate( @@ -26,14 +26,11 @@ JsiIntegrationTestHermesEngineAdapter::createAgentDelegate( std::unique_ptr previouslyExportedState, const ExecutionContextDescription& executionContextDescription) { - return std::unique_ptr( - new HermesRuntimeAgentDelegate( - frontendChannel, - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - runtime_, - getRuntimeExecutor())); + return targetDelegate_.createAgentDelegate( + std::move(frontendChannel), + sessionState, + std::move(previouslyExportedState), + executionContextDescription); } jsi::Runtime& JsiIntegrationTestHermesEngineAdapter::getRuntime() diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h index 08c35800e257d7..ad2573b0c9ab8a 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -39,6 +40,7 @@ class JsiIntegrationTestHermesEngineAdapter : public RuntimeTargetDelegate { private: std::shared_ptr runtime_; folly::Executor& jsExecutor_; + HermesRuntimeTargetDelegate targetDelegate_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index e21f5f7fb58091..ec808954eb5c88 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -7,7 +7,7 @@ #include "HermesInstance.h" -#include +#include #include #include #include @@ -98,7 +98,7 @@ class HermesJSRuntime : public JSRuntime { std::unique_ptr runtime, std::shared_ptr msgQueueThread) : runtime_(std::move(runtime)), - msgQueueThread_(std::move(msgQueueThread)) {} + targetDelegate_(runtime_, std::move(msgQueueThread)) {} jsi::Runtime& getRuntime() noexcept override { return *runtime_; @@ -111,32 +111,16 @@ class HermesJSRuntime : public JSRuntime { previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& executionContextDescription) override { - return std::unique_ptr( - new jsinspector_modern::HermesRuntimeAgentDelegate( - frontendChannel, - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - runtime_, - [msgQueueThreadWeak = std::weak_ptr(msgQueueThread_), - runtimeWeak = std::weak_ptr(runtime_)](auto fn) { - auto msgQueueThread = msgQueueThreadWeak.lock(); - if (!msgQueueThread) { - return; - } - msgQueueThread->runOnQueue([runtimeWeak, fn]() { - auto runtime = runtimeWeak.lock(); - if (!runtime) { - return; - } - fn(*runtime); - }); - })); + return targetDelegate_.createAgentDelegate( + std::move(frontendChannel), + sessionState, + std::move(previouslyExportedState), + executionContextDescription); } private: std::shared_ptr runtime_; - std::shared_ptr msgQueueThread_; + jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_; }; std::unique_ptr HermesInstance::createJSRuntime( From 396475a26d281670f302350f0300b5b7b9775a23 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 6 Mar 2024 02:18:48 -0800 Subject: [PATCH 098/361] Use RuntimeExecutor consistently throughout the modern CDP backend (#43332) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43332 Changelog: [Internal] The Hermes debugger integrations in Bridge/Bridgeless have so far used `MessageQueueThread` directly to schedule work on the JS thread, instead of the Instance-managed executor. This was always a smell, but is now actively unsafe since the modern CDP backend requires `JSExecutor` / `JSRuntime` to remain alive while work is ongoing on the JS thread. This is not guaranteed when using `MessageQueueThread` directly like we do now, but *is* guaranteed by the Instance-managed `RuntimeExecutor` (see reasoning in D54493456). We already have access to that executor in `RuntimeTarget`, so here we ensure that it's the one used by the AgentDelegate too and eliminate the direct use of `MessageQueueThread`. NOTE: It would have been, perhaps, nice to just house the executor inside `JSExecutor` / `JSRuntime` to begin with, instead of adding a parameter to `createAgentDelegate()`. This would require some broader refactoring which I'm choosing to avoid for now. Reviewed By: huntie Differential Revision: D54539429 fbshipit-source-id: 6a5ad1c56642d809f6193b230301fa268318bbce --- .../ReactCommon/cxxreact/JSExecutor.cpp | 4 +- .../ReactCommon/cxxreact/JSExecutor.h | 3 +- .../hermes/executor/HermesExecutorFactory.cpp | 15 +++--- .../hermes/executor/HermesExecutorFactory.h | 3 +- .../chrome/HermesRuntimeTargetDelegate.cpp | 53 ++++--------------- .../chrome/HermesRuntimeTargetDelegate.h | 18 ++----- .../jsinspector-modern/RuntimeTarget.cpp | 3 +- .../jsinspector-modern/RuntimeTarget.h | 3 +- .../tests/HostTargetTest.cpp | 7 +-- .../jsinspector-modern/tests/InspectorMocks.h | 8 +-- ...JsiIntegrationTestGenericEngineAdapter.cpp | 3 +- .../JsiIntegrationTestGenericEngineAdapter.h | 3 +- .../JsiIntegrationTestHermesEngineAdapter.cpp | 8 +-- .../JsiIntegrationTestHermesEngineAdapter.h | 3 +- .../react/runtime/JSRuntimeFactory.cpp | 4 +- .../react/runtime/JSRuntimeFactory.h | 3 +- .../react/runtime/hermes/HermesInstance.cpp | 18 +++---- 17 files changed, 69 insertions(+), 90 deletions(-) diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp index e68a716d772592..f188cfe93304ca 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp @@ -41,8 +41,10 @@ JSExecutor::createAgentDelegate( jsinspector_modern::SessionState& sessionState, std::unique_ptr, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) { + executionContextDescription, + RuntimeExecutor runtimeExecutor) { (void)executionContextDescription; + (void)runtimeExecutor; return std::make_unique( std::move(frontendChannel), sessionState, getDescription()); } diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h index e89f924545249a..757997aec84067 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h @@ -150,7 +150,8 @@ class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate { std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) override; + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp index 163e044b83515e..9a537f4cf01f85 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp @@ -7,8 +7,6 @@ #include "HermesExecutorFactory.h" -#include - #include #include #include @@ -154,6 +152,8 @@ class DecoratedRuntime : public jsi::WithRuntimeDecorator { debugToken_ = facebook::hermes::inspector_modern::chrome::enableDebugging( std::move(adapter), debuggerName); } +#else + (void)jsQueue; #endif // HERMES_ENABLE_DEBUGGER } @@ -253,9 +253,8 @@ HermesExecutor::HermesExecutor( HermesRuntime& hermesRuntime) : JSIExecutor(runtime, delegate, timeoutInvoker, runtimeInstaller), runtime_(runtime), - targetDelegate_( - std::shared_ptr(runtime_, &hermesRuntime), - std::move(jsQueue)) {} + targetDelegate_{ + std::shared_ptr(runtime_, &hermesRuntime)} {} std::unique_ptr HermesExecutor::createAgentDelegate( @@ -264,12 +263,14 @@ HermesExecutor::createAgentDelegate( std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) { + executionContextDescription, + RuntimeExecutor runtimeExecutor) { return targetDelegate_.createAgentDelegate( std::move(frontendChannel), sessionState, std::move(previouslyExportedState), - executionContextDescription); + executionContextDescription, + std::move(runtimeExecutor)); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h index f28e982fd43638..c0ee1b8edc0a94 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h @@ -62,7 +62,8 @@ class HermesExecutor : public JSIExecutor { std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) override; + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; private: JSIScopedTimeoutInvoker timeoutInvoker_; diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index 8f1719c3399907..810d9f35af3810 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -16,31 +16,8 @@ namespace facebook::react::jsinspector_modern { class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { public: - Impl( - std::shared_ptr hermesRuntime, - std::shared_ptr jsMessageQueueThread) - : Impl( - hermesRuntime, - [msgQueueThreadWeak = std::weak_ptr(jsMessageQueueThread), - runtimeWeak = std::weak_ptr(hermesRuntime)](auto fn) { - auto msgQueueThread = msgQueueThreadWeak.lock(); - if (!msgQueueThread) { - return; - } - msgQueueThread->runOnQueue([runtimeWeak, fn]() { - auto runtime = runtimeWeak.lock(); - if (!runtime) { - return; - } - fn(*runtime); - }); - }) {} - - Impl( - std::shared_ptr hermesRuntime, - RuntimeExecutor runtimeExecutor) - : runtime_(std::move(hermesRuntime)), - runtimeExecutor_(std::move(runtimeExecutor)) {} + explicit Impl(std::shared_ptr hermesRuntime) + : runtime_(std::move(hermesRuntime)) {} // RuntimeTargetDelegate methods @@ -49,34 +26,24 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) override { + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) override { return std::unique_ptr(new HermesRuntimeAgentDelegate( frontendChannel, sessionState, std::move(previouslyExportedState), executionContextDescription, runtime_, - runtimeExecutor_)); + std::move(runtimeExecutor))); } private: std::shared_ptr runtime_; - RuntimeExecutor runtimeExecutor_; }; HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( - std::shared_ptr hermesRuntime, - std::shared_ptr jsMessageQueueThread) - : impl_(std::make_unique( - std::move(hermesRuntime), - std::move(jsMessageQueueThread))) {} - -HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( - std::shared_ptr hermesRuntime, - RuntimeExecutor runtimeExecutor) - : impl_(std::make_unique( - std::move(hermesRuntime), - std::move(runtimeExecutor))) {} + std::shared_ptr hermesRuntime) + : impl_(std::make_unique(std::move(hermesRuntime))) {} HermesRuntimeTargetDelegate::~HermesRuntimeTargetDelegate() = default; @@ -86,12 +53,14 @@ HermesRuntimeTargetDelegate::createAgentDelegate( SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) { + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) { return impl_->createAgentDelegate( frontendChannel, sessionState, std::move(previouslyExportedState), - executionContextDescription); + executionContextDescription, + std::move(runtimeExecutor)); } } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h index 3703b16917d99b..08a4da81084c3a 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h @@ -23,19 +23,10 @@ namespace facebook::react::jsinspector_modern { class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { public: /** - * Creates a HermesRuntimeTargetDelegate for the given runtime and message - * queue thread. + * Creates a HermesRuntimeTargetDelegate for the given runtime. */ - HermesRuntimeTargetDelegate( - std::shared_ptr hermesRuntime, - std::shared_ptr jsMessageQueueThread); - - /** - * Creates a HermesRuntimeTargetDelegate for the given runtime and executor. - */ - HermesRuntimeTargetDelegate( - std::shared_ptr hermesRuntime, - RuntimeExecutor runtimeExecutor); + explicit HermesRuntimeTargetDelegate( + std::shared_ptr hermesRuntime); ~HermesRuntimeTargetDelegate() override; @@ -47,7 +38,8 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) override; + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; private: class Impl; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp index c9a8be6f597480..44397a8ae6488d 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp @@ -46,7 +46,8 @@ std::shared_ptr RuntimeTarget::createAgent( channel, sessionState, std::move(runtimeAgentState.delegateState), - executionContextDescription_)); + executionContextDescription_, + jsExecutor_)); agents_.insert(runtimeAgent); return runtimeAgent; } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h index 9960c170f03852..59091730b20086 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h @@ -49,7 +49,8 @@ class RuntimeTargetDelegate { SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) = 0; + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) = 0; }; /** diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp index 5f6fcd789cba0e..f27baef9567379 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/HostTargetTest.cpp @@ -31,12 +31,13 @@ class HostTargetTest : public Test { protected: HostTargetTest() { - EXPECT_CALL(runtimeTargetDelegate_, createAgentDelegate(_, _, _, _)) + EXPECT_CALL(runtimeTargetDelegate_, createAgentDelegate(_, _, _, _, _)) .WillRepeatedly(runtimeAgentDelegates_.lazily_make_unique< FrontendChannel, SessionState&, std::unique_ptr, - const ExecutionContextDescription&>()); + const ExecutionContextDescription&, + RuntimeExecutor>()); } void connect() { @@ -445,7 +446,7 @@ TEST_F(HostTargetProtocolTest, MessageRoutingWhileNoRuntimeAgentDelegate) { TEST_F(HostTargetProtocolTest, InstanceWithNullRuntimeAgentDelegate) { InSequence s; - EXPECT_CALL(runtimeTargetDelegate_, createAgentDelegate(_, _, _, _)) + EXPECT_CALL(runtimeTargetDelegate_, createAgentDelegate(_, _, _, _, _)) .WillRepeatedly(ReturnNull()); auto& instanceTarget = page_->registerInstance(instanceTargetDelegate_); diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h index 2cef66e97a7c3e..66f8d7bdf6a78d 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h @@ -133,7 +133,8 @@ class MockRuntimeTargetDelegate : public RuntimeTargetDelegate { SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription&), + const ExecutionContextDescription&, + RuntimeExecutor), (override)); }; @@ -143,10 +144,11 @@ class MockRuntimeAgentDelegate : public RuntimeAgentDelegate { FrontendChannel frontendChannel, SessionState& sessionState, std::unique_ptr, - const ExecutionContextDescription& executionContextDescription) + ExecutionContextDescription executionContextDescription, + const RuntimeExecutor& /*runtimeExecutor*/) : frontendChannel(std::move(frontendChannel)), sessionState(sessionState), - executionContextDescription(executionContextDescription) {} + executionContextDescription(std::move(executionContextDescription)) {} // RuntimeAgentDelegate methods MOCK_METHOD( diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp index ee842d237dcd31..b9de7fd82a674a 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp @@ -25,7 +25,8 @@ JsiIntegrationTestGenericEngineAdapter::createAgentDelegate( FrontendChannel frontendChannel, SessionState& sessionState, std::unique_ptr, - const ExecutionContextDescription&) { + const ExecutionContextDescription& /*executionContextDescription*/, + RuntimeExecutor /*runtimeExecutor*/) { return std::unique_ptr( new FallbackRuntimeAgentDelegate( frontendChannel, diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h index 665477e303b644..5a03ae654f0bab 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h @@ -30,7 +30,8 @@ class JsiIntegrationTestGenericEngineAdapter : public RuntimeTargetDelegate { SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) override; + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) override; jsi::Runtime& getRuntime() const noexcept; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp index d5ad319f5bca45..bffc056dd7ec4f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp @@ -17,7 +17,7 @@ JsiIntegrationTestHermesEngineAdapter::JsiIntegrationTestHermesEngineAdapter( folly::Executor& jsExecutor) : runtime_{hermes::makeHermesRuntime()}, jsExecutor_{jsExecutor}, - targetDelegate_(runtime_, getRuntimeExecutor()) {} + targetDelegate_{runtime_} {} std::unique_ptr JsiIntegrationTestHermesEngineAdapter::createAgentDelegate( @@ -25,12 +25,14 @@ JsiIntegrationTestHermesEngineAdapter::createAgentDelegate( SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) { + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) { return targetDelegate_.createAgentDelegate( std::move(frontendChannel), sessionState, std::move(previouslyExportedState), - executionContextDescription); + executionContextDescription, + std::move(runtimeExecutor)); } jsi::Runtime& JsiIntegrationTestHermesEngineAdapter::getRuntime() diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h index ad2573b0c9ab8a..d2291661394bcb 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h @@ -31,7 +31,8 @@ class JsiIntegrationTestHermesEngineAdapter : public RuntimeTargetDelegate { SessionState& sessionState, std::unique_ptr previouslyExportedState, - const ExecutionContextDescription& executionContextDescription) override; + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) override; jsi::Runtime& getRuntime() const noexcept; diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp index 832d21e40c7e9f..e868f1c12691d4 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp @@ -24,8 +24,10 @@ JSIRuntimeHolder::createAgentDelegate( jsinspector_modern::SessionState& sessionState, std::unique_ptr, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) { + executionContextDescription, + RuntimeExecutor runtimeExecutor) { (void)executionContextDescription; + (void)runtimeExecutor; return std::make_unique( std::move(frontendChannel), sessionState, runtime_->description()); } diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h index f7b17be856232c..34d1cace4e5ce3 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h @@ -47,7 +47,8 @@ class JSIRuntimeHolder : public JSRuntime { std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) override; + executionContextDescription, + RuntimeExecutor runtimeExecutor) override; explicit JSIRuntimeHolder(std::unique_ptr runtime); diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index ec808954eb5c88..58e8af3c62d19d 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -94,11 +94,8 @@ class DecoratedRuntime : public jsi::RuntimeDecorator { class HermesJSRuntime : public JSRuntime { public: - HermesJSRuntime( - std::unique_ptr runtime, - std::shared_ptr msgQueueThread) - : runtime_(std::move(runtime)), - targetDelegate_(runtime_, std::move(msgQueueThread)) {} + HermesJSRuntime(std::unique_ptr runtime) + : runtime_(std::move(runtime)), targetDelegate_{runtime_} {} jsi::Runtime& getRuntime() noexcept override { return *runtime_; @@ -110,12 +107,14 @@ class HermesJSRuntime : public JSRuntime { std::unique_ptr previouslyExportedState, const jsinspector_modern::ExecutionContextDescription& - executionContextDescription) override { + executionContextDescription, + RuntimeExecutor runtimeExecutor) override { return targetDelegate_.createAgentDelegate( std::move(frontendChannel), sessionState, std::move(previouslyExportedState), - executionContextDescription); + executionContextDescription, + std::move(runtimeExecutor)); } private: @@ -165,10 +164,11 @@ std::unique_ptr HermesInstance::createJSRuntime( std::move(hermesRuntime), msgQueueThread); return std::make_unique(std::move(decoratedRuntime)); } +#else + (void)msgQueueThread; #endif - return std::make_unique( - std::move(hermesRuntime), std::move(msgQueueThread)); + return std::make_unique(std::move(hermesRuntime)); } } // namespace facebook::react From e4f3338069bfe70217a46239c468e4f12fa179fc Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 6 Mar 2024 02:53:17 -0800 Subject: [PATCH 099/361] Remove deprecated Pressability methods (#43328) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43328 These have been deprecated since 2019 (D18742620), probably time we remove them. Changelog: [General][Removed] Removed deprecated methods from Pressability. Reviewed By: NickGerleman Differential Revision: D54535029 fbshipit-source-id: 45f85fb002824c94363c839fee2f831c01ad4dbd --- .../Libraries/Pressability/Pressability.js | 54 ++----------------- .../__tests__/Pressability-test.js | 40 +++----------- packages/react-native/Libraries/Text/Text.js | 16 +++--- .../__snapshots__/public-api-test.js.snap | 4 -- .../Libraries/__tests__/public-api-test.js | 1 - 5 files changed, 19 insertions(+), 96 deletions(-) diff --git a/packages/react-native/Libraries/Pressability/Pressability.js b/packages/react-native/Libraries/Pressability/Pressability.js index 940249af9a8df4..1bd6853b4202e4 100644 --- a/packages/react-native/Libraries/Pressability/Pressability.js +++ b/packages/react-native/Libraries/Pressability/Pressability.js @@ -136,33 +136,6 @@ export type PressabilityConfig = $ReadOnly<{| * while this pressable is responder. */ blockNativeResponder?: ?boolean, - - /** - * Returns whether a long press gesture should cancel the press gesture. - * Defaults to true. - * - * @deprecated - */ - onLongPressShouldCancelPress_DEPRECATED?: ?() => boolean, - - /** - * If `cancelable` is set, this will be ignored. - * - * Returns whether to yield to a lock termination request (e.g. if a native - * scroll gesture attempts to steal the responder lock). - * - * @deprecated - */ - onResponderTerminationRequest_DEPRECATED?: ?() => boolean, - - /** - * If `disabled` is set, this will be ignored. - * - * Returns whether to start a press gesture. - * - * @deprecated - */ - onStartShouldSetResponder_DEPRECATED?: ?() => boolean, |}>; export type EventHandlers = $ReadOnly<{| @@ -475,13 +448,7 @@ export default class Pressability { const responderEventHandlers = { onStartShouldSetResponder: (): boolean => { const {disabled} = this._config; - if (disabled == null) { - const {onStartShouldSetResponder_DEPRECATED} = this._config; - return onStartShouldSetResponder_DEPRECATED == null - ? true - : onStartShouldSetResponder_DEPRECATED(); - } - return !disabled; + return !disabled ?? true; }, onResponderGrant: (event: PressEvent): void | boolean => { @@ -559,13 +526,7 @@ export default class Pressability { onResponderTerminationRequest: (): boolean => { const {cancelable} = this._config; - if (cancelable == null) { - const {onResponderTerminationRequest_DEPRECATED} = this._config; - return onResponderTerminationRequest_DEPRECATED == null - ? true - : onResponderTerminationRequest_DEPRECATED(); - } - return cancelable; + return cancelable ?? true; }, onClick: (event: PressEvent): void => { @@ -789,9 +750,7 @@ export default class Pressability { const {onLongPress, onPress, android_disableSound} = this._config; if (onPress != null) { const isPressCanceledByLongPress = - onLongPress != null && - prevState === 'RESPONDER_ACTIVE_LONG_PRESS_IN' && - this._shouldLongPressCancelPress(); + onLongPress != null && prevState === 'RESPONDER_ACTIVE_LONG_PRESS_IN'; if (!isPressCanceledByLongPress) { if (Platform.OS === 'android' && android_disableSound !== true) { SoundManager.playTouchSound(); @@ -925,13 +884,6 @@ export default class Pressability { } } - _shouldLongPressCancelPress(): boolean { - return ( - this._config.onLongPressShouldCancelPress_DEPRECATED == null || - this._config.onLongPressShouldCancelPress_DEPRECATED() - ); - } - _cancelHoverInDelayTimeout(): void { if (this._hoverInDelayTimeout != null) { clearTimeout(this._hoverInDelayTimeout); diff --git a/packages/react-native/Libraries/Pressability/__tests__/Pressability-test.js b/packages/react-native/Libraries/Pressability/__tests__/Pressability-test.js index 5581db9787fa5c..08d770d0f70f4d 100644 --- a/packages/react-native/Libraries/Pressability/__tests__/Pressability-test.js +++ b/packages/react-native/Libraries/Pressability/__tests__/Pressability-test.js @@ -13,13 +13,13 @@ jest.useFakeTimers({legacyFakeTimers: true}); import type {PressEvent} from '../../Types/CoreEventTypes'; +import type {PressabilityConfig} from '../Pressability'; const UIManager = require('../../ReactNative/UIManager'); const Platform = require('../../Utilities/Platform'); const HoverState = require('../HoverState'); const Pressability = require('../Pressability').default; const invariant = require('invariant'); -const nullthrows = require('nullthrows'); const isWindows = process.platform === 'win32'; const itif = (condition: boolean) => { @@ -36,9 +36,7 @@ function getMock, TReturn>( return (fn: $FlowFixMe); } -/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's - * LTI update could not be added via codemod */ -const createMockPressability = overrides => { +const createMockPressability = (overrides: ?Partial) => { const config = { cancelable: null, disabled: null, @@ -57,9 +55,6 @@ const createMockPressability = overrides => { onPress: jest.fn(), onPressIn: jest.fn(), onPressOut: jest.fn(), - onLongPressShouldCancelPress_DEPRECATED: jest.fn(), - onResponderTerminationRequest_DEPRECATED: jest.fn(() => true), - onStartShouldSetResponder_DEPRECATED: jest.fn(() => true), ...overrides, }; const touchable = new Pressability(config); @@ -514,7 +509,11 @@ describe('Pressability', () => { describe('onPress', () => { it('is called even when `measure` does not finish', () => { - const {config, handlers} = createMockPressability(); + // Disable onLongPress. Since we run all timers, we otherwise end up + // interpreting these events as a long press. + const {config, handlers} = createMockPressability({ + onLongPress: undefined, + }); handlers.onStartShouldSetResponder(); handlers.onResponderGrant(createMockPressEvent('onResponderGrant')); @@ -877,29 +876,4 @@ describe('Pressability', () => { }); }); }); - - describe('onStartShouldSetResponder', () => { - it('if omitted the responder is set by default', () => { - const {handlers} = createMockPressability({ - onStartShouldSetResponder_DEPRECATED: null, - }); - - expect(handlers.onStartShouldSetResponder()).toBe(true); - }); - - it('if supplied it is called', () => { - const {config, handlers} = createMockPressability(); - const onStartShouldSetResponder_DEPRECATED = nullthrows( - config.onStartShouldSetResponder_DEPRECATED, - ); - - // $FlowFixMe[prop-missing] - onStartShouldSetResponder_DEPRECATED.mockReturnValue(false); - expect(handlers.onStartShouldSetResponder()).toBe(false); - - // $FlowFixMe[prop-missing] - onStartShouldSetResponder_DEPRECATED.mockReturnValue(true); - expect(handlers.onStartShouldSetResponder()).toBe(true); - }); - }); }); diff --git a/packages/react-native/Libraries/Text/Text.js b/packages/react-native/Libraries/Text/Text.js index 5ccceefc346e6b..19d697c99a2776 100644 --- a/packages/react-native/Libraries/Text/Text.js +++ b/packages/react-native/Libraries/Text/Text.js @@ -118,9 +118,6 @@ const Text: React.AbstractComponent< setHighlighted(false); onPressOut?.(event); }, - onResponderTerminationRequest_DEPRECATED: - onResponderTerminationRequest, - onStartShouldSetResponder_DEPRECATED: onStartShouldSetResponder, } : null, [ @@ -131,8 +128,6 @@ const Text: React.AbstractComponent< onPress, onPressIn, onPressOut, - onResponderTerminationRequest, - onStartShouldSetResponder, suppressHighlighting, ], ); @@ -169,8 +164,13 @@ const Text: React.AbstractComponent< }, onClick: eventHandlers.onClick, onResponderTerminationRequest: - eventHandlers.onResponderTerminationRequest, - onStartShouldSetResponder: eventHandlers.onStartShouldSetResponder, + onResponderTerminationRequest != null + ? onResponderTerminationRequest + : eventHandlers.onResponderTerminationRequest, + onStartShouldSetResponder: + onStartShouldSetResponder != null + ? onStartShouldSetResponder + : eventHandlers.onStartShouldSetResponder, }, [ eventHandlers, @@ -178,6 +178,8 @@ const Text: React.AbstractComponent< onResponderMove, onResponderRelease, onResponderTerminate, + onResponderTerminationRequest, + onStartShouldSetResponder, ], ); diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index edf3153cfa18ff..4dcde7ead1a1c5 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -6192,9 +6192,6 @@ exports[`public API should not change unintentionally Libraries/Pressability/Pre onPressMove?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, blockNativeResponder?: ?boolean, - onLongPressShouldCancelPress_DEPRECATED?: ?() => boolean, - onResponderTerminationRequest_DEPRECATED?: ?() => boolean, - onStartShouldSetResponder_DEPRECATED?: ?() => boolean, |}>; export type EventHandlers = $ReadOnly<{| onBlur: (event: BlurEvent) => void, @@ -6269,7 +6266,6 @@ declare export default class Pressability { |}> ): boolean; _handleLongPress(event: PressEvent): void; - _shouldLongPressCancelPress(): boolean; _cancelHoverInDelayTimeout(): void; _cancelHoverOutDelayTimeout(): void; _cancelLongPressDelayTimeout(): void; diff --git a/packages/react-native/Libraries/__tests__/public-api-test.js b/packages/react-native/Libraries/__tests__/public-api-test.js index 2d098e84d4a796..6fcd7671d763e2 100644 --- a/packages/react-native/Libraries/__tests__/public-api-test.js +++ b/packages/react-native/Libraries/__tests__/public-api-test.js @@ -36,7 +36,6 @@ const FILES_WITH_KNOWN_ERRORS = new Set([ 'Libraries/Components/RefreshControl/RefreshControl.js', 'Libraries/Components/ScrollView/ScrollView.js', 'Libraries/Components/StatusBar/StatusBar.js', - 'Libraries/Components/TextInput/InputAccessoryView.js', 'Libraries/Components/StaticRenderer.js', 'Libraries/Components/Touchable/TouchableNativeFeedback.js', 'Libraries/Components/Touchable/TouchableWithoutFeedback.js', From fb9872d4fe07ac7028ce536200632b3543d5e8a9 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 6 Mar 2024 03:11:33 -0800 Subject: [PATCH 100/361] Fix DefaultReactNativeHost assuming lazyViewManagers are always available (#43334) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43334 cortinico flagged that bridge + fabric regressed in 0.74, likely due to D53406841. Changelog: [Android][Fixed] Fix registration of ViewManagers in new renderer when not using lazyViewManagers. Reviewed By: fkgozali Differential Revision: D54551645 fbshipit-source-id: 0783030cd0d2900a3a254ae04c9ea4e51035272a --- .../facebook/react/ReactInstanceManager.java | 5 +++++ .../react/defaults/DefaultReactNativeHost.kt | 17 +++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java index a600833e264a4a..7258ab91f4dbc1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java @@ -998,6 +998,11 @@ public Collection getViewManagerNames() { if (names != null) { uniqueNames.addAll(names); } + } else { + FLog.w( + ReactConstants.TAG, + "Package %s is not a ViewManagerOnDemandReactPackage, view managers will not be loaded", + reactPackage.getClass().getSimpleName()); } Systrace.endSection(TRACE_TAG_REACT_JAVA_BRIDGE); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt index da82f02ea68262..817e953d0de25f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactNativeHost.kt @@ -49,13 +49,18 @@ protected constructor( DefaultComponentsRegistry.register(componentFactory) val viewManagerRegistry = - ViewManagerRegistry( - object : ViewManagerResolver { - override fun getViewManager(viewManagerName: String) = - reactInstanceManager.createViewManager(viewManagerName) + if (lazyViewManagersEnabled) { + ViewManagerRegistry( + object : ViewManagerResolver { + override fun getViewManager(viewManagerName: String) = + reactInstanceManager.createViewManager(viewManagerName) - override fun getViewManagerNames() = reactInstanceManager.viewManagerNames - }) + override fun getViewManagerNames() = reactInstanceManager.viewManagerNames + }) + } else { + ViewManagerRegistry( + reactInstanceManager.getOrCreateViewManagers(reactApplicationContext)) + } FabricUIManagerProviderImpl( componentFactory, ReactNativeConfig.DEFAULT_CONFIG, viewManagerRegistry) From e1702f44c99ee38696d40f90f6c804ab5428bd0c Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 6 Mar 2024 03:21:44 -0800 Subject: [PATCH 101/361] Do not publish src/**/__tests__ folder for react-native (#43261) Summary: We should not be publishing the `__tests__` folder to the npm package. Fixes https://github.com/facebook/react-native/issues/43242 ## Changelog: [INTERNAL] [CHANGED] - Do not publish src/**/__tests__ for react-native Pull Request resolved: https://github.com/facebook/react-native/pull/43261 Test Plan: Nothing to test Reviewed By: cipolleschi Differential Revision: D54540896 Pulled By: cortinico fbshipit-source-id: 10b557a911b9b17d64c4697724825248a597feae --- packages/react-native/src/.npmignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 packages/react-native/src/.npmignore diff --git a/packages/react-native/src/.npmignore b/packages/react-native/src/.npmignore new file mode 100644 index 00000000000000..c912533dd7d2dd --- /dev/null +++ b/packages/react-native/src/.npmignore @@ -0,0 +1 @@ +__tests__ From 1c69100a2b822309c210733a33a57ebb560a1c71 Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Wed, 6 Mar 2024 03:54:46 -0800 Subject: [PATCH 102/361] Expose `rrc_text` via prefab (#43275) Summary: The `rrc_text` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166. ## Changelog: [ANDROID] [CHANGED] - Expose `rrc_text` via prefab. Pull Request resolved: https://github.com/facebook/react-native/pull/43275 Reviewed By: cipolleschi Differential Revision: D54536468 Pulled By: cortinico fbshipit-source-id: 8c4ef983467bfc46930f10bf7bd95761c2d11788 --- packages/react-native/ReactAndroid/build.gradle.kts | 7 +++++++ .../ReactAndroid/cmake-utils/ReactNative-application.cmake | 2 ++ 2 files changed, 9 insertions(+) diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 38fdca228cb72e..fdd07aa4613247 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -125,6 +125,11 @@ val preparePrefab by "react/renderer/components/view/"), Pair("../ReactCommon/react/renderer/components/view/platform/android/", ""), )), + PrefabPreprocessingEntry( + "rrc_text", + Pair( + "../ReactCommon/react/renderer/components/text/", + "react/renderer/components/text/")), PrefabPreprocessingEntry( "rrc_textinput", Pair( @@ -545,6 +550,7 @@ android { "rrc_image", "rrc_root", "rrc_view", + "rrc_text", "rrc_textinput", "rrc_legacyviewmanagerinterop", "jsi", @@ -670,6 +676,7 @@ android { create("rrc_image") { headers = File(prefabHeadersDir, "rrc_image").absolutePath } create("rrc_root") { headers = File(prefabHeadersDir, "rrc_root").absolutePath } create("rrc_view") { headers = File(prefabHeadersDir, "rrc_view").absolutePath } + create("rrc_text") { headers = File(prefabHeadersDir, "rrc_text").absolutePath } create("rrc_textinput") { headers = File(prefabHeadersDir, "rrc_textinput").absolutePath } create("rrc_legacyviewmanagerinterop") { headers = File(prefabHeadersDir, "rrc_legacyviewmanagerinterop").absolutePath diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index c27c8e58b4c2c7..0a1c9197a954e5 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -74,6 +74,7 @@ add_library(react_cxxreactpackage ALIAS ReactAndroid::react_cxxreactpackage) add_library(react_render_core ALIAS ReactAndroid::react_render_core) add_library(react_render_graphics ALIAS ReactAndroid::react_render_graphics) add_library(rrc_view ALIAS ReactAndroid::rrc_view) +add_library(rrc_text ALIAS ReactAndroid::rrc_text) add_library(rrc_textinput ALIAS ReactAndroid::rrc_textinput) add_library(jsi ALIAS ReactAndroid::jsi) add_library(glog ALIAS ReactAndroid::glog) @@ -109,6 +110,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_render_mapbuffer # prefab ready rrc_image # prefab ready rrc_view # prefab ready + rrc_text # prefab ready rrc_textinput # prefab ready rrc_legacyviewmanagerinterop # prefab ready runtimeexecutor # prefab ready From 7c953698b41af7187504fa56a9a7c943ae724cd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Wed, 6 Mar 2024 06:51:31 -0800 Subject: [PATCH 103/361] Allow importing RCTAppDelegate in Swift (#43339) Summary: This PR fixes importing RCTAppDelegate, cleans up the imports, and properly sets the background color for bridgeless mode when using `RCTRootViewFactory`. The issue with importing to Swift was that `RCTTurboModuleManager` has C++ in headers which caused Swift to error out. bypass-github-export-checks ## Changelog: [IOS] [FIXED] - Allow importing RCTAppDelegate in Swift [INTERNAL] [REMOVED] - Remove unnecessary imports in AppDelegate [INTERNAL] [FIXED] - Properly set background color for bridgeless Pull Request resolved: https://github.com/facebook/react-native/pull/43339 Test Plan: - CI Green - Check if background color is correct Reviewed By: dmytrorykun Differential Revision: D54584489 Pulled By: cipolleschi fbshipit-source-id: cb4b947ca9d0f375b1852dbf5a7d889e920562f7 --- .../AppDelegate/RCTAppDelegate+Protected.h | 4 ++++ .../Libraries/AppDelegate/RCTAppDelegate.mm | 15 +-------------- .../Libraries/AppDelegate/RCTRootViewFactory.mm | 1 + 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate+Protected.h b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate+Protected.h index e74c9c8b43207d..2321b43c4da971 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate+Protected.h +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate+Protected.h @@ -5,8 +5,12 @@ * LICENSE file in the root directory of this source tree. */ +#if defined(__cplusplus) + #import #import "RCTAppDelegate.h" @interface RCTAppDelegate () @end + +#endif diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index f4ea71c1c896b8..64b9ccceca897a 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -7,13 +7,12 @@ #import "RCTAppDelegate.h" #import -#import #import #import #import #import +#import #import -#import #import "RCTAppDelegate+Protected.h" #import "RCTAppSetupUtils.h" @@ -22,26 +21,14 @@ #else #import #endif -#import #import #import -#import -#import -#import -#import #if USE_HERMES #import #else #import #endif -#import -#import -#import -#import #import -#import -#import -#import @interface RCTAppDelegate () @end diff --git a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm index e8ebdefba1dc7e..c71ea624423433 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTRootViewFactory.mm @@ -131,6 +131,7 @@ - (UIView *)viewWithModuleName:(NSString *)moduleName initWithSurface:surface sizeMeasureMode:RCTSurfaceSizeMeasureModeWidthExact | RCTSurfaceSizeMeasureModeHeightExact]; + surfaceHostingProxyRootView.backgroundColor = [UIColor systemBackgroundColor]; return surfaceHostingProxyRootView; } From b2fba371df0edafbb3323188004fc1f6d9ab1e8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Wed, 6 Mar 2024 07:07:53 -0800 Subject: [PATCH 104/361] feat: optimize RCTKeyWindow() for iOS 15+ (#43066) Summary: This PR further optimizes RCTKeyWindow() for iOS 15+ removing the need for additional loop bypass-github-export-checks ## Changelog: [IOS] [ADDED] - optimize RCTKeyWindow() for iOS 15+ Pull Request resolved: https://github.com/facebook/react-native/pull/43066 Test Plan: Launch RNTester, check if proper keyWindow is returned for iOS 15+ Reviewed By: javache Differential Revision: D54541838 Pulled By: cipolleschi fbshipit-source-id: be79ff48f825d10c8fd71efc18629377aadc29fd --- packages/react-native/React/Base/RCTUtils.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-native/React/Base/RCTUtils.m b/packages/react-native/React/Base/RCTUtils.m index 96e59e2db10181..716b5439ad0129 100644 --- a/packages/react-native/React/Base/RCTUtils.m +++ b/packages/react-native/React/Base/RCTUtils.m @@ -569,6 +569,10 @@ BOOL RCTRunningInAppExtension(void) } UIWindowScene *windowScene = (UIWindowScene *)scene; + if (@available(iOS 15.0, *)) { + return windowScene.keyWindow; + } + for (UIWindow *window in windowScene.windows) { if (window.isKeyWindow) { return window; From 82db33036029c232cbaec7e58f2d84c873504732 Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Wed, 6 Mar 2024 07:44:01 -0800 Subject: [PATCH 105/361] Fix parseLogBoxLog test that test hermes component stacks (#43281) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43281 ## Overview This diff fixes a bug in the hermes component stack location parser, and fixes the hermes component stack tests which were not using hermes stack parsing, which is why the bug wasn't caught. The bug fix is that React component stacks may not all have stack frame locations. For example, this stack: ``` at MyComponent (/path/to/filename.js:1:2) at MyOtherComponent <-- no location at MyAppComponent (/path/to/app.js:100:20) ``` This can happen when we're unable to make a component throw (e.g. it doesn't use a hook or access props). We have plans to fix these frames, but currently they can exist. The bug was when `parseHermesStack` finds a frame without an `entry`, it would reset the `entries`. But if entries is already non-null, or if the current frame is a frame without a source, we should continue. ### Caveats The handling here fixes the behavior to go back to skipping these frames. I'm not sure what the best way to handle these cases are, since these frames do not have source location and should skip symbolication. We should follow up with handling for these frames. ## Why it wasn't caught In D18627930 we changed the hermes component stack parsing to check `global.HermesInternal`, but the tests for the hermes component stacks were still using the `stacktrace-parser`. I updated the tests to set/reset the global, which caught the bug. Changelog: [General][Fixed] - Support hermes component stacks with missing source info. Reviewed By: yungsters Differential Revision: D54423252 fbshipit-source-id: 80ded8b99eab919e60f847369dcb1f3afa72b6be --- .../Core/Devtools/parseHermesStack.js | 6 +++++ .../Data/__tests__/parseLogBoxLog-test.js | 23 ++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js b/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js index f7b6929834b388..d39a69c9637ae3 100644 --- a/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js +++ b/packages/react-native/Libraries/Core/Devtools/parseHermesStack.js @@ -72,6 +72,7 @@ const RE_FRAME = // Capturing groups: // 1. count of skipped frames const RE_SKIPPED = /^ {4}... skipping (\d+) frames$/; +const RE_COMPONENT_NO_STACK = /^ {4}at .*$/; function isInternalBytecodeSourceUrl(sourceUrl: string): boolean { // See https://github.com/facebook/hermes/blob/3332fa020cae0bab751f648db7c94e1d687eeec7/lib/VM/Runtime.cpp#L1100 @@ -132,6 +133,11 @@ module.exports = function parseHermesStack(stack: string): HermesParsedStack { entries.push(entry); continue; } + if (RE_COMPONENT_NO_STACK.test(line)) { + // Skip component stacks without source location. + // TODO: This will not be displayed, not sure how to handle it. + continue; + } // No match - we're still in the message lastMessageLine = i; entries = []; diff --git a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js index 3035f76a9082dc..e2773b28d738bd 100644 --- a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js +++ b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js @@ -993,14 +993,25 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, }); }); - describe('Handles component stack frames formatted as call stacks', () => { + describe('Handles component stack frames formatted as call stacks in Hermes', () => { + let originalHermesInternal; + beforeEach(() => { + originalHermesInternal = global.HermesInternal; + // $FlowFixMe[cannot-write] - Jest + global.HermesInternal = true; + }); + afterEach(() => { + // $FlowFixMe[cannot-write] - Jest + global.HermesInternal = originalHermesInternal; + }); + // In new versions of React, the component stack frame format changed to match call stacks. it('detects a component stack in an interpolated warning', () => { expect( parseLogBoxLog([ 'Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?%s%s', '\n\nCheck the render method of `MyComponent`.', - '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', + '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ componentStack: [ @@ -1037,7 +1048,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, it('detects a component stack in the first argument', () => { expect( parseLogBoxLog([ - 'Some kind of message\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', + 'Some kind of message\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ componentStack: [ @@ -1068,7 +1079,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, expect( parseLogBoxLog([ 'Some kind of message', - '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', + '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ componentStack: [ @@ -1101,7 +1112,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Warning: Each child in a list should have a unique "key" prop.%s%s See https://fb.me/react-warning-keys for more information.%s', '\n\nCheck the render method of `MyOtherComponent`.', '', - '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', + '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ componentStack: [ @@ -1148,7 +1159,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, originalMessage: '### Error', name: '', componentStack: - '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', + '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', stack: [ { column: 1, From 9426d249cb80cc9f296c88436e91ad59a6d94af4 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 6 Mar 2024 08:38:55 -0800 Subject: [PATCH 106/361] delete butter module (#43300) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43300 changelog: [internal] not used, let's delete Reviewed By: fkgozali Differential Revision: D54462125 fbshipit-source-id: f6cb5199e00e139c0340ad5c7b338acfb99f0d15 --- .../ReactAndroid/build.gradle.kts | 1 - .../ReactCommon/butter/CMakeLists.txt | 21 ----- .../react-native/ReactCommon/butter/butter.h | 76 ------------------- .../react-native/ReactCommon/butter/map.h | 45 ----------- 4 files changed, 143 deletions(-) delete mode 100644 packages/react-native/ReactCommon/butter/CMakeLists.txt delete mode 100644 packages/react-native/ReactCommon/butter/butter.h delete mode 100644 packages/react-native/ReactCommon/butter/map.h diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index fdd07aa4613247..9b948515926704 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -169,7 +169,6 @@ val preparePrefab by Pair(File(buildDir, "third-party-ndk/fmt/include/").absolutePath, ""), Pair(File(buildDir, "third-party-ndk/folly/").absolutePath, ""), Pair(File(buildDir, "third-party-ndk/glog/exported/").absolutePath, ""), - Pair("../ReactCommon/butter/", "butter/"), Pair("../ReactCommon/callinvoker/", ""), Pair("../ReactCommon/cxxreact/", "cxxreact/"), Pair("../ReactCommon/react/bridging/", "react/bridging/"), diff --git a/packages/react-native/ReactCommon/butter/CMakeLists.txt b/packages/react-native/ReactCommon/butter/CMakeLists.txt deleted file mode 100644 index 1bfbc89275e996..00000000000000 --- a/packages/react-native/ReactCommon/butter/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) Meta Platforms, Inc. and affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -cmake_minimum_required(VERSION 3.13) -set(CMAKE_VERBOSE_MAKEFILE on) - -add_compile_options( - -DLOG_TAG=\"Butter\" - -fexceptions - -frtti - -std=c++20 - -Wall - -Wpedantic) - -add_library(butter INTERFACE) - -target_include_directories(butter INTERFACE .) - -target_link_libraries(butter INTERFACE glog) diff --git a/packages/react-native/ReactCommon/butter/butter.h b/packages/react-native/ReactCommon/butter/butter.h deleted file mode 100644 index 1b823235c48b6b..00000000000000 --- a/packages/react-native/ReactCommon/butter/butter.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -namespace facebook { -namespace butter { - -/* - * `Butter` is a minimal collection of basic tools borrowed from other low-level - * general purpose libraries (like Folly, Abseil or Boost). The main goals of - * Butter: - * - Make the codebase more portable; - * - Make the dependency list explicit (by decoupling it as a dependency list of - * Butter); - * - Make relying on modern C++ patterns and tools in code simple and easy. - * - Make executing experiments with different dependencies easier. - * - Limit reliance on third-party libraries eventually. - * - * Target C++ Version - * ------------------ - * Currently, Butter targets c++20. - * - * The Scope - * --------- - * What should be part of Butter and what should not? Should I add some piece of - * functionality in the Butter? Here is a quick checklist. - * - * As of now, Butter is relatively permissive per the guidance below: - * - * If one of the following is true, yes, go for it: - * - If some feature is already in some future C++ standard (possibly in draft - * stage) and it's already implemented in some 3rd party library. - * - If some standardized feature of C++ is implemented in the standard not in - * the most efficient way (because the standard enforces some tricky - * constraints, like always-valid iterators, which nobody uses and should use), - * but you have a library that does it right providing exact same interface. - * - * If one of the following is true, please do *NOT* do it (at least as part of - * the library): - * - You want to use some very fancy pattern that your favorite library (but - * nothing else) provides, and You want to make this pattern very command in the - * code base. Your hope is that this pattern will conquer the world and be - * a part of the C++ standard eventually. - * - You favorite library provides some general purpose container that 10x times - * faster than the standard one, so You want to use that in the code base. That - * container does not have compatible API though (because it's a clear trade-off - * with efficiency, of course). - * - * Note that eventually Butter will restrict the API collection to reduce - * reliance on non-standard C++ builtin libraries. That way, the API footprint - * stays small and is limited to just the essential APIs. This restriction is - * currently a work in progress. - */ - -/* - * Configuration - */ - -/* - * Enables using Folly containers instead of standard ones (such as map, vector, - * small_vector, optional and etc.) - * Custom containers are only enabled in release mode. Using custom stuff - * complicates debugging process because it breaks embedded into IDE - * introspections mechanisms. - */ -#ifndef DEBUG -#define BUTTER_USE_FOLLY_CONTAINERS -#endif - -} // namespace butter -} // namespace facebook diff --git a/packages/react-native/ReactCommon/butter/map.h b/packages/react-native/ReactCommon/butter/map.h deleted file mode 100644 index a5f6c665b68dd5..00000000000000 --- a/packages/react-native/ReactCommon/butter/map.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -#ifdef BUTTER_USE_FOLLY_CONTAINERS - -#include - -#else - -#include - -#endif - -namespace facebook { -namespace butter { - -/* - * Note: In Butter, `map` aliases to `unordered_map` because everyone agrees - * that an *ordered* map is nonsense and was a huge mistake for standardization. - * If you need an *ordered* map, feel free to introduce that as - * `butter::ordered_map`. - */ - -#ifdef BUTTER_USE_FOLLY_CONTAINERS - -template -using map = folly::F14FastMap; - -#else - -template -using map = std::unordered_map; - -#endif - -} // namespace butter -} // namespace facebook From 3ed0ff34b37bb1481d0a49bac40efadfa7fde01b Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Wed, 6 Mar 2024 09:27:50 -0800 Subject: [PATCH 107/361] Add helpers for formatting JSON CDP responses (#43340) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43340 Adds convenience methods `jsonResult`, `jsonError` and `jsonNotification` for more ergonomic construction of CDP JSON responses. Note that CDP is *loosely* based on [JSON-RPC 2.0](https://www.jsonrpc.org/specification), but differs for example in the omission of `"jsonrpc": "2.0"`. Before: ``` frontendChannel_(folly::toJson(folly::dynamic::object("id", req.id)( "error", folly::dynamic::object("code", -32602)( "message", "executionContextName is mutually exclusive with executionContextId")))); ``` After: ``` frontendChannel_(cdp::jsonError( req.id, cdp::ErrorCode::InvalidParams, "executionContextName is mutually exclusive with executionContextId")); ``` Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54202854 fbshipit-source-id: 76a407ae39ff9c2ec79bcaddb6cd4d494afb7693 --- .../jsinspector-modern/CdpJson.cpp | 61 +++++++++ .../ReactCommon/jsinspector-modern/CdpJson.h | 124 ++++++++++++++++++ .../FallbackRuntimeAgentDelegate.cpp | 19 ++- .../jsinspector-modern/HostAgent.cpp | 40 +++--- .../jsinspector-modern/HostAgent.h | 1 - .../jsinspector-modern/HostTarget.cpp | 17 +-- .../jsinspector-modern/InstanceAgent.cpp | 11 +- .../jsinspector-modern/InstanceAgent.h | 2 +- .../jsinspector-modern/Parsing.cpp | 32 ----- .../ReactCommon/jsinspector-modern/Parsing.h | 69 ---------- .../jsinspector-modern/RuntimeAgent.cpp | 38 +++--- .../jsinspector-modern/RuntimeAgent.h | 3 +- .../jsinspector-modern/RuntimeAgentDelegate.h | 2 +- 13 files changed, 241 insertions(+), 178 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/CdpJson.cpp create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h delete mode 100644 packages/react-native/ReactCommon/jsinspector-modern/Parsing.cpp delete mode 100644 packages/react-native/ReactCommon/jsinspector-modern/Parsing.h diff --git a/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.cpp b/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.cpp new file mode 100644 index 00000000000000..d91d3f3678a38c --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "CdpJson.h" + +#include +#include + +namespace facebook::react::jsinspector_modern::cdp { + +PreparsedRequest preparse(std::string_view message) { + folly::dynamic parsed = folly::parseJson(message); + return PreparsedRequest{ + .id = parsed["id"].getInt(), + .method = parsed["method"].getString(), + .params = parsed.count("params") != 0u ? parsed["params"] : nullptr}; +} + +std::string PreparsedRequest::toJson() const { + folly::dynamic obj = folly::dynamic::object; + obj["id"] = id; + obj["method"] = method; + if (params != nullptr) { + obj["params"] = params; + } + return folly::toJson(obj); +} + +std::string jsonError( + std::optional id, + ErrorCode code, + std::optional message) { + auto dynamicError = folly::dynamic::object("code", static_cast(code)); + if (message) { + dynamicError("message", *message); + } + return folly::toJson( + (id ? folly::dynamic::object("id", *id) + : folly::dynamic::object( + "id", nullptr))("error", std::move(dynamicError))); +} + +std::string jsonResult(RequestId id, const folly::dynamic& result) { + return folly::toJson(folly::dynamic::object("id", id)("result", result)); +} + +std::string jsonNotification( + std::string_view method, + std::optional params) { + auto dynamicNotification = folly::dynamic::object("method", method); + if (params) { + dynamicNotification("params", *params); + } + return folly::toJson(std::move(dynamicNotification)); +} + +} // namespace facebook::react::jsinspector_modern::cdp diff --git a/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h b/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h new file mode 100644 index 00000000000000..b77e40f7ef7cfb --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/CdpJson.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include + +namespace facebook::react::jsinspector_modern::cdp { + +using RequestId = long long; + +/** + * Error codes to be used in CDP responses. + * https://www.jsonrpc.org/specification#error_object + */ +enum class ErrorCode { + ParseError = -32700, + InvalidRequest = -32600, + MethodNotFound = -32601, + InvalidParams = -32602, + InternalError = -32603 + /* -32000 to -32099: Implementation-defined server errors. */ +}; + +/** + * An incoming CDP request that has been parsed into a more usable form. + */ +struct PreparsedRequest { + public: + /** + * The ID of the request. + */ + RequestId id{}; + + /** + * The name of the method being invoked. + */ + std::string method; + + /** + * The parameters passed to the method, if any. + */ + folly::dynamic params; + + /** + * Equality operator, useful for unit tests + */ + inline bool operator==(const PreparsedRequest& rhs) const { + return id == rhs.id && method == rhs.method && params == rhs.params; + } + + std::string toJson() const; +}; + +/** + * Parse a JSON-encoded CDP request into its constituent parts. + * \throws ParseError If the input cannot be parsed. + * \throws TypeError If the input does not conform to the expected format. + */ +PreparsedRequest preparse(std::string_view message); + +/** + * A type error that may be thrown while preparsing a request, or while + * accessing dynamic params on a request. + */ +using TypeError = folly::TypeError; + +/** + * A parse error that may be thrown while preparsing a request. + */ +using ParseError = folly::json::parse_error; + +/** + * Helper functions for creating CDP (loosely JSON-RPC) messages of various + * types, returning a JSON string ready for sending over the wire. + */ + +/** + * Returns a JSON-formatted string representing an error. + * + * {"id": , "error": { "code": , "message": }} + * + * \param id Request ID. Mandatory, null only if the request omitted it or + * could not be parsed. + * \param code Integer code from cdp::ErrorCode. + * \param message Optional, brief human-readable error message. + */ +std::string jsonError( + std::optional id, + ErrorCode code, + std::optional message = std::nullopt); + +/** + * Returns a JSON-formatted string representing a successful response. + * + * {"id": , "result": } + * + * \param id The id of the request that this response corresponds to. + * \param result Result payload, defaulting to {}. + */ +std::string jsonResult( + RequestId id, + const folly::dynamic& result = folly::dynamic::object()); + +/** + * Returns a JSON-formatted string representing a unilateral notifcation. + * + * {"method": , "params": } + * + * \param method Notification (aka "event") method. + * \param params Optional payload pbject. + */ +std::string jsonNotification( + std::string_view method, + std::optional params = std::nullopt); + +} // namespace facebook::react::jsinspector_modern::cdp diff --git a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeAgentDelegate.cpp b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeAgentDelegate.cpp index 75f74e5f285302..5cab36048b67ff 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeAgentDelegate.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeAgentDelegate.cpp @@ -54,17 +54,16 @@ void FallbackRuntimeAgentDelegate::sendFallbackRuntimeWarning() { } void FallbackRuntimeAgentDelegate::sendWarningLogEntry(std::string_view text) { - frontendChannel_( - folly::toJson(folly::dynamic::object("method", "Log.entryAdded")( - "params", + frontendChannel_(cdp::jsonNotification( + "Log.entryAdded", + folly::dynamic::object( + "entry", folly::dynamic::object( - "entry", - folly::dynamic::object( - "timestamp", - duration_cast( - system_clock::now().time_since_epoch()) - .count())("source", "other")( - "level", "warning")("text", text))))); + "timestamp", + duration_cast( + system_clock::now().time_since_epoch()) + .count())("source", "other")( + "level", "warning")("text", text)))); } } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp index 9d26aa4d7bb003..2415586f099a07 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#include "CdpJson.h" + #include #include #include @@ -98,33 +100,27 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) { } if (shouldSendOKResponse) { - folly::dynamic res = folly::dynamic::object("id", req.id)( - "result", folly::dynamic::object()); - std::string json = folly::toJson(res); - frontendChannel_(json); + frontendChannel_(cdp::jsonResult(req.id)); return; } - folly::dynamic res = folly::dynamic::object("id", req.id)( - "error", - folly::dynamic::object("code", -32601)( - "message", req.method + " not implemented yet")); - std::string json = folly::toJson(res); - frontendChannel_(json); + frontendChannel_(cdp::jsonError( + req.id, + cdp::ErrorCode::MethodNotFound, + req.method + " not implemented yet")); } void HostAgent::sendInfoLogEntry(std::string_view text) { - frontendChannel_( - folly::toJson(folly::dynamic::object("method", "Log.entryAdded")( - "params", + frontendChannel_(cdp::jsonNotification( + "Log.entryAdded", + folly::dynamic::object( + "entry", folly::dynamic::object( - "entry", - folly::dynamic::object( - "timestamp", - duration_cast( - system_clock::now().time_since_epoch()) - .count())("source", "other")( - "level", "info")("text", text))))); + "timestamp", + duration_cast( + system_clock::now().time_since_epoch()) + .count())("source", "other")( + "level", "info")("text", text)))); } void HostAgent::setCurrentInstanceAgent( @@ -140,9 +136,7 @@ void HostAgent::setCurrentInstanceAgent( // Because we can only have a single instance, we can report all contexts // as cleared. - folly::dynamic contextsCleared = - folly::dynamic::object("method", "Runtime.executionContextsCleared"); - frontendChannel_(folly::toJson(contextsCleared)); + frontendChannel_(cdp::jsonNotification("Runtime.executionContextsCleared")); } if (instanceAgent_) { // TODO: Send Runtime.executionContextCreated here - at the moment we expect diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h index 6830e0b4521166..aec355bc3ce284 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.h @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp index 4817e4d575754c..2bbb8d78e74b00 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostTarget.cpp @@ -6,11 +6,11 @@ */ #include "HostTarget.h" +#include "CdpJson.h" #include "HostAgent.h" #include "InspectorInterfaces.h" #include "InspectorUtilities.h" #include "InstanceTarget.h" -#include "Parsing.h" #include "SessionState.h" #include @@ -53,14 +53,12 @@ class HostTargetSession { try { request = cdp::preparse(message); } catch (const cdp::ParseError& e) { - frontendChannel_(folly::toJson(folly::dynamic::object("id", nullptr)( - "error", - folly::dynamic::object("code", -32700)("message", e.what())))); + frontendChannel_( + cdp::jsonError(std::nullopt, cdp::ErrorCode::ParseError, e.what())); return; } catch (const cdp::TypeError& e) { - frontendChannel_(folly::toJson(folly::dynamic::object("id", nullptr)( - "error", - folly::dynamic::object("code", -32600)("message", e.what())))); + frontendChannel_(cdp::jsonError( + std::nullopt, cdp::ErrorCode::InvalidRequest, e.what())); return; } @@ -69,9 +67,8 @@ class HostTargetSession { try { hostAgent_.handleRequest(request); } catch (const cdp::TypeError& e) { - frontendChannel_(folly::toJson(folly::dynamic::object("id", request.id)( - "error", - folly::dynamic::object("code", -32600)("message", e.what())))); + frontendChannel_( + cdp::jsonError(request.id, cdp::ErrorCode::InvalidRequest, e.what())); return; } } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp index fdb57b0b4c7dcc..a68d82a479b222 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.cpp @@ -6,6 +6,7 @@ */ #include +#include "CdpJson.h" #include "RuntimeTarget.h" namespace facebook::react::jsinspector_modern { @@ -49,9 +50,8 @@ void InstanceAgent::setCurrentRuntime(RuntimeTarget* runtimeTarget) { if (previousContext.uniqueId.has_value()) { params["executionContextUniqueId"] = *previousContext.uniqueId; } - folly::dynamic contextDestroyed = folly::dynamic::object( - "method", "Runtime.executionContextDestroyed")("params", params); - frontendChannel_(folly::toJson(contextDestroyed)); + frontendChannel_( + cdp::jsonNotification("Runtime.executionContextDestroyed", params)); } maybeSendExecutionContextCreatedNotification(); } @@ -66,9 +66,8 @@ void InstanceAgent::maybeSendExecutionContextCreatedNotification() { if (newContext.uniqueId.has_value()) { params["uniqueId"] = *newContext.uniqueId; } - folly::dynamic contextCreated = folly::dynamic::object( - "method", "Runtime.executionContextCreated")("params", params); - frontendChannel_(folly::toJson(contextCreated)); + frontendChannel_( + cdp::jsonNotification("Runtime.executionContextCreated", params)); } } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h index 70b7fe8d5e5c6a..167c4c2205bea9 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InstanceAgent.h @@ -7,11 +7,11 @@ #pragma once +#include "CdpJson.h" #include "RuntimeTarget.h" #include "SessionState.h" #include -#include #include #include diff --git a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.cpp b/packages/react-native/ReactCommon/jsinspector-modern/Parsing.cpp deleted file mode 100644 index 99b233aa9ca728..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include -#include -#include - -namespace facebook::react::jsinspector_modern::cdp { - -PreparsedRequest preparse(std::string_view message) { - folly::dynamic parsed = folly::parseJson(message); - return PreparsedRequest{ - .id = parsed["id"].getInt(), - .method = parsed["method"].getString(), - .params = parsed.count("params") ? parsed["params"] : nullptr}; -} - -std::string PreparsedRequest::toJson() const { - folly::dynamic obj = folly::dynamic::object; - obj["id"] = id; - obj["method"] = method; - if (params != nullptr) { - obj["params"] = params; - } - return folly::toJson(obj); -} - -} // namespace facebook::react::jsinspector_modern::cdp diff --git a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h b/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h deleted file mode 100644 index bd446fb1971448..00000000000000 --- a/packages/react-native/ReactCommon/jsinspector-modern/Parsing.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include -#include -#include - -namespace facebook::react::jsinspector_modern { - -namespace cdp { -using RequestId = long long; - -/** - * An incoming CDP request that has been parsed into a more usable form. - */ -struct PreparsedRequest { - public: - /** - * The ID of the request. - */ - RequestId id; - - /** - * The name of the method being invoked. - */ - std::string method; - - /** - * The parameters passed to the method, if any. - */ - folly::dynamic params; - - /** - * Equality operator, useful for unit tests - */ - inline bool operator==(const PreparsedRequest& rhs) const { - return id == rhs.id && method == rhs.method && params == rhs.params; - } - - std::string toJson() const; -}; - -/** - * Parse a JSON-encoded CDP request into its constituent parts. - * \throws ParseError If the input cannot be parsed. - * \throws TypeError If the input does not conform to the expected format. - */ -PreparsedRequest preparse(std::string_view message); - -/** - * A type error that may be thrown while preparsing a request, or while - * accessing dynamic params on a request. - */ -using TypeError = folly::TypeError; - -/** - * A parse error that may be thrown while preparsing a request. - */ -using ParseError = folly::json::parse_error; -} // namespace cdp - -} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp index efac621026d638..0172ff47d13355 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.cpp @@ -42,21 +42,20 @@ bool RuntimeAgent::handleRequest(const cdp::PreparsedRequest& req) { auto executionContextId = req.params["executionContextId"].getInt(); if (executionContextId < (int64_t)std::numeric_limits::min() || executionContextId > (int64_t)std::numeric_limits::max()) { - frontendChannel_(folly::toJson(folly::dynamic::object("id", req.id)( - "error", - folly::dynamic::object("code", -32602)( - "message", "Invalid execution context id")))); + frontendChannel_(cdp::jsonError( + req.id, + cdp::ErrorCode::InvalidParams, + "Invalid execution context id")); return true; } contextSelector = ExecutionContextSelector::byId((int32_t)executionContextId); if (req.params.count("executionContextName")) { - frontendChannel_(folly::toJson(folly::dynamic::object("id", req.id)( - "error", - folly::dynamic::object("code", -32602)( - "message", - "executionContextName is mutually exclusive with executionContextId")))); + frontendChannel_(cdp::jsonError( + req.id, + cdp::ErrorCode::InvalidParams, + "executionContextName is mutually exclusive with executionContextId")); return true; } } else if (req.params.count("executionContextName")) { @@ -68,10 +67,7 @@ bool RuntimeAgent::handleRequest(const cdp::PreparsedRequest& req) { } sessionState_.subscribedBindings[bindingName].insert(contextSelector); - folly::dynamic res = folly::dynamic::object("id", req.id)( - "result", folly::dynamic::object()); - std::string json = folly::toJson(res); - frontendChannel_(json); + frontendChannel_(cdp::jsonResult(req.id)); return true; } @@ -83,10 +79,7 @@ bool RuntimeAgent::handleRequest(const cdp::PreparsedRequest& req) { // if the subscription is targeted by context name. sessionState_.subscribedBindings.erase(req.params["name"].getString()); - folly::dynamic res = folly::dynamic::object("id", req.id)( - "result", folly::dynamic::object()); - std::string json = folly::toJson(res); - frontendChannel_(json); + frontendChannel_(cdp::jsonResult(req.id)); return true; } @@ -113,12 +106,11 @@ void RuntimeAgent::notifyBindingCalled( return; } - frontendChannel_( - folly::toJson(folly::dynamic::object("method", "Runtime.bindingCalled")( - "params", - folly::dynamic::object( - "executionContextId", executionContextDescription_.id)( - "name", bindingName)("payload", payload)))); + frontendChannel_(cdp::jsonNotification( + "Runtime.bindingCalled", + folly::dynamic::object( + "executionContextId", executionContextDescription_.id)( + "name", bindingName)("payload", payload))); } RuntimeAgent::ExportedState RuntimeAgent::getExportedState() { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h index 9a96760e565fbb..4cc01bc1bd0d9a 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgent.h @@ -7,12 +7,11 @@ #pragma once +#include "CdpJson.h" #include "InspectorInterfaces.h" #include "RuntimeAgentDelegate.h" #include "RuntimeTarget.h" -#include - namespace facebook::react::jsinspector_modern { class RuntimeTargetController; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h index d7042d60d48c24..d5e62d1b576c2c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeAgentDelegate.h @@ -7,7 +7,7 @@ #pragma once -#include +#include "CdpJson.h" namespace facebook::react::jsinspector_modern { From 028615180b1fee8a4ab38a77163aa1fbfd68c6db Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:07:48 -0800 Subject: [PATCH 108/361] Add missing `Headers` methods (#43279) Summary: ```tsx // Hermes runtime (RN 73.x) console.log({...Headers.prototype}) // result: { "append": [Function anonymous], "delete": [Function anonymous], "entries": [Function anonymous], "forEach": [Function anonymous], "get": [Function anonymous], "has": [Function anonymous], "keys": [Function anonymous], "set": [Function anonymous], "values": [Function anonymous], Symbol(Symbol.iterator): [Function anonymous] } ``` But in typescript ```tsx new Headers().entries() // ^^^ Error: Property entries does not exist on type Headers Object.fromEntries(new Headers()) // ^^^ Error: Property [Symbol.iterator] is missing in type Headers but required in type Iterable ``` ## Changelog: [GENERAL] [ADDED] - [TypeScript] Add missing `Header` methods Pull Request resolved: https://github.com/facebook/react-native/pull/43279 Test Plan: Use code above in your RN project and run `yarn tsc --noEmit` Reviewed By: rshest Differential Revision: D54554523 Pulled By: arushikesarwani94 fbshipit-source-id: ae7f05f9526771ff003aaf22f786b5503661c739 --- packages/react-native/types/modules/globals.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-native/types/modules/globals.d.ts b/packages/react-native/types/modules/globals.d.ts index 51272890300db7..e22b936f3403d7 100644 --- a/packages/react-native/types/modules/globals.d.ts +++ b/packages/react-native/types/modules/globals.d.ts @@ -132,6 +132,10 @@ declare interface Headers { get(name: string): string | null; has(name: string): boolean; set(name: string, value: string): void; + entries(): IterableIterator<[string, string]>; + keys(): IterableIterator; + values(): IterableIterator; + [Symbol.iterator](): IterableIterator<[string, string]>; } declare var Headers: { From a66f4450e5520895a2e20cf6bb33c64b5256e431 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 6 Mar 2024 12:41:49 -0800 Subject: [PATCH 109/361] Improve logic to report mounted surfaces (#43337) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43337 Changelog: [internal] Mount instructions and listeners are only called from the UI thread, so there's no need to have synchronization mechanisms for concurrency. We're also scheduling mount hooks notifications once, but subsequent calls are ignored instead of accumulated to be notified together. This also changes that to collect all the surface IDs in the array that is read on notification. Reviewed By: sammy-SC Differential Revision: D54547194 fbshipit-source-id: a861e3b0113914aae5325c1486bcf8acd50eef79 --- .../react/fabric/FabricUIManager.java | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index 4b5adcbf972a78..e11dd3637030ae 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -91,7 +91,6 @@ import java.util.Map; import java.util.Queue; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; /** * We instruct ProGuard not to strip out any fields or methods, because many of these methods are @@ -173,7 +172,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener { @NonNull private final CopyOnWriteArrayList mListeners = new CopyOnWriteArrayList<>(); - @NonNull private final AtomicBoolean mMountNotificationScheduled = new AtomicBoolean(false); + private boolean mMountNotificationScheduled = false; + private final List mMountedSurfaceIds = new ArrayList<>(); @ThreadConfined(UI) @NonNull @@ -1203,6 +1203,8 @@ public Map getPerformanceCounters() { } private class MountItemDispatchListener implements MountItemDispatcher.ItemDispatchListener { + @UiThread + @ThreadConfined(UI) @Override public void willMountItems(@Nullable List mountItems) { for (UIManagerListener listener : mListeners) { @@ -1210,18 +1212,26 @@ public void willMountItems(@Nullable List mountItems) { } } + @UiThread + @ThreadConfined(UI) @Override public void didMountItems(@Nullable List mountItems) { for (UIManagerListener listener : mListeners) { listener.didMountItems(FabricUIManager.this); } - if (!ReactFeatureFlags.enableMountHooks) { + if (!ReactFeatureFlags.enableMountHooks || mountItems == null || mountItems.isEmpty()) { return; } - boolean mountNotificationScheduled = mMountNotificationScheduled.getAndSet(true); - if (!mountNotificationScheduled) { + // Collect surface IDs for all the mount items + for (MountItem mountItem : mountItems) { + if (mountItem != null && !mMountedSurfaceIds.contains(mountItem.getSurfaceId())) { + mMountedSurfaceIds.add(mountItem.getSurfaceId()); + } + } + + if (!mMountNotificationScheduled && !mMountedSurfaceIds.isEmpty()) { // Notify mount when the effects are visible and prevent mount hooks to // delay paint. UiThreadUtil.getUiThreadHandler() @@ -1229,28 +1239,19 @@ public void didMountItems(@Nullable List mountItems) { new Runnable() { @Override public void run() { - mMountNotificationScheduled.set(false); - - if (mDestroyed) { - return; - } + mMountNotificationScheduled = false; final @Nullable Binding binding = mBinding; - if (mountItems == null || binding == null) { + if (binding == null || mDestroyed) { + mMountedSurfaceIds.clear(); return; } - // Collect surface IDs for all the mount items - List surfaceIds = new ArrayList<>(); - for (MountItem mountItem : mountItems) { - if (mountItem != null && !surfaceIds.contains(mountItem.getSurfaceId())) { - surfaceIds.add(mountItem.getSurfaceId()); - } - } - - for (int surfaceId : surfaceIds) { + for (int surfaceId : mMountedSurfaceIds) { binding.reportMount(surfaceId); } + + mMountedSurfaceIds.clear(); } }); } From fafd64e9c39e69139f5f9cdbf01d62b5be910349 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 6 Mar 2024 12:41:49 -0800 Subject: [PATCH 110/361] Migrate mount hooks flag to new system (#43350) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43350 Changelog: [internal] Mount hooks have been shipped on iOS, so this removes the flag for them. On Android, we're still testing them so it's worth moving them to the new system and scoping them to that platform. Reviewed By: sammy-SC Differential Revision: D54587740 fbshipit-source-id: d074927fee1a967bd3928970c31975d07cd393bb --- .../React/Fabric/RCTSurfacePresenter.mm | 4 --- .../ReactAndroid/api/ReactAndroid.api | 1 - .../react/config/ReactFeatureFlags.java | 3 -- .../react/fabric/FabricUIManager.java | 5 +++- .../featureflags/ReactNativeFeatureFlags.kt | 8 +++++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +++++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 ++- .../ReactNativeFeatureFlagsDefaults.kt | 4 ++- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++++++- .../ReactNativeFeatureFlagsProvider.kt | 4 ++- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++++++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +++- .../featureflags/ReactNativeFeatureFlags.cpp | 6 +++- .../featureflags/ReactNativeFeatureFlags.h | 7 ++++- .../ReactNativeFeatureFlagsAccessor.cpp | 28 +++++++++++++++---- .../ReactNativeFeatureFlagsAccessor.h | 6 ++-- .../ReactNativeFeatureFlagsDefaults.h | 6 +++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++++- .../NativeReactNativeFeatureFlags.h | 4 ++- .../ReactCommon/react/utils/CoreFeatures.cpp | 1 - .../ReactCommon/react/utils/CoreFeatures.h | 3 -- .../ReactNativeFeatureFlags.config.js | 5 ++++ .../NativeReactNativeFeatureFlags.js | 3 +- .../featureflags/ReactNativeFeatureFlags.js | 7 ++++- 25 files changed, 129 insertions(+), 36 deletions(-) diff --git a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm index 4c1e048c4063f2..712d2cfe5e4dca 100644 --- a/packages/react-native/React/Fabric/RCTSurfacePresenter.mm +++ b/packages/react-native/React/Fabric/RCTSurfacePresenter.mm @@ -265,10 +265,6 @@ - (RCTScheduler *)_createScheduler CoreFeatures::enableGranularScrollViewStateUpdatesIOS = true; } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_mount_hooks_ios")) { - CoreFeatures::enableMountHooks = true; - } - if (reactNativeConfig && reactNativeConfig->getBool("react_fabric:enable_cloneless_state_progression")) { CoreFeatures::enableClonelessStateProgression = true; } diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index d2437b2c8a25a4..16be0c4d3d81e7 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1910,7 +1910,6 @@ public class com/facebook/react/config/ReactFeatureFlags { public static field enableFabricPendingEventQueue Z public static field enableFabricRenderer Z public static field enableFabricRendererExclusively Z - public static field enableMountHooks Z public static field enableRemoveDeleteTreeInstruction Z public static field enableTextSpannableCache Z public static field enableViewRecycling Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index f122d195bbab6b..ad6e23618140d1 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -109,9 +109,6 @@ public class ReactFeatureFlags { */ public static boolean enableRemoveDeleteTreeInstruction = false; - /** Report mount operations from the host platform to notify mount hooks. */ - public static boolean enableMountHooks = false; - /** Use native view configs in bridgeless mode. */ public static boolean useNativeViewConfigsInBridgelessMode = false; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java index e11dd3637030ae..476dd2318d3bd0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java @@ -65,6 +65,7 @@ import com.facebook.react.fabric.mounting.mountitems.MountItem; import com.facebook.react.fabric.mounting.mountitems.MountItemFactory; import com.facebook.react.interfaces.fabric.SurfaceHandler; +import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags; import com.facebook.react.internal.interop.InteropEventEmitter; import com.facebook.react.modules.core.ReactChoreographer; import com.facebook.react.modules.i18nmanager.I18nUtil; @@ -1220,7 +1221,9 @@ public void didMountItems(@Nullable List mountItems) { listener.didMountItems(FabricUIManager.this); } - if (!ReactFeatureFlags.enableMountHooks || mountItems == null || mountItems.isEmpty()) { + if (!ReactNativeFeatureFlags.enableMountHooksAndroid() + || mountItems == null + || mountItems.isEmpty()) { return; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index dd048b337de86c..a14811239d8f64 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6d6fd79bdd221b3aeed0057ac756ee92>> + * @generated SignedSource<> */ /** @@ -64,6 +64,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun enableMicrotasks(): Boolean = accessor.enableMicrotasks() + /** + * Enables the notification of mount operations to mount hooks on Android. + */ + @JvmStatic + public fun enableMountHooksAndroid(): Boolean = accessor.enableMountHooksAndroid() + /** * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index a791381d81b5ed..e65fa7974529d4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<45776de0416f833eed9bb84d6b7d1052>> + * @generated SignedSource<<7ae379135157666d9646f1d8eeec9989>> */ /** @@ -26,6 +26,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableCustomDrawOrderFabricCache: Boolean? = null private var enableFixForClippedSubviewsCrashCache: Boolean? = null private var enableMicrotasksCache: Boolean? = null + private var enableMountHooksAndroidCache: Boolean? = null private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null @@ -85,6 +86,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun enableMountHooksAndroid(): Boolean { + var cached = enableMountHooksAndroidCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.enableMountHooksAndroid() + enableMountHooksAndroidCache = cached + } + return cached + } + override fun enableSpannableBuildingUnification(): Boolean { var cached = enableSpannableBuildingUnificationCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index 84daf0216d615d..d6093108c73d9b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<244a0656beee8e018585bdd4bb4e5cd1>> */ /** @@ -40,6 +40,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun enableMicrotasks(): Boolean + @DoNotStrip @JvmStatic public external fun enableMountHooksAndroid(): Boolean + @DoNotStrip @JvmStatic public external fun enableSpannableBuildingUnification(): Boolean @DoNotStrip @JvmStatic public external fun inspectorEnableCxxInspectorPackagerConnection(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 9c3cdc1da857fd..7a2ac9d1601672 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4f72683fb2a832d5b77ee2cb37343526>> + * @generated SignedSource<> */ /** @@ -35,6 +35,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun enableMicrotasks(): Boolean = false + override fun enableMountHooksAndroid(): Boolean = false + override fun enableSpannableBuildingUnification(): Boolean = false override fun inspectorEnableCxxInspectorPackagerConnection(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 8f318b3a8eaec8..cae01383bef9fd 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5fd54183222961f5557dbe0ac111a6ec>> + * @generated SignedSource<<919eb0f27540e5dd7a1e028663c23264>> */ /** @@ -30,6 +30,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableCustomDrawOrderFabricCache: Boolean? = null private var enableFixForClippedSubviewsCrashCache: Boolean? = null private var enableMicrotasksCache: Boolean? = null + private var enableMountHooksAndroidCache: Boolean? = null private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null @@ -95,6 +96,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun enableMountHooksAndroid(): Boolean { + var cached = enableMountHooksAndroidCache + if (cached == null) { + cached = currentProvider.enableMountHooksAndroid() + accessedFeatureFlags.add("enableMountHooksAndroid") + enableMountHooksAndroidCache = cached + } + return cached + } + override fun enableSpannableBuildingUnification(): Boolean { var cached = enableSpannableBuildingUnificationCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 30d0298638f42d..451f64be6d98bc 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -35,6 +35,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun enableMicrotasks(): Boolean + @DoNotStrip public fun enableMountHooksAndroid(): Boolean + @DoNotStrip public fun enableSpannableBuildingUnification(): Boolean @DoNotStrip public fun inspectorEnableCxxInspectorPackagerConnection(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index d8d1c6994186ff..4add6436bbd4c9 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5b40c18d94331e9ec3fdd1a8814b1292>> + * @generated SignedSource<<393c6cf93399cfe0b0533927877531d5>> */ /** @@ -75,6 +75,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool enableMountHooksAndroid() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableMountHooksAndroid"); + return method(javaProvider_); + } + bool enableSpannableBuildingUnification() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("enableSpannableBuildingUnification"); @@ -133,6 +139,11 @@ bool JReactNativeFeatureFlagsCxxInterop::enableMicrotasks( return ReactNativeFeatureFlags::enableMicrotasks(); } +bool JReactNativeFeatureFlagsCxxInterop::enableMountHooksAndroid( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::enableMountHooksAndroid(); +} + bool JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::enableSpannableBuildingUnification(); @@ -188,6 +199,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "enableMicrotasks", JReactNativeFeatureFlagsCxxInterop::enableMicrotasks), + makeNativeMethod( + "enableMountHooksAndroid", + JReactNativeFeatureFlagsCxxInterop::enableMountHooksAndroid), makeNativeMethod( "enableSpannableBuildingUnification", JReactNativeFeatureFlagsCxxInterop::enableSpannableBuildingUnification), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 800e3eb93b9336..d710f2c4052299 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<514446a9fd1351df1f7f3b307de54b56>> + * @generated SignedSource<> */ /** @@ -48,6 +48,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool enableMicrotasks( facebook::jni::alias_ref); + static bool enableMountHooksAndroid( + facebook::jni::alias_ref); + static bool enableSpannableBuildingUnification( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index a28c548a112616..163c9e238845fe 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<59573653a5f37505d9a52ac76a9dbcff>> + * @generated SignedSource<> */ /** @@ -45,6 +45,10 @@ bool ReactNativeFeatureFlags::enableMicrotasks() { return getAccessor().enableMicrotasks(); } +bool ReactNativeFeatureFlags::enableMountHooksAndroid() { + return getAccessor().enableMountHooksAndroid(); +} + bool ReactNativeFeatureFlags::enableSpannableBuildingUnification() { return getAccessor().enableSpannableBuildingUnification(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index 8bab08ca93bdf0..c8d5083c60dfab 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<036e7f3ee4def5b955ed61c707bbc8f8>> + * @generated SignedSource<> */ /** @@ -63,6 +63,11 @@ class ReactNativeFeatureFlags { */ static bool enableMicrotasks(); + /** + * Enables the notification of mount operations to mount hooks on Android. + */ + static bool enableMountHooksAndroid(); + /** * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index c5754efb760729..9adeb8f60d422d 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -137,6 +137,24 @@ bool ReactNativeFeatureFlagsAccessor::enableMicrotasks() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::enableMountHooksAndroid() { + auto flagValue = enableMountHooksAndroid_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(6, "enableMountHooksAndroid"); + + flagValue = currentProvider_->enableMountHooksAndroid(); + enableMountHooksAndroid_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::enableSpannableBuildingUnification() { auto flagValue = enableSpannableBuildingUnification_.load(); @@ -146,7 +164,7 @@ bool ReactNativeFeatureFlagsAccessor::enableSpannableBuildingUnification() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(6, "enableSpannableBuildingUnification"); + markFlagAsAccessed(7, "enableSpannableBuildingUnification"); flagValue = currentProvider_->enableSpannableBuildingUnification(); enableSpannableBuildingUnification_ = flagValue; @@ -164,7 +182,7 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableCxxInspectorPackagerConnect // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(7, "inspectorEnableCxxInspectorPackagerConnection"); + markFlagAsAccessed(8, "inspectorEnableCxxInspectorPackagerConnection"); flagValue = currentProvider_->inspectorEnableCxxInspectorPackagerConnection(); inspectorEnableCxxInspectorPackagerConnection_ = flagValue; @@ -182,7 +200,7 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(8, "inspectorEnableModernCDPRegistry"); + markFlagAsAccessed(9, "inspectorEnableModernCDPRegistry"); flagValue = currentProvider_->inspectorEnableModernCDPRegistry(); inspectorEnableModernCDPRegistry_ = flagValue; @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "useModernRuntimeScheduler"); + markFlagAsAccessed(10, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 700ff2a6d67bf8..5199fc1ca59371 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<2fa6a12c1d9b10483d8e2e23125d231e>> + * @generated SignedSource<> */ /** @@ -37,6 +37,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableCustomDrawOrderFabric(); bool enableFixForClippedSubviewsCrash(); bool enableMicrotasks(); + bool enableMountHooksAndroid(); bool enableSpannableBuildingUnification(); bool inspectorEnableCxxInspectorPackagerConnection(); bool inspectorEnableModernCDPRegistry(); @@ -51,7 +52,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 10> accessedFeatureFlags_; + std::array, 11> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> batchRenderingUpdatesInEventLoop_; @@ -59,6 +60,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableCustomDrawOrderFabric_; std::atomic> enableFixForClippedSubviewsCrash_; std::atomic> enableMicrotasks_; + std::atomic> enableMountHooksAndroid_; std::atomic> enableSpannableBuildingUnification_; std::atomic> inspectorEnableCxxInspectorPackagerConnection_; std::atomic> inspectorEnableModernCDPRegistry_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 32d4954b1ce726..85f6d322e89d79 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<927bc1410a5baadf3a4005e50067c4df>> + * @generated SignedSource<<62de1b0e27590ad769296358a4f42c7a>> */ /** @@ -51,6 +51,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool enableMountHooksAndroid() override { + return false; + } + bool enableSpannableBuildingUnification() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index eb29ae858fe8cd..48ec9f28697f87 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<74b4ca674d50bda5fb18d74568024399>> + * @generated SignedSource<<3117fc0389416297369a47ee480eb906>> */ /** @@ -31,6 +31,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableCustomDrawOrderFabric() = 0; virtual bool enableFixForClippedSubviewsCrash() = 0; virtual bool enableMicrotasks() = 0; + virtual bool enableMountHooksAndroid() = 0; virtual bool enableSpannableBuildingUnification() = 0; virtual bool inspectorEnableCxxInspectorPackagerConnection() = 0; virtual bool inspectorEnableModernCDPRegistry() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index a12c50f8b7eab4..30c6d98f483d24 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<1a785df8b045c1340d3139bd85add42b>> + * @generated SignedSource<<27923a2dbf1dcbad238a4d06ebb54fb5>> */ /** @@ -67,6 +67,11 @@ bool NativeReactNativeFeatureFlags::enableMicrotasks( return ReactNativeFeatureFlags::enableMicrotasks(); } +bool NativeReactNativeFeatureFlags::enableMountHooksAndroid( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::enableMountHooksAndroid(); +} + bool NativeReactNativeFeatureFlags::enableSpannableBuildingUnification( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::enableSpannableBuildingUnification(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 840f4a959f208f..4fe211cda46181 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -48,6 +48,8 @@ class NativeReactNativeFeatureFlags bool enableMicrotasks(jsi::Runtime& runtime); + bool enableMountHooksAndroid(jsi::Runtime& runtime); + bool enableSpannableBuildingUnification(jsi::Runtime& runtime); bool inspectorEnableCxxInspectorPackagerConnection(jsi::Runtime& runtime); diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp index 1ae6897bfbc1cc..f29d262bd1fa1c 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.cpp @@ -12,7 +12,6 @@ namespace facebook::react { bool CoreFeatures::enablePropIteratorSetter = false; bool CoreFeatures::cacheLastTextMeasurement = false; bool CoreFeatures::enableGranularScrollViewStateUpdatesIOS = false; -bool CoreFeatures::enableMountHooks = false; bool CoreFeatures::enableGranularShadowTreeStateReconciliation = false; bool CoreFeatures::enableClonelessStateProgression = false; bool CoreFeatures::excludeYogaFromRawProps = false; diff --git a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h index 1cf5dc68d1e2df..7b9731917f580a 100644 --- a/packages/react-native/ReactCommon/react/utils/CoreFeatures.h +++ b/packages/react-native/ReactCommon/react/utils/CoreFeatures.h @@ -29,9 +29,6 @@ class CoreFeatures { // updates for all changes in scroll position. static bool enableGranularScrollViewStateUpdatesIOS; - // Report mount operations from the host platform to notify mount hooks. - static bool enableMountHooks; - // When enabled, the renderer would only fail commits when they propagate // state and the last commit that updated state changed before committing. static bool enableGranularShadowTreeStateReconciliation; diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 1719eceb11d4b0..bec7fcf7f23477 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -57,6 +57,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution).', }, + enableMountHooksAndroid: { + defaultValue: false, + description: + 'Enables the notification of mount operations to mount hooks on Android.', + }, enableSpannableBuildingUnification: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js index 67bfc466894e12..9352ed1141c242 100644 --- a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * @flow strict-local */ @@ -29,6 +29,7 @@ export interface Spec extends TurboModule { +enableCustomDrawOrderFabric?: () => boolean; +enableFixForClippedSubviewsCrash?: () => boolean; +enableMicrotasks?: () => boolean; + +enableMountHooksAndroid?: () => boolean; +enableSpannableBuildingUnification?: () => boolean; +inspectorEnableCxxInspectorPackagerConnection?: () => boolean; +inspectorEnableModernCDPRegistry?: () => boolean; diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 6c5ab2458d1c93..3d68cd7572a3d8 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * @flow strict-local */ @@ -46,6 +46,7 @@ export type ReactNativeFeatureFlags = { enableCustomDrawOrderFabric: Getter, enableFixForClippedSubviewsCrash: Getter, enableMicrotasks: Getter, + enableMountHooksAndroid: Getter, enableSpannableBuildingUnification: Getter, inspectorEnableCxxInspectorPackagerConnection: Getter, inspectorEnableModernCDPRegistry: Getter, @@ -116,6 +117,10 @@ export const enableFixForClippedSubviewsCrash: Getter = createNativeFla * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). */ export const enableMicrotasks: Getter = createNativeFlagGetter('enableMicrotasks', false); +/** + * Enables the notification of mount operations to mount hooks on Android. + */ +export const enableMountHooksAndroid: Getter = createNativeFlagGetter('enableMountHooksAndroid', false); /** * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ From c645646a20b20c48e0d5c92738843bf6b90a00c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 6 Mar 2024 12:41:49 -0800 Subject: [PATCH 111/361] Create new flag to disable the last part of the notifications for mount hooks on Android (#43349) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43349 Changelog: [internal] We still haven't found the root cause of some of the crashes we're seeing in the experiments to enable mount hooks on Android. This adds a new feature flag to skip part of the mount hooks pipeline to see if we can scope the investigation to that specific part (where we query the root tree in the base revision from the mounting coordinator). Reviewed By: sammy-SC Differential Revision: D54587739 fbshipit-source-id: 792aa8b06808e96638d1bba072bf4060ec492bd2 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 ++++++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 +++++++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +++- .../ReactNativeFeatureFlagsDefaults.kt | 4 +++- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++++++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +++- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 +++++++++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 ++++- .../ReactCommon/React-Fabric.podspec | 1 + .../ReactCommon/ReactCommon.podspec | 3 ++- .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++++- .../featureflags/ReactNativeFeatureFlags.h | 7 +++++- .../ReactNativeFeatureFlagsAccessor.cpp | 22 +++++++++++++++++-- .../ReactNativeFeatureFlagsAccessor.h | 6 +++-- .../ReactNativeFeatureFlagsDefaults.h | 6 ++++- .../ReactNativeFeatureFlagsProvider.h | 3 ++- .../NativeReactNativeFeatureFlags.cpp | 7 +++++- .../NativeReactNativeFeatureFlags.h | 4 +++- .../react/renderer/uimanager/CMakeLists.txt | 1 + .../react/renderer/uimanager/UIManager.cpp | 9 ++++++++ .../ReactNativeFeatureFlags.config.js | 5 +++++ .../NativeReactNativeFeatureFlags.js | 3 ++- .../featureflags/ReactNativeFeatureFlags.js | 7 +++++- 23 files changed, 135 insertions(+), 21 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index a14811239d8f64..975a7182c5be44 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -88,6 +88,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun inspectorEnableModernCDPRegistry(): Boolean = accessor.inspectorEnableModernCDPRegistry() + /** + * This is a temporary flag to disable part of the mount hooks pipeline to investigate a crash. + */ + @JvmStatic + public fun skipMountHookNotifications(): Boolean = accessor.skipMountHookNotifications() + /** * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index e65fa7974529d4..fc217774592d47 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<7ae379135157666d9646f1d8eeec9989>> + * @generated SignedSource<<8539cf7ba13ab52ca878efd2c4858d7a>> */ /** @@ -30,6 +30,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null + private var skipMountHookNotificationsCache: Boolean? = null private var useModernRuntimeSchedulerCache: Boolean? = null override fun commonTestFlag(): Boolean { @@ -122,6 +123,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun skipMountHookNotifications(): Boolean { + var cached = skipMountHookNotificationsCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.skipMountHookNotifications() + skipMountHookNotificationsCache = cached + } + return cached + } + override fun useModernRuntimeScheduler(): Boolean { var cached = useModernRuntimeSchedulerCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index d6093108c73d9b..d97a2dd6b4ab17 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<244a0656beee8e018585bdd4bb4e5cd1>> + * @generated SignedSource<> */ /** @@ -48,6 +48,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun inspectorEnableModernCDPRegistry(): Boolean + @DoNotStrip @JvmStatic public external fun skipMountHookNotifications(): Boolean + @DoNotStrip @JvmStatic public external fun useModernRuntimeScheduler(): Boolean @DoNotStrip @JvmStatic public external fun override(provider: Any) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 7a2ac9d1601672..006caa1e9505b6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<99263973c4a06fdc91e7c9edf4aa4e19>> */ /** @@ -43,5 +43,7 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun inspectorEnableModernCDPRegistry(): Boolean = false + override fun skipMountHookNotifications(): Boolean = false + override fun useModernRuntimeScheduler(): Boolean = false } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index cae01383bef9fd..88558da84c97f0 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<919eb0f27540e5dd7a1e028663c23264>> + * @generated SignedSource<> */ /** @@ -34,6 +34,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null + private var skipMountHookNotificationsCache: Boolean? = null private var useModernRuntimeSchedulerCache: Boolean? = null override fun commonTestFlag(): Boolean { @@ -136,6 +137,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun skipMountHookNotifications(): Boolean { + var cached = skipMountHookNotificationsCache + if (cached == null) { + cached = currentProvider.skipMountHookNotifications() + accessedFeatureFlags.add("skipMountHookNotifications") + skipMountHookNotificationsCache = cached + } + return cached + } + override fun useModernRuntimeScheduler(): Boolean { var cached = useModernRuntimeSchedulerCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 451f64be6d98bc..905ee909744af3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<268a87860fea5f281567d2142f90b0d4>> */ /** @@ -43,5 +43,7 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun inspectorEnableModernCDPRegistry(): Boolean + @DoNotStrip public fun skipMountHookNotifications(): Boolean + @DoNotStrip public fun useModernRuntimeScheduler(): Boolean } diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index 4add6436bbd4c9..fec585cacd02c9 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<393c6cf93399cfe0b0533927877531d5>> + * @generated SignedSource<> */ /** @@ -99,6 +99,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool skipMountHookNotifications() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("skipMountHookNotifications"); + return method(javaProvider_); + } + bool useModernRuntimeScheduler() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("useModernRuntimeScheduler"); @@ -159,6 +165,11 @@ bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry( return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); } +bool JReactNativeFeatureFlagsCxxInterop::skipMountHookNotifications( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::skipMountHookNotifications(); +} + bool JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::useModernRuntimeScheduler(); @@ -211,6 +222,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "inspectorEnableModernCDPRegistry", JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry), + makeNativeMethod( + "skipMountHookNotifications", + JReactNativeFeatureFlagsCxxInterop::skipMountHookNotifications), makeNativeMethod( "useModernRuntimeScheduler", JReactNativeFeatureFlagsCxxInterop::useModernRuntimeScheduler), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index d710f2c4052299..45ccaf577a0b8f 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -60,6 +60,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool inspectorEnableModernCDPRegistry( facebook::jni::alias_ref); + static bool skipMountHookNotifications( + facebook::jni::alias_ref); + static bool useModernRuntimeScheduler( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index 58f6f0a84383c8..0423352e654c09 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -56,6 +56,7 @@ Pod::Spec.new do |s| s.dependency "fmt", "9.1.0" s.dependency "React-Core" s.dependency "React-debug" + s.dependency "React-featureflags" s.dependency "React-utils" s.dependency "React-runtimescheduler" s.dependency "React-cxxreact" diff --git a/packages/react-native/ReactCommon/ReactCommon.podspec b/packages/react-native/ReactCommon/ReactCommon.podspec index 599e3f97a1c6c7..7fe1c6acee3e55 100644 --- a/packages/react-native/ReactCommon/ReactCommon.podspec +++ b/packages/react-native/ReactCommon/ReactCommon.podspec @@ -72,8 +72,9 @@ Pod::Spec.new do |s| ss.subspec "core" do |sss| sss.source_files = "react/nativemodule/core/ReactCommon/**/*.{cpp,h}" - sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-utils/React_utils.framework/Headers\"" } + sss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_TARGET_SRCROOT)/ReactCommon\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_debug.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-debug/React_featureflags.framework/Headers\" \"$(PODS_CONFIGURATION_BUILD_DIR)/React-utils/React_utils.framework/Headers\"" } sss.dependency "React-debug", version + sss.dependency "React-featureflags", version sss.dependency "React-utils", version end end diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 163c9e238845fe..5a1a133eceae81 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -61,6 +61,10 @@ bool ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry() { return getAccessor().inspectorEnableModernCDPRegistry(); } +bool ReactNativeFeatureFlags::skipMountHookNotifications() { + return getAccessor().skipMountHookNotifications(); +} + bool ReactNativeFeatureFlags::useModernRuntimeScheduler() { return getAccessor().useModernRuntimeScheduler(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index c8d5083c60dfab..e3710156299756 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -83,6 +83,11 @@ class ReactNativeFeatureFlags { */ static bool inspectorEnableModernCDPRegistry(); + /** + * This is a temporary flag to disable part of the mount hooks pipeline to investigate a crash. + */ + static bool skipMountHookNotifications(); + /** * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index 9adeb8f60d422d..f352ada4f9124c 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6c1e6b6a51cd6fdddae40d3b61ae2b36>> */ /** @@ -209,6 +209,24 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::skipMountHookNotifications() { + auto flagValue = skipMountHookNotifications_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(10, "skipMountHookNotifications"); + + flagValue = currentProvider_->skipMountHookNotifications(); + skipMountHookNotifications_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { auto flagValue = useModernRuntimeScheduler_.load(); @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "useModernRuntimeScheduler"); + markFlagAsAccessed(11, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 5199fc1ca59371..6e51c8fda83255 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<4c5446d5b72429d090e17523f2d544a7>> */ /** @@ -41,6 +41,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableSpannableBuildingUnification(); bool inspectorEnableCxxInspectorPackagerConnection(); bool inspectorEnableModernCDPRegistry(); + bool skipMountHookNotifications(); bool useModernRuntimeScheduler(); void override(std::unique_ptr provider); @@ -52,7 +53,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 11> accessedFeatureFlags_; + std::array, 12> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> batchRenderingUpdatesInEventLoop_; @@ -64,6 +65,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableSpannableBuildingUnification_; std::atomic> inspectorEnableCxxInspectorPackagerConnection_; std::atomic> inspectorEnableModernCDPRegistry_; + std::atomic> skipMountHookNotifications_; std::atomic> useModernRuntimeScheduler_; }; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 85f6d322e89d79..3324b1239a1840 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<62de1b0e27590ad769296358a4f42c7a>> + * @generated SignedSource<<95e3fd7cf662623e3c09b093649d4ff2>> */ /** @@ -67,6 +67,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool skipMountHookNotifications() override { + return false; + } + bool useModernRuntimeScheduler() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index 48ec9f28697f87..a28f6e1c2ed1d5 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<3117fc0389416297369a47ee480eb906>> + * @generated SignedSource<<26990a0a11bb2d7cf8510773b6ece099>> */ /** @@ -35,6 +35,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableSpannableBuildingUnification() = 0; virtual bool inspectorEnableCxxInspectorPackagerConnection() = 0; virtual bool inspectorEnableModernCDPRegistry() = 0; + virtual bool skipMountHookNotifications() = 0; virtual bool useModernRuntimeScheduler() = 0; }; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index 30c6d98f483d24..f2a21bbc09d5cc 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<27923a2dbf1dcbad238a4d06ebb54fb5>> + * @generated SignedSource<<4f7daa629ad90a9ab2fdc99e7c51e355>> */ /** @@ -87,6 +87,11 @@ bool NativeReactNativeFeatureFlags::inspectorEnableModernCDPRegistry( return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); } +bool NativeReactNativeFeatureFlags::skipMountHookNotifications( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::skipMountHookNotifications(); +} + bool NativeReactNativeFeatureFlags::useModernRuntimeScheduler( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::useModernRuntimeScheduler(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 4fe211cda46181..47293751c29528 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -56,6 +56,8 @@ class NativeReactNativeFeatureFlags bool inspectorEnableModernCDPRegistry(jsi::Runtime& runtime); + bool skipMountHookNotifications(jsi::Runtime& runtime); + bool useModernRuntimeScheduler(jsi::Runtime& runtime); }; diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt index a7583450cadfb7..8f0aafeb80288a 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(react_render_uimanager folly_runtime jsi react_debug + react_featureflags react_render_componentregistry react_render_core react_render_debug diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp index 2f5b64cf0dc7f5..98dfb2b053a130 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -718,6 +719,14 @@ void UIManager::reportMount(SurfaceId surfaceId) const { auto time = JSExecutor::performanceNow(); + // We are testing the impact of enabling mount hooks on Android and we're + // seeing some crashes that we didn't see on iOS. We'll run a test to enable + // the mount reporting pipeline excluding the logic below, to see if that + // logic is what's causing the issues. See T179749070. + if (ReactNativeFeatureFlags::skipMountHookNotifications()) { + return; + } + auto rootShadowNode = RootShadowNode::Shared{}; shadowTreeRegistry_.visit(surfaceId, [&](const ShadowTree& shadowTree) { rootShadowNode = diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index bec7fcf7f23477..1a10c53c020c6a 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -77,6 +77,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes.', }, + skipMountHookNotifications: { + defaultValue: false, + description: + 'This is a temporary flag to disable part of the mount hooks pipeline to investigate a crash.', + }, useModernRuntimeScheduler: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js index 9352ed1141c242..2fda50641c86f0 100644 --- a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> * @flow strict-local */ @@ -33,6 +33,7 @@ export interface Spec extends TurboModule { +enableSpannableBuildingUnification?: () => boolean; +inspectorEnableCxxInspectorPackagerConnection?: () => boolean; +inspectorEnableModernCDPRegistry?: () => boolean; + +skipMountHookNotifications?: () => boolean; +useModernRuntimeScheduler?: () => boolean; } diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 3d68cd7572a3d8..56d0b91cb34090 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<5d1eca67ace8cccc336a6c6f65b40c99>> * @flow strict-local */ @@ -50,6 +50,7 @@ export type ReactNativeFeatureFlags = { enableSpannableBuildingUnification: Getter, inspectorEnableCxxInspectorPackagerConnection: Getter, inspectorEnableModernCDPRegistry: Getter, + skipMountHookNotifications: Getter, useModernRuntimeScheduler: Getter, } @@ -133,6 +134,10 @@ export const inspectorEnableCxxInspectorPackagerConnection: Getter = cr * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ export const inspectorEnableModernCDPRegistry: Getter = createNativeFlagGetter('inspectorEnableModernCDPRegistry', false); +/** + * This is a temporary flag to disable part of the mount hooks pipeline to investigate a crash. + */ +export const skipMountHookNotifications: Getter = createNativeFlagGetter('skipMountHookNotifications', false); /** * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. */ From c771011fed748b739ec0f2352654e255e8e507d9 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Wed, 6 Mar 2024 13:19:55 -0800 Subject: [PATCH 112/361] Support onActivityResult in Bridgeless (#43351) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43351 Implement `onActivityResult` on Bridgeless Changelog: [Internal] internal Reviewed By: cortinico Differential Revision: D54574139 fbshipit-source-id: f2369077199186ac6ef0187b5dfe7ed95f3b87fc --- .../ReactAndroid/api/ReactAndroid.api | 2 ++ .../com/facebook/react/ReactDelegate.java | 2 +- .../main/java/com/facebook/react/ReactHost.kt | 9 ++++++ .../facebook/react/runtime/ReactHostImpl.java | 32 +++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 16be0c4d3d81e7..a296e9fb3d3e0a 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -196,6 +196,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun getJsEngineResolutionAlgorithm ()Lcom/facebook/react/JSEngineResolutionAlgorithm; public abstract fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState; public abstract fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; + public abstract fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public abstract fun onBackPressed ()Z public abstract fun onHostDestroy ()V public abstract fun onHostDestroy (Landroid/app/Activity;)V @@ -3644,6 +3645,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React public fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState; public fun getMemoryPressureRouter ()Lcom/facebook/react/MemoryPressureRouter; public fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; + public fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public fun onBackPressed ()Z public fun onHostDestroy ()V public fun onHostDestroy (Landroid/app/Activity;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 12b1b06b3fa7f1..1f89ceee0f6a58 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -139,7 +139,7 @@ public boolean onBackPressed() { public void onActivityResult( int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) { if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: Implement onActivityResult for Bridgeless + mReactHost.onActivityResult(mActivity, requestCode, resultCode, data); } else { if (getReactNativeHost().hasInstance() && shouldForwardToReactInstance) { getReactNativeHost() diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index 966bbb54fda32e..69c9821b004a27 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -9,6 +9,7 @@ package com.facebook.react import android.app.Activity import android.content.Context +import android.content.Intent import android.os.Bundle import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.queue.ReactQueueConfiguration @@ -111,6 +112,14 @@ public interface ReactHost { */ public fun destroy(reason: String, ex: Exception?): TaskInterface + /* To be called when the host activity receives an activity result. */ + public fun onActivityResult( + activity: Activity, + requestCode: Int, + resultCode: Int, + data: Intent?, + ) + public fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit) public fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 40a29a1d8f9bad..ac66e250774c21 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -15,6 +15,7 @@ import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -603,6 +604,37 @@ RuntimeExecutor getRuntimeExecutor() { return null; } + /** + * To be called when the host activity receives an activity result. + * + * @param activity The host activity + */ + @ThreadConfined(UI) + @Override + public void onActivityResult( + Activity activity, int requestCode, int resultCode, @Nullable Intent data) { + final String method = + "onActivityResult(activity = \"" + + activity + + "\", requestCode = \"" + + requestCode + + "\", resultCode = \"" + + resultCode + + "\", data = \"" + + data + + "\")"; + log(method); + + ReactContext currentContext = getCurrentReactContext(); + if (currentContext != null) { + currentContext.onActivityResult(activity, requestCode, resultCode, data); + } + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Tried to access onActivityResult while context is not ready")); + } + @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); From f7bbaffdc3aa4e7af0b4d5f62e594cc7edd4f837 Mon Sep 17 00:00:00 2001 From: Adam Ernst Date: Wed, 6 Mar 2024 20:09:49 -0800 Subject: [PATCH 113/361] Apply RN_EXPORT to ReactNativeFeatureFlags functions (#43356) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43356 To make it accessible across different dylib/bundle. Changelog: [Internal] Reviewed By: d16r Differential Revision: D54601288 fbshipit-source-id: e65b724b228a680784e81b8c51ecd3f4df3fd668 --- .../featureflags/ReactNativeFeatureFlags.h | 34 +++++++++++-------- .../ReactNativeFeatureFlags.h-template.js | 10 ++++-- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index e3710156299756..f0c0c72b367bb9 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -23,6 +23,10 @@ #include #include +#ifndef RN_EXPORT +#define RN_EXPORT __attribute__((visibility("default"))) +#endif + namespace facebook::react { /** @@ -36,62 +40,62 @@ class ReactNativeFeatureFlags { /** * Common flag for testing. Do NOT modify. */ - static bool commonTestFlag(); + RN_EXPORT static bool commonTestFlag(); /** * When enabled, the RuntimeScheduler processing the event loop will batch all rendering updates and dispatch them together at the end of each iteration of the loop. */ - static bool batchRenderingUpdatesInEventLoop(); + RN_EXPORT static bool batchRenderingUpdatesInEventLoop(); /** * Enables the use of a background executor to compute layout and commit updates on Fabric (this system is deprecated and should not be used). */ - static bool enableBackgroundExecutor(); + RN_EXPORT static bool enableBackgroundExecutor(); /** * When enabled, Fabric will use customDrawOrder in ReactViewGroup (similar to old architecture). */ - static bool enableCustomDrawOrderFabric(); + RN_EXPORT static bool enableCustomDrawOrderFabric(); /** * Attempt at fixing a crash related to subview clipping on Android. This is a kill switch for the fix */ - static bool enableFixForClippedSubviewsCrash(); + RN_EXPORT static bool enableFixForClippedSubviewsCrash(); /** * Enables the use of microtasks in Hermes (scheduling) and RuntimeScheduler (execution). */ - static bool enableMicrotasks(); + RN_EXPORT static bool enableMicrotasks(); /** * Enables the notification of mount operations to mount hooks on Android. */ - static bool enableMountHooksAndroid(); + RN_EXPORT static bool enableMountHooksAndroid(); /** * Uses new, deduplicated logic for constructing Android Spannables from text fragments */ - static bool enableSpannableBuildingUnification(); + RN_EXPORT static bool enableSpannableBuildingUnification(); /** * Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes. */ - static bool inspectorEnableCxxInspectorPackagerConnection(); + RN_EXPORT static bool inspectorEnableCxxInspectorPackagerConnection(); /** * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ - static bool inspectorEnableModernCDPRegistry(); + RN_EXPORT static bool inspectorEnableModernCDPRegistry(); /** * This is a temporary flag to disable part of the mount hooks pipeline to investigate a crash. */ - static bool skipMountHookNotifications(); + RN_EXPORT static bool skipMountHookNotifications(); /** * When enabled, it uses the modern fork of RuntimeScheduler that allows scheduling tasks with priorities from any thread. */ - static bool useModernRuntimeScheduler(); + RN_EXPORT static bool useModernRuntimeScheduler(); /** * Overrides the feature flags with the ones provided by the given provider @@ -111,7 +115,7 @@ class ReactNativeFeatureFlags { * std::make_unique()); * ``` */ - static void override( + RN_EXPORT static void override( std::unique_ptr provider); /** @@ -126,7 +130,7 @@ class ReactNativeFeatureFlags { * call `dangerouslyReset` after destroying the runtime and `override` again * before initializing the new one. */ - static void dangerouslyReset(); + RN_EXPORT static void dangerouslyReset(); private: ReactNativeFeatureFlags() = delete; diff --git a/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativeFeatureFlags.h-template.js b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativeFeatureFlags.h-template.js index 5e6e896560e637..4397942cc45c6f 100644 --- a/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativeFeatureFlags.h-template.js +++ b/packages/react-native/scripts/featureflags/templates/common-cxx/ReactNativeFeatureFlags.h-template.js @@ -31,6 +31,10 @@ ${DO_NOT_MODIFY_COMMENT} #include #include +#ifndef RN_EXPORT +#define RN_EXPORT __attribute__((visibility("default"))) +#endif + namespace facebook::react { /** @@ -47,7 +51,7 @@ ${Object.entries(definitions.common) ` /** * ${flagConfig.description} */ - static ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`, + RN_EXPORT static ${getCxxTypeFromDefaultValue(flagConfig.defaultValue)} ${flagName}();`, ) .join('\n\n')} @@ -69,7 +73,7 @@ ${Object.entries(definitions.common) * std::make_unique()); * \`\`\` */ - static void override( + RN_EXPORT static void override( std::unique_ptr provider); /** @@ -84,7 +88,7 @@ ${Object.entries(definitions.common) * call \`dangerouslyReset\` after destroying the runtime and \`override\` again * before initializing the new one. */ - static void dangerouslyReset(); + RN_EXPORT static void dangerouslyReset(); private: ReactNativeFeatureFlags() = delete; From ff03b149e76982096be3ca4f3aea9a30c463ccec Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Thu, 7 Mar 2024 09:19:09 -0800 Subject: [PATCH 114/361] Use fs.cpSync instead of execSync('cp ... (#43368) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43368 This diff replaces direct invocation of the `cp` command with the platform agnostic `fs.cpSync`. Changelog: [Internal] Reviewed By: huntie Differential Revision: D54634108 fbshipit-source-id: 41fe7b44b6534026ef1b930da85725bf3eb1e7bb --- .../scripts/codegen/generate-artifacts-executor.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/react-native/scripts/codegen/generate-artifacts-executor.js b/packages/react-native/scripts/codegen/generate-artifacts-executor.js index 271a66e093dee6..df3c1e6ac0306d 100644 --- a/packages/react-native/scripts/codegen/generate-artifacts-executor.js +++ b/packages/react-native/scripts/codegen/generate-artifacts-executor.js @@ -465,8 +465,7 @@ function generateCode(outputPath, schemaInfo, includesGeneratedCode, platform) { const outputDir = reactNativeCoreLibraryOutputPath(libraryName, platform) ?? outputPath; fs.mkdirSync(outputDir, {recursive: true}); - // TODO: Fix this. This will not work on Windows. - execSync(`cp -R ${tmpOutputDir}/* "${outputDir}"`); + fs.cpSync(tmpOutputDir, outputDir, {recursive: true}); console.log(`[Codegen] Generated artifacts: ${outputDir}`); } From 9b1c486e40f1a002626cb3cb16b12d1e7f0a2c4c Mon Sep 17 00:00:00 2001 From: "Alex Taylor (alta)" Date: Thu, 7 Mar 2024 15:27:50 -0800 Subject: [PATCH 115/361] Deploy 0.230.0 to xplat (#43373) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43373 Changelog: [Internal] Reviewed By: pieterv Differential Revision: D54640661 fbshipit-source-id: 6d09ec126ea55bbe0d7a6b3a2823b1a0ffef7d21 --- .flowconfig | 2 +- package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.flowconfig b/.flowconfig index a5708732741628..bebab54962e4f1 100644 --- a/.flowconfig +++ b/.flowconfig @@ -85,4 +85,4 @@ untyped-import untyped-type-import [version] -^0.229.2 +^0.230.0 diff --git a/package.json b/package.json index 1b5e63d46e3a40..44779411e7373f 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", "flow-api-translator": "0.20.1", - "flow-bin": "^0.229.2", + "flow-bin": "^0.230.0", "glob": "^7.1.1", "hermes-eslint": "0.20.1", "hermes-transform": "0.20.1", diff --git a/yarn.lock b/yarn.lock index f702dabecf3a7e..f42a55b4d49a08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5150,10 +5150,10 @@ flow-api-translator@0.20.1: hermes-parser "0.20.1" hermes-transform "0.20.1" -flow-bin@^0.229.2: - version "0.229.2" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.229.2.tgz#6ce5575c8d6fe93390430f9e13da4c06a9a250f4" - integrity sha512-4hjnaApj/BUhosbStw9Tqk0Muf3WCxAnauPOEHvxIfvHWBHJH3wPCCWryPkLPoifjvvcRYYEKPNWHrYF3PkErA== +flow-bin@^0.230.0: + version "0.230.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.230.0.tgz#eefb67215270ab144cd1fa0203061d1687d1cfa6" + integrity sha512-Yx/AnKXR+D4Ieb7xlanfe7cNamJEsuXG6RLWCOl7OSzehMDmrZUuGh2Ycvf4tCKdM1nYt2569p3kkNELiBonaw== flow-enums-runtime@^0.0.6: version "0.0.6" From 2d547a3252b328251e49dabfeec85f8d46c85411 Mon Sep 17 00:00:00 2001 From: Vojtech Novak Date: Thu, 7 Mar 2024 18:05:34 -0800 Subject: [PATCH 116/361] feat: RCTConvert to support UIModalPresentationStyle (#43297) Summary: Currently, the ability to convert JS values to `UIModalPresentationStyle` is not present directly on `RCTConvert`. In the RN code base itself, there's not a lot of need to do this type of conversion, but in community modules, presenting ViewControllers can be a fairly common scenario and it'd be nice to be able to use this conversion directly from `RCTConvert`, rather than from `RCTModalHostViewManager`, as it'd improve its "discoverability" and consistency. If someone relied on this, then it's technically speaking a breaking change but I'd say it's for the better, and searching `#import ` on github doesn't reveal a lot of results. ## Changelog: [IOS] [ADDED] - RCTConvert to support UIModalPresentationStyle For more details, see: https://reactnative.dev/contributing/changelogs-in-pull-requests Pull Request resolved: https://github.com/facebook/react-native/pull/43297 Test Plan: Tested using RN Tester https://github.com/facebook/react-native/assets/1566403/6e62df86-dde3-47b0-b2e9-bb6b483cadf6 Reviewed By: fkgozali Differential Revision: D54635896 Pulled By: dmytrorykun fbshipit-source-id: c6747857830762cd0333c31c287954f3f10d4954 --- packages/react-native/React/Base/RCTConvert.h | 1 + packages/react-native/React/Base/RCTConvert.mm | 11 +++++++++++ .../React/Views/RCTModalHostViewManager.h | 6 ------ .../React/Views/RCTModalHostViewManager.m | 15 --------------- 4 files changed, 12 insertions(+), 21 deletions(-) diff --git a/packages/react-native/React/Base/RCTConvert.h b/packages/react-native/React/Base/RCTConvert.h index 8b819fda89e602..8e8a847f6fc414 100644 --- a/packages/react-native/React/Base/RCTConvert.h +++ b/packages/react-native/React/Base/RCTConvert.h @@ -80,6 +80,7 @@ typedef NSURL RCTFileURL; + (UIReturnKeyType)UIReturnKeyType:(id)json; + (UIUserInterfaceStyle)UIUserInterfaceStyle:(id)json API_AVAILABLE(ios(12)); + (UIInterfaceOrientationMask)UIInterfaceOrientationMask:(NSString *)orientation; ++ (UIModalPresentationStyle)UIModalPresentationStyle:(id)json; #if !TARGET_OS_TV + (UIDataDetectorTypes)UIDataDetectorTypes:(id)json; diff --git a/packages/react-native/React/Base/RCTConvert.mm b/packages/react-native/React/Base/RCTConvert.mm index fb5e43c6d2edff..c4b15a1df20b52 100644 --- a/packages/react-native/React/Base/RCTConvert.mm +++ b/packages/react-native/React/Base/RCTConvert.mm @@ -510,6 +510,17 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC NSNotFound, unsignedIntegerValue) +RCT_ENUM_CONVERTER( + UIModalPresentationStyle, + (@{ + @"fullScreen" : @(UIModalPresentationFullScreen), + @"pageSheet" : @(UIModalPresentationPageSheet), + @"formSheet" : @(UIModalPresentationFormSheet), + @"overFullScreen" : @(UIModalPresentationOverFullScreen), + }), + UIModalPresentationFullScreen, + integerValue) + RCT_ENUM_CONVERTER( UIViewContentMode, (@{ diff --git a/packages/react-native/React/Views/RCTModalHostViewManager.h b/packages/react-native/React/Views/RCTModalHostViewManager.h index 11b52984b30834..d2694ea26fd186 100644 --- a/packages/react-native/React/Views/RCTModalHostViewManager.h +++ b/packages/react-native/React/Views/RCTModalHostViewManager.h @@ -9,12 +9,6 @@ #import #import -@interface RCTConvert (RCTModalHostView) - -+ (UIModalPresentationStyle)UIModalPresentationStyle:(id)json; - -@end - typedef void (^RCTModalViewInteractionBlock)( UIViewController *reactViewController, UIViewController *viewController, diff --git a/packages/react-native/React/Views/RCTModalHostViewManager.m b/packages/react-native/React/Views/RCTModalHostViewManager.m index b0295e05ae4d54..eccf05f9cb6795 100644 --- a/packages/react-native/React/Views/RCTModalHostViewManager.m +++ b/packages/react-native/React/Views/RCTModalHostViewManager.m @@ -14,21 +14,6 @@ #import "RCTShadowView.h" #import "RCTUtils.h" -@implementation RCTConvert (RCTModalHostView) - -RCT_ENUM_CONVERTER( - UIModalPresentationStyle, - (@{ - @"fullScreen" : @(UIModalPresentationFullScreen), - @"pageSheet" : @(UIModalPresentationPageSheet), - @"formSheet" : @(UIModalPresentationFormSheet), - @"overFullScreen" : @(UIModalPresentationOverFullScreen), - }), - UIModalPresentationFullScreen, - integerValue) - -@end - @interface RCTModalHostShadowView : RCTShadowView @end From adaf5eba3e8381d0b499257ab04d30d6f3fb4c93 Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Thu, 7 Mar 2024 23:15:55 -0800 Subject: [PATCH 117/361] Fix component stacks for tsx, ts, and jsx files (#43370) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43370 Component stacks with files ending in .ts, .tsx, or .jsx were skipped in LogBox reporting. This diff fixes the regex. Changelog: [General][Fixed] - Support .tsx, .ts, and .jsx in component stacks Reviewed By: yungsters Differential Revision: D54638526 fbshipit-source-id: a5271daaa7b687e8e075be3f94ab9b9c03f79b66 --- .../Data/__tests__/parseLogBoxLog-test.js | 48 +++++++++++++++++++ .../Libraries/LogBox/Data/parseLogBoxLog.js | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js index e2773b28d738bd..9d98a9d29c4459 100644 --- a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js +++ b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js @@ -1287,6 +1287,54 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, }); }); + it('detects a component stack for ts, tsx, jsx, and js files', () => { + expect( + parseLogBoxLog([ + 'Some kind of message\n in MyTSComponent (at MyTSXComponent.ts:1)\n in MyTSXComponent (at MyTSCComponent.tsx:1)\n in MyJSXComponent (at MyJSXComponent.jsx:1)\n in MyJSComponent (at MyJSComponent.js:1)', + ]), + ).toEqual({ + componentStack: [ + { + content: 'MyTSComponent', + fileName: 'MyTSXComponent.ts', + location: { + column: -1, + row: 1, + }, + }, + { + content: 'MyTSXComponent', + fileName: 'MyTSCComponent.tsx', + location: { + column: -1, + row: 1, + }, + }, + { + content: 'MyJSXComponent', + fileName: 'MyJSXComponent.jsx', + location: { + column: -1, + row: 1, + }, + }, + { + content: 'MyJSComponent', + fileName: 'MyJSComponent.js', + location: { + column: -1, + row: 1, + }, + }, + ], + category: 'Some kind of message', + message: { + content: 'Some kind of message', + substitutions: [], + }, + }); + }); + it('detects a component stack in the first argument (JSC)', () => { expect( parseLogBoxLog([ diff --git a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js index f72d1227170823..84828adb6ab7ad 100644 --- a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js @@ -192,7 +192,7 @@ export function parseComponentStack(message: string): ComponentStack { if (!s) { return null; } - const match = s.match(/(.*) \(at (.*\.js):([\d]+)\)/); + const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/); if (match) { let [content, fileName, row] = match.slice(1); return { From ed32b4ba0aab96edc3237b65c7a3a9a0bd148cb1 Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Thu, 7 Mar 2024 23:15:55 -0800 Subject: [PATCH 118/361] Organize component stack regexes better (#43371) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43371 This file has a lot of regexes, let's organize and comment them all. Changelog: [Internal] Reviewed By: yungsters Differential Revision: D54638520 fbshipit-source-id: eed61133758ccefd2a640f121c4da214bcad4880 --- .../Libraries/LogBox/Data/parseLogBoxLog.js | 89 ++++++++++++++----- 1 file changed, 68 insertions(+), 21 deletions(-) diff --git a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js index 84828adb6ab7ad..c4dad211746088 100644 --- a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js @@ -18,11 +18,62 @@ import ansiRegex from 'ansi-regex'; const ANSI_REGEX = ansiRegex().source; -const BABEL_TRANSFORM_ERROR_FORMAT = +const RE_TRANSFORM_ERROR = /^TransformError /; +const RE_COMPONENT_STACK_LINE = /\n {4}(in|at) /; +const RE_COMPONENT_STACK_LINE_GLOBAL = /\n {4}(in|at) /g; +const RE_COMPONENT_STACK_LINE_OLD = / {4}in/; +const RE_COMPONENT_STACK_LINE_NEW = / {4}at/; +const RE_COMPONENT_STACK_LINE_STACK_FRAME = /@.*\n/; + +// "TransformError " (Optional) and either "SyntaxError: " or "ReferenceError: " +// Capturing groups: +// 1: error message +// 2: file path +// 3: line number +// 4: column number +// \n\n +// 5: code frame +const RE_BABEL_TRANSFORM_ERROR_FORMAT = /^(?:TransformError )?(?:SyntaxError: |ReferenceError: )(.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/; +// Capturing groups: +// 1: component name +// "at" +// 2: file path including extension +// 3: line number +const RE_COMPONENT_STACK_WITH_SOURCE = + /(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/; + +// Capturing groups: +// 1: component name +// "at" +// 2: parent component name +const RE_COMPONENT_STACK_NO_SOURCE = /(.*) \(created by .*\)/; + +// Capturing groups: +// - non-capturing "TransformError " (optional) +// - non-capturing Error message +// 1: file path +// 2: file name +// 3: error message +// 4: code frame, which includes code snippet indicators or terminal escape sequences for formatting. +const RE_BABEL_CODE_FRAME_ERROR_FORMAT = + // eslint-disable-next-line no-control-regex + /^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u; + +// Capturing groups: +// - non-capturing "InternalError Metro has encountered an error:" +// 1: error title +// 2: error message +// 3: file path +// 4: line number +// 5: column number +// 6: code frame, which includes code snippet indicators or terminal escape sequences for formatting. +const RE_METRO_ERROR_FORMAT = + /^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u; + // https://github.com/babel/babel/blob/33dbb85e9e9fe36915273080ecc42aee62ed0ade/packages/babel-code-frame/src/index.ts#L183-L184 -const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp( +const RE_BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp( [ // Beginning of a line (per 'm' flag) '^', @@ -42,13 +93,6 @@ const BABEL_CODE_FRAME_MARKER_PATTERN = new RegExp( 'm', ); -const BABEL_CODE_FRAME_ERROR_FORMAT = - // eslint-disable-next-line no-control-regex - /^(?:TransformError )?(?:.*):? (?:.*?)(\/.*): ([\s\S]+?)\n([ >]{2}[\d\s]+ \|[\s\S]+|\u{001b}[\s\S]+)/u; - -const METRO_ERROR_FORMAT = - /^(?:InternalError Metro has encountered an error:) (.*): (.*) \((\d+):(\d+)\)\n\n([\s\S]+)/u; - export type ExtendedExceptionData = ExceptionData & { isComponentError: boolean, ... @@ -158,9 +202,12 @@ export function parseInterpolation(args: $ReadOnlyArray): $ReadOnly<{| } function isComponentStack(consoleArgument: string) { - const isOldComponentStackFormat = / {4}in/.test(consoleArgument); - const isNewComponentStackFormat = / {4}at/.test(consoleArgument); - const isNewJSCComponentStackFormat = /@.*\n/.test(consoleArgument); + const isOldComponentStackFormat = + RE_COMPONENT_STACK_LINE_OLD.test(consoleArgument); + const isNewComponentStackFormat = + RE_COMPONENT_STACK_LINE_NEW.test(consoleArgument); + const isNewJSCComponentStackFormat = + RE_COMPONENT_STACK_LINE_STACK_FRAME.test(consoleArgument); return ( isOldComponentStackFormat || @@ -187,12 +234,12 @@ export function parseComponentStack(message: string): ComponentStack { } return message - .split(/\n {4}in /g) + .split(RE_COMPONENT_STACK_LINE_GLOBAL) .map(s => { if (!s) { return null; } - const match = s.match(/(.*) \(at (.*\.(?:js|jsx|ts|tsx)):([\d]+)\)/); + const match = s.match(RE_COMPONENT_STACK_WITH_SOURCE); if (match) { let [content, fileName, row] = match.slice(1); return { @@ -203,7 +250,7 @@ export function parseComponentStack(message: string): ComponentStack { } // In some cases, the component stack doesn't have a source. - const matchWithoutSource = s.match(/(.*) \(created by .*\)/); + const matchWithoutSource = s.match(RE_COMPONENT_STACK_NO_SOURCE); if (matchWithoutSource) { return { content: matchWithoutSource[1], @@ -223,7 +270,7 @@ export function parseLogBoxException( const message = error.originalMessage != null ? error.originalMessage : 'Unknown'; - const metroInternalError = message.match(METRO_ERROR_FORMAT); + const metroInternalError = message.match(RE_METRO_ERROR_FORMAT); if (metroInternalError) { const [content, fileName, row, column, codeFrame] = metroInternalError.slice(1); @@ -251,7 +298,7 @@ export function parseLogBoxException( }; } - const babelTransformError = message.match(BABEL_TRANSFORM_ERROR_FORMAT); + const babelTransformError = message.match(RE_BABEL_TRANSFORM_ERROR_FORMAT); if (babelTransformError) { // Transform errors are thrown from inside the Babel transformer. const [fileName, content, row, column, codeFrame] = @@ -281,8 +328,8 @@ export function parseLogBoxException( // Perform a cheap match first before trying to parse the full message, which // can get expensive for arbitrary input. - if (BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) { - const babelCodeFrameError = message.match(BABEL_CODE_FRAME_ERROR_FORMAT); + if (RE_BABEL_CODE_FRAME_MARKER_PATTERN.test(message)) { + const babelCodeFrameError = message.match(RE_BABEL_CODE_FRAME_ERROR_FORMAT); if (babelCodeFrameError) { // Codeframe errors are thrown from any use of buildCodeFrameError. @@ -307,7 +354,7 @@ export function parseLogBoxException( } } - if (message.match(/^TransformError /)) { + if (message.match(RE_TRANSFORM_ERROR)) { return { level: 'syntax', stack: error.stack, @@ -386,7 +433,7 @@ export function parseLogBoxLog(args: $ReadOnlyArray): {| for (const arg of args) { if (typeof arg === 'string' && isComponentStack(arg)) { // Strip out any messages before the component stack. - let messageEndIndex = arg.search(/\n {4}(in|at) /); + let messageEndIndex = arg.search(RE_COMPONENT_STACK_LINE); if (messageEndIndex < 0) { // Handle JSC component stacks. messageEndIndex = arg.search(/\n/); From 5126bace656e1fb1c7455c0b00ae1d5ec4b77b9a Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Thu, 7 Mar 2024 23:19:27 -0800 Subject: [PATCH 119/361] Fix VirtualizedList-test.js (#43377) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43377 Fixes `VirtualizedList-test.js`, which assumes fake timers (e.g. using `jest.runAllTimers()` and `jest.runOnlyPendingTimers()`) but did not actually use fake timers. Changelog: [Internal] Reviewed By: yungsters Differential Revision: D54668281 fbshipit-source-id: b14757744bb7a21a4e5573053549c36178826021 --- .../virtualized-lists/Lists/__tests__/VirtualizedList-test.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js b/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js index 774a2473556bc1..b40a7d885c5868 100644 --- a/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js +++ b/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js @@ -14,6 +14,8 @@ import VirtualizedList from '../VirtualizedList'; import React from 'react'; import ReactTestRenderer from 'react-test-renderer'; +jest.useFakeTimers(); + describe('VirtualizedList', () => { it('renders simple list', () => { const component = ReactTestRenderer.create( From 6bc95b2074a794607a34eae201f07dae110c2832 Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Fri, 8 Mar 2024 02:30:17 -0800 Subject: [PATCH 120/361] Add registerCallableModule types (#43366) Summary: `registerCallableModule()` was added from 7f549ec7bebe but no typescript types there. this pr tries to add the corresponding types. ## Changelog: [GENERAL] [FIXED] - Add missing `registerCallableModule` TypeScript definitions Pull Request resolved: https://github.com/facebook/react-native/pull/43366 Test Plan: patch locally and try to `import { registerCallableModule } from 'react-native';` in a 0.74.0-rc.2 project Reviewed By: fabriziocucci Differential Revision: D54676151 Pulled By: cortinico fbshipit-source-id: cd01f2ebe2d2516b458fae5b2e83cba3d3794455 --- .../Libraries/Core/registerCallableModule.d.ts | 16 ++++++++++++++++ packages/react-native/types/index.d.ts | 1 + 2 files changed, 17 insertions(+) create mode 100644 packages/react-native/Libraries/Core/registerCallableModule.d.ts diff --git a/packages/react-native/Libraries/Core/registerCallableModule.d.ts b/packages/react-native/Libraries/Core/registerCallableModule.d.ts new file mode 100644 index 00000000000000..05d9e92da7c717 --- /dev/null +++ b/packages/react-native/Libraries/Core/registerCallableModule.d.ts @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @format + */ + +type Module = Object; +type RegisterCallableModule = ( + name: string, + moduleOrFactory: Module | (() => Module), +) => void; + +export const registerCallableModule: RegisterCallableModule; diff --git a/packages/react-native/types/index.d.ts b/packages/react-native/types/index.d.ts index b23e2e0a2ff267..5aeec0685ed009 100644 --- a/packages/react-native/types/index.d.ts +++ b/packages/react-native/types/index.d.ts @@ -103,6 +103,7 @@ export * from '../Libraries/Components/View/View'; export * from '../Libraries/Components/View/ViewAccessibility'; export * from '../Libraries/Components/View/ViewPropTypes'; export * from '../Libraries/Components/Button'; +export * from '../Libraries/Core/registerCallableModule'; export * from '../Libraries/DevToolsSettings/DevToolsSettingsManager'; export * from '../Libraries/EventEmitter/NativeEventEmitter'; export * from '../Libraries/EventEmitter/RCTDeviceEventEmitter'; From 642b4e5c2c80b6f46429b41f36489eb81ac8a06e Mon Sep 17 00:00:00 2001 From: Tomek Zawadzki Date: Fri, 8 Mar 2024 04:32:44 -0800 Subject: [PATCH 121/361] Expose `react_render_textlayoutmanager` via prefab (#43381) Summary: The `react_render_textlayoutmanager` was not exposed via prefab. I'm adding it to make possible for react-native-live-markdown to integrate on top of React Native via prefab. Based on https://github.com/facebook/react-native/issues/36166. ## Changelog: [ANDROID] [CHANGED] - Expose `react_render_textlayoutmanager` via prefab. Pull Request resolved: https://github.com/facebook/react-native/pull/43381 Reviewed By: javache Differential Revision: D54676207 Pulled By: cortinico fbshipit-source-id: 90e3b90ff842250bf1e3abcc0c54f057b68a82fd --- packages/react-native/ReactAndroid/build.gradle.kts | 12 ++++++++++++ .../cmake-utils/ReactNative-application.cmake | 2 ++ 2 files changed, 14 insertions(+) diff --git a/packages/react-native/ReactAndroid/build.gradle.kts b/packages/react-native/ReactAndroid/build.gradle.kts index 9b948515926704..0c7d24db69ec6e 100644 --- a/packages/react-native/ReactAndroid/build.gradle.kts +++ b/packages/react-native/ReactAndroid/build.gradle.kts @@ -148,6 +148,14 @@ val preparePrefab by PrefabPreprocessingEntry( "react_render_mapbuffer", Pair("../ReactCommon/react/renderer/mapbuffer/", "react/renderer/mapbuffer/")), + PrefabPreprocessingEntry( + "react_render_textlayoutmanager", + listOf( + Pair( + "../ReactCommon/react/renderer/textlayoutmanager/", + "react/renderer/textlayoutmanager/"), + Pair("../ReactCommon/react/renderer/textlayoutmanager/platform/android/", ""), + )), PrefabPreprocessingEntry( "yoga", listOf( @@ -556,6 +564,7 @@ android { "glog", "fabricjni", "react_render_mapbuffer", + "react_render_textlayoutmanager", "yoga", "folly_runtime", "react_nativemodule_core", @@ -686,6 +695,9 @@ android { create("react_render_mapbuffer") { headers = File(prefabHeadersDir, "react_render_mapbuffer").absolutePath } + create("react_render_textlayoutmanager") { + headers = File(prefabHeadersDir, "react_render_textlayoutmanager").absolutePath + } create("yoga") { headers = File(prefabHeadersDir, "yoga").absolutePath } create("folly_runtime") { headers = File(prefabHeadersDir, "folly_runtime").absolutePath } create("react_nativemodule_core") { diff --git a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake index 0a1c9197a954e5..e2efc266ca0f68 100644 --- a/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake +++ b/packages/react-native/ReactAndroid/cmake-utils/ReactNative-application.cmake @@ -80,6 +80,7 @@ add_library(jsi ALIAS ReactAndroid::jsi) add_library(glog ALIAS ReactAndroid::glog) add_library(fabricjni ALIAS ReactAndroid::fabricjni) add_library(react_render_mapbuffer ALIAS ReactAndroid::react_render_mapbuffer) +add_library(react_render_textlayoutmanager ALIAS ReactAndroid::react_render_textlayoutmanager) add_library(yoga ALIAS ReactAndroid::yoga) add_library(folly_runtime ALIAS ReactAndroid::folly_runtime) add_library(react_nativemodule_core ALIAS ReactAndroid::react_nativemodule_core) @@ -108,6 +109,7 @@ target_link_libraries(${CMAKE_PROJECT_NAME} react_render_graphics # prefab ready react_render_imagemanager # prefab ready react_render_mapbuffer # prefab ready + react_render_textlayoutmanager # prefab ready rrc_image # prefab ready rrc_view # prefab ready rrc_text # prefab ready From 4adef35e97f31db466e536aa21d5eeec6ee34fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Fri, 8 Mar 2024 04:53:42 -0800 Subject: [PATCH 122/361] fix(iOS) [0.74]: RCTRedBox not appearing in Bridgeless when metro is not running (#43147) Summary: When testing out `0.74.0-rc0` I found that when the metro is not running we are not displaying RedBox which bumps users to start the packager and reload the app. It also fixes the case where users try to reload by clicking the "Reload" button on RedBox. ## Before https://github.com/facebook/react-native/assets/52801365/086c557f-ea1f-4a97-b4c7-df8a945cc7a0 ## After https://github.com/facebook/react-native/assets/52801365/9f8421b3-5e83-466f-8cdb-38f97981275d ## Changelog: [IOS] [FIXED] - RCTRedBox not appearing in Bridgeless when metro is not running Pull Request resolved: https://github.com/facebook/react-native/pull/43147 Test Plan: Build the app without metro running check if RedBox is shown Reviewed By: javache Differential Revision: D54632056 Pulled By: dmytrorykun fbshipit-source-id: fb6742898d3bd82545bfffd9175208e1a5984cb6 --- .../React/CoreModules/RCTRedBox.mm | 8 +++- .../platform/ios/ReactCommon/RCTInstance.mm | 43 ++++++++++++++++--- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/packages/react-native/React/CoreModules/RCTRedBox.mm b/packages/react-native/React/CoreModules/RCTRedBox.mm index 822e17ab570baf..15cf2f023aaa4c 100644 --- a/packages/react-native/React/CoreModules/RCTRedBox.mm +++ b/packages/react-native/React/CoreModules/RCTRedBox.mm @@ -274,7 +274,13 @@ - (void)dismiss - (void)reload { - [_actionDelegate reloadFromRedBoxController:self]; + if (_actionDelegate != nil) { + [_actionDelegate reloadFromRedBoxController:self]; + } else { + // In bridgeless mode `RCTRedBox` gets deallocated, we need to notify listeners anyway. + RCTTriggerReloadCommandListeners(@"Redbox"); + [self dismiss]; + } } - (void)showExtraDataViewController diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 6b9f987123c53d..38f17f96129091 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -28,6 +28,8 @@ #import #import #import +#import +#import #import #import #import @@ -122,10 +124,17 @@ - (instancetype)initWithDelegate:(id)delegate }]; } - [[NSNotificationCenter defaultCenter] addObserver:self - selector:@selector(_notifyEventDispatcherObserversOfEvent_DEPRECATED:) - name:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED" - object:nil]; + NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter]; + + [defaultCenter addObserver:self + selector:@selector(_notifyEventDispatcherObserversOfEvent_DEPRECATED:) + name:@"RCTNotifyEventDispatcherObserversOfEvent_DEPRECATED" + object:nil]; + + [defaultCenter addObserver:self + selector:@selector(didReceiveReloadCommand) + name:RCTTriggerReloadCommandNotification + object:nil]; [self _start]; } @@ -389,6 +398,24 @@ - (void)_attachBridgelessAPIsToModule:(id)module } } +- (void)handleBundleLoadingError:(NSError *)error +{ + if (!_valid) { + return; + } + + RCTRedBox *redBox = [_turboModuleManager moduleForName:"RedBox"]; + + RCTExecuteOnMainQueue(^{ + [[NSNotificationCenter defaultCenter] postNotificationName:RCTJavaScriptDidFailToLoadNotification + object:self + userInfo:@{@"error" : error}]; + [redBox showErrorMessage:[error localizedDescription]]; + + RCTFatal(error); + }); +} + - (void)_loadJSBundle:(NSURL *)sourceURL { #if RCT_DEV_MENU && __has_include() @@ -420,8 +447,7 @@ - (void)_loadJSBundle:(NSURL *)sourceURL } if (error) { - // TODO(T91461138): Properly address bundle loading errors. - RCTLogError(@"RCTInstance: Error while loading bundle: %@", error); + [strongSelf handleBundleLoadingError:error]; [strongSelf invalidate]; return; } @@ -490,4 +516,9 @@ - (void)_handleJSErrorMap:(facebook::react::MapBuffer)errorMap isFatal:errorMap.getBool(JSErrorHandlerKey::kIsFatal)]; } +- (void)didReceiveReloadCommand +{ + [self _loadJSBundle:[_bridgeModuleDecorator.bundleManager bundleURL]]; +} + @end From da913236ab2ec1b043a5a067aa0e958b8b294762 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Fri, 8 Mar 2024 06:48:58 -0800 Subject: [PATCH 123/361] add missing synchronisation call for native animated (#43374) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43374 changelog: [internal] when animation that uses native driver finishes, it must synchronise the end state with shadow tree. `onUpdateRef` for native animated is only called when the animation finishes. Reviewed By: javache, yungsters Differential Revision: D54582987 fbshipit-source-id: 4320ed172b8bb4b22f82c6e24b47f88f1603e4fb --- .../Libraries/Animated/useAnimatedProps.js | 72 +++++++++++-------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/packages/react-native/Libraries/Animated/useAnimatedProps.js b/packages/react-native/Libraries/Animated/useAnimatedProps.js index 6be9fac9cd86cf..51196426ec2234 100644 --- a/packages/react-native/Libraries/Animated/useAnimatedProps.js +++ b/packages/react-native/Libraries/Animated/useAnimatedProps.js @@ -74,40 +74,56 @@ export default function useAnimatedProps( // every animation frame. When using the native driver, this callback is // called when the animation completes. onUpdateRef.current = () => { + if (node.__isNative || process.env.NODE_ENV === 'test') { + // Check 1: either tests are running or this is a native driven animation. + // In native driven animations, this callback is only called once the animation completes. + // Call `scheduleUpdate` to synchronise Fiber and Shadow tree. + return scheduleUpdate(); + } + if ( - process.env.NODE_ENV === 'test' || typeof instance !== 'object' || - typeof instance?.setNativeProps !== 'function' || - (isFabricInstance(instance) && !useNativePropsInFabric) + typeof instance?.setNativeProps !== 'function' ) { - // Schedule an update for this component to update `reducedProps`, - // but do not compute it immediately. If a parent also updated, we - // need to merge those new props in before updating. - scheduleUpdate(); - } else if (!node.__isNative) { + // Check 2: the instance does not support setNativeProps. Call `scheduleUpdate`. + return scheduleUpdate(); + } + + if (!isFabricInstance(instance)) { + // Check 3: this is a paper instance, call setNativeProps. // $FlowIgnore[not-a-function] - Assume it's still a function. // $FlowFixMe[incompatible-use] - instance.setNativeProps(node.__getAnimatedValue()); - if (isFabricInstance(instance)) { - // Keeping state of Fiber tree and Shadow tree in sync. - // - // This is done by calling `scheduleUpdate` which will trigger a commit. - // However, React commit is not fast enough to drive animations. - // This is where setNativeProps comes in handy but the state between - // Fiber tree and Shadow tree needs to be kept in sync. - // The goal is to call `scheduleUpdate` as little as possible to maintain - // performance but frequently enough to keep state in sync. - // Debounce is set to 48ms, which is 3 * the duration of a frame. - // 3 frames was the highest value where flickering state was not observed. - if (timerRef.current != null) { - clearTimeout(timerRef.current); - } - timerRef.current = setTimeout(() => { - timerRef.current = null; - scheduleUpdate(); - }, 48); - } + return instance.setNativeProps(node.__getAnimatedValue()); } + + if (!useNativePropsInFabric) { + // Check 4: setNativeProps are disabled. + return scheduleUpdate(); + } + + // This is a Fabric instance and setNativeProps are supported. + + // $FlowIgnore[not-a-function] - Assume it's still a function. + // $FlowFixMe[incompatible-use] + instance.setNativeProps(node.__getAnimatedValue()); + + // Keeping state of Fiber tree and Shadow tree in sync. + // + // This is done by calling `scheduleUpdate` which will trigger a commit. + // However, React commit is not fast enough to drive animations. + // This is where setNativeProps comes in handy but the state between + // Fiber tree and Shadow tree needs to be kept in sync. + // The goal is to call `scheduleUpdate` as little as possible to maintain + // performance but frequently enough to keep state in sync. + // Debounce is set to 48ms, which is 3 * the duration of a frame. + // 3 frames was the highest value where flickering state was not observed. + if (timerRef.current != null) { + clearTimeout(timerRef.current); + } + timerRef.current = setTimeout(() => { + timerRef.current = null; + scheduleUpdate(); + }, 48); }; const target = getEventTarget(instance); From 5ed3057822dce98efe9ea7db731f3cf253fd8d56 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Fri, 8 Mar 2024 07:04:12 -0800 Subject: [PATCH 124/361] Make ReactActivityDelegate methods public (#43367) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43367 Enable `ReactActivityDelegate` to be used outside of `ReactActivity` as well. Changelog: [Internal] Reviewed By: arushikesarwani94 Differential Revision: D54634339 fbshipit-source-id: 977e0da689d5a827feca89a5dcc9416ad5178334 --- .../ReactAndroid/api/ReactAndroid.api | 8 +++---- .../facebook/react/ReactActivityDelegate.java | 21 ++++++++----------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index a296e9fb3d3e0a..8eadbcf684f539 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -121,15 +121,15 @@ public class com/facebook/react/ReactActivityDelegate { public fun onActivityResult (IILandroid/content/Intent;)V public fun onBackPressed ()Z public fun onConfigurationChanged (Landroid/content/res/Configuration;)V - protected fun onCreate (Landroid/os/Bundle;)V - protected fun onDestroy ()V + public fun onCreate (Landroid/os/Bundle;)V + public fun onDestroy ()V public fun onKeyDown (ILandroid/view/KeyEvent;)Z public fun onKeyLongPress (ILandroid/view/KeyEvent;)Z public fun onKeyUp (ILandroid/view/KeyEvent;)Z public fun onNewIntent (Landroid/content/Intent;)Z - protected fun onPause ()V + public fun onPause ()V public fun onRequestPermissionsResult (I[Ljava/lang/String;[I)V - protected fun onResume ()V + public fun onResume ()V public fun onWindowFocusChanged (Z)V public fun requestPermissions ([Ljava/lang/String;ILcom/facebook/react/modules/core/PermissionListener;)V } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 4bbaa82e06fe8b..b305b390945a4c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -96,7 +96,7 @@ public String getMainComponentName() { return mMainComponentName; } - protected void onCreate(Bundle savedInstanceState) { + public void onCreate(Bundle savedInstanceState) { String mainComponentName = getMainComponentName(); final Bundle launchOptions = composeLaunchOptions(); if (ReactFeatureFlags.enableBridgelessArchitecture) { @@ -122,11 +122,11 @@ protected void loadApp(String appKey) { getPlainActivity().setContentView(mReactDelegate.getReactRootView()); } - protected void onPause() { + public void onPause() { mReactDelegate.onHostPause(); } - protected void onResume() { + public void onResume() { mReactDelegate.onHostResume(); if (mPermissionsCallback != null) { @@ -135,7 +135,7 @@ protected void onResume() { } } - protected void onDestroy() { + public void onDestroy() { mReactDelegate.onHostDestroy(); } @@ -220,14 +220,11 @@ public void requestPermissions( public void onRequestPermissionsResult( final int requestCode, final String[] permissions, final int[] grantResults) { mPermissionsCallback = - new Callback() { - @Override - public void invoke(Object... args) { - if (mPermissionListener != null - && mPermissionListener.onRequestPermissionsResult( - requestCode, permissions, grantResults)) { - mPermissionListener = null; - } + args -> { + if (mPermissionListener != null + && mPermissionListener.onRequestPermissionsResult( + requestCode, permissions, grantResults)) { + mPermissionListener = null; } }; } From 52bd8418d8720f39772c67e589277a5c06a4340b Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 8 Mar 2024 07:29:22 -0800 Subject: [PATCH 125/361] Create InspectorFlagOverridesGuard util, substitute in tests (#43372) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43372 Create a shared `InspectorFlagOverridesGuard` util for our `jsinspector-modern` tests, update `ReactInstanceIntegrationTestWithFlags` to reuse this. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54639775 fbshipit-source-id: 9b23e4c05bcdbb8ebc2a02a6e69326eb749d1cfd --- .../tests/ReactInstanceIntegrationTest.cpp | 46 +++------------- .../tests/ReactInstanceIntegrationTest.h | 14 ++--- .../utils/InspectorFlagOverridesGuard.cpp | 52 +++++++++++++++++++ .../tests/utils/InspectorFlagOverridesGuard.h | 41 +++++++++++++++ 4 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp index e305713edbaff6..a945d692b9f8ee 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp @@ -21,44 +21,13 @@ namespace facebook::react::jsinspector_modern { using namespace ::testing; -class ReactInstanceIntegrationTestFeatureFlagsProvider - : public ReactNativeFeatureFlagsDefaults { - private: - FeatureFlags flags_; - - public: - explicit ReactInstanceIntegrationTestFeatureFlagsProvider( - FeatureFlags featureFlags) - : flags_(featureFlags) {} - - bool inspectorEnableModernCDPRegistry() override { - return flags_.enableModernCDPRegistry; - } - bool inspectorEnableCxxInspectorPackagerConnection() override { - return flags_.enableCxxInspectorPackagerConnection; - } -}; - ReactInstanceIntegrationTest::ReactInstanceIntegrationTest() : runtime(nullptr), instance(nullptr), messageQueueThread(std::make_shared()), - errorHandler(std::make_shared()), - featureFlags(std::make_unique()) {} + errorHandler(std::make_shared()) {} void ReactInstanceIntegrationTest::SetUp() { - ReactNativeFeatureFlags::override( - std::make_unique( - *featureFlags)); - // Reset InspectorFlags to overridden upstream values before creating objects - // that may access them. - InspectorFlags::getInstance().dangerouslyResetFlags(); - - // Double check that a flag matches our overrides. - ASSERT_EQ( - InspectorFlags::getInstance().getEnableModernCDPRegistry(), - featureFlags->enableModernCDPRegistry); - auto mockRegistry = std::make_unique(); auto timerManager = std::make_shared(std::move(mockRegistry)); @@ -83,7 +52,7 @@ void ReactInstanceIntegrationTest::SetUp() { std::shared_ptr hostTargetIfModernCDP = nullptr; - if (featureFlags->enableModernCDPRegistry) { + if (InspectorFlags::getInstance().getEnableModernCDPRegistry()) { VoidExecutor inspectorExecutor = [this](auto callback) { immediateExecutor_.add(callback); }; @@ -143,7 +112,8 @@ void ReactInstanceIntegrationTest::TearDown() { // Destroy the local connection. clientToVM_.reset(); - if (pageId_.has_value() && featureFlags->enableModernCDPRegistry) { + if (pageId_.has_value() && + InspectorFlags::getInstance().getEnableModernCDPRegistry()) { // Under modern CDP, clean up the page we added in SetUp and destroy // resources owned by HostTarget. getInspectorInstance().removePage(pageId_.value()); @@ -229,7 +199,7 @@ TEST_P(ReactInstanceIntegrationTestWithFlags, ConsoleLog) { // modern registry, and the runtime does not yet fire these events. When the // implementation is more complete we should be able to remove this // condition. - if (!featureFlags->enableModernCDPRegistry) { + if (!InspectorFlags::getInstance().getEnableModernCDPRegistry()) { EXPECT_CALL( getRemoteConnection(), onMessage(JsonParsed(AllOf( @@ -247,13 +217,13 @@ INSTANTIATE_TEST_SUITE_P( ReactInstanceVaryingInspectorFlags, ReactInstanceIntegrationTestWithFlags, ::testing::Values( - FeatureFlags{ + InspectorFlagOverrides{ .enableCxxInspectorPackagerConnection = true, .enableModernCDPRegistry = true}, - FeatureFlags{ + InspectorFlagOverrides{ .enableCxxInspectorPackagerConnection = false, .enableModernCDPRegistry = false}, - FeatureFlags{ + InspectorFlagOverrides{ .enableCxxInspectorPackagerConnection = true, .enableModernCDPRegistry = false})); diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h index 34710c6d5c9c52..e141d6925d4128 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.h @@ -10,6 +10,7 @@ #include "InspectorMocks.h" #include "ReactNativeMocks.h" #include "UniquePtrFactory.h" +#include "utils/InspectorFlagOverridesGuard.h" #include #include @@ -31,6 +32,7 @@ struct FeatureFlags { class ReactInstanceIntegrationTest : public Test { protected: ReactInstanceIntegrationTest(); + void SetUp() override; void TearDown() override; @@ -46,7 +48,6 @@ class ReactInstanceIntegrationTest : public Test { std::unique_ptr instance; std::shared_ptr messageQueueThread; std::shared_ptr errorHandler; - std::unique_ptr featureFlags; MockRemoteConnection& getRemoteConnection() { EXPECT_EQ(mockRemoteConnections_.objectsVended(), 1); @@ -68,10 +69,11 @@ class ReactInstanceIntegrationTest : public Test { class ReactInstanceIntegrationTestWithFlags : public ReactInstanceIntegrationTest, - public ::testing::WithParamInterface { - void SetUp() override { - featureFlags = std::make_unique(GetParam()); - ReactInstanceIntegrationTest::SetUp(); - } + public ::testing::WithParamInterface { + protected: + ReactInstanceIntegrationTestWithFlags() : inspectorFlagsGuard_(GetParam()) {} + + private: + InspectorFlagOverridesGuard inspectorFlagsGuard_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp new file mode 100644 index 00000000000000..aa1b87b8f57f10 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "InspectorFlagOverridesGuard.h" + +#include +#include +#include + +#include + +namespace facebook::react::jsinspector_modern { + +/** + * Helper class that maps \c InspectorFlagOverrides to the shape of \c + * ReactNativeFeatureFlagsDefaults. + */ +class ReactNativeFeatureFlagsOverrides + : public ReactNativeFeatureFlagsDefaults { + public: + explicit ReactNativeFeatureFlagsOverrides( + const InspectorFlagOverrides& overrides) + : overrides_(overrides) {} + + bool inspectorEnableCxxInspectorPackagerConnection() override { + return overrides_.enableCxxInspectorPackagerConnection; + } + + bool inspectorEnableModernCDPRegistry() override { + return overrides_.enableModernCDPRegistry; + } + + private: + InspectorFlagOverrides overrides_; +}; + +InspectorFlagOverridesGuard::InspectorFlagOverridesGuard( + const InspectorFlagOverrides& overrides) { + ReactNativeFeatureFlags::override( + std::make_unique(overrides)); +} + +InspectorFlagOverridesGuard::~InspectorFlagOverridesGuard() { + InspectorFlags::getInstance().dangerouslyResetFlags(); + ReactNativeFeatureFlags::dangerouslyReset(); +} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h new file mode 100644 index 00000000000000..4d7ad76b7e05cf --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook::react::jsinspector_modern { + +/** + * Overridden \c InspectorFlags values for use in tests. + */ +struct InspectorFlagOverrides { + // NOTE: Keep these entries in sync with ReactNativeFeatureFlagsOverrides in + // the implementation file. + bool enableCxxInspectorPackagerConnection = false; + bool enableModernCDPRegistry = false; +}; + +/** + * A RAII helper to set up and tear down \c InspectorFlags (via \c + * ReactNativeFeatureFlags) with overrides for the lifetime of a test object. + */ +class InspectorFlagOverridesGuard { + public: + explicit InspectorFlagOverridesGuard(const InspectorFlagOverrides& overrides); + InspectorFlagOverridesGuard(const InspectorFlagOverridesGuard&) = delete; + InspectorFlagOverridesGuard(InspectorFlagOverridesGuard&&) = default; + InspectorFlagOverridesGuard& operator=(const InspectorFlagOverridesGuard&) = + delete; + InspectorFlagOverridesGuard& operator=(InspectorFlagOverridesGuard&&) = + default; + + ~InspectorFlagOverridesGuard(); +}; + +} // namespace facebook::react::jsinspector_modern From 166fdc51250cf5033f59bc018552378e9687af15 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 8 Mar 2024 07:29:22 -0800 Subject: [PATCH 126/361] Create wrapper class for Hermes CDPAgent + CDPDebugAPI (#43352) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43352 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Adds the `HermesRuntimeAgentDelegateNew` class to provide a swap-in replacement for the existing `HermesRuntimeAgentDelegate` when we enable this via an incoming feature flag. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D53810356 fbshipit-source-id: c63684252230a747ecf0bd8cbb6f4e22052ed9bf --- .github/workflows/ios-tests.yml | 2 +- .../chrome/HermesRuntimeAgentDelegateNew.cpp | 132 ++++++++++++++++++ .../chrome/HermesRuntimeAgentDelegateNew.h | 75 ++++++++++ .../chrome/HermesRuntimeTargetDelegate.cpp | 26 ++++ .../chrome/HermesRuntimeTargetDelegate.h | 16 +++ .../sdks/hermes-engine/hermes-engine.podspec | 6 + .../utils/build-apple-framework.sh | 6 + 7 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp create mode 100644 packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h diff --git a/.github/workflows/ios-tests.yml b/.github/workflows/ios-tests.yml index 7677425ab0b235..cdfe1189593db7 100644 --- a/.github/workflows/ios-tests.yml +++ b/.github/workflows/ios-tests.yml @@ -36,7 +36,7 @@ jobs: uses: actions/cache@v3 with: path: packages/rn-tester/Pods - key: v1-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }} + key: v2-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }} - name: Pod Install run: | cd packages/rn-tester diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp new file mode 100644 index 00000000000000..429b7e69132edd --- /dev/null +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "HermesRuntimeAgentDelegateNew.h" + +// If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes +// CDP headers or types. + +#ifdef HERMES_ENABLE_DEBUGGER +#include +#include +#include +#else // HERMES_ENABLE_DEBUGGER +#include +#endif // HERMES_ENABLE_DEBUGGER + +#include +#include + +using namespace facebook::hermes; + +namespace facebook::react::jsinspector_modern { + +#ifdef HERMES_ENABLE_DEBUGGER + +class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { + public: + Impl( + FrontendChannel frontendChannel, + SessionState& /*unused*/, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription, + HermesRuntime& runtime, + HermesRuntimeTargetDelegate& runtimeTargetDelegate, + const RuntimeExecutor& runtimeExecutor) + : hermes_(hermes::cdp::CDPAgent::create( + executionContextDescription.id, + runtimeTargetDelegate.getCDPDebugAPI(), + // RuntimeTask takes a HermesRuntime whereas our RuntimeExecutor + // takes a jsi::Runtime. + [runtimeExecutor, + &runtime](facebook::hermes::debugger::RuntimeTask fn) { + runtimeExecutor( + [&runtime, fn = std::move(fn)](auto&) { fn(runtime); }); + }, + std::move(frontendChannel))) { + // TODO(T178858701): Pass previouslyExportedState to CDPAgent + (void)previouslyExportedState; + } + + /** + * Handle a CDP request. The response will be sent over the provided + * \c FrontendChannel synchronously or asynchronously. + * \param req The parsed request. + * \returns true if this agent has responded, or will respond asynchronously, + * to the request (with either a success or error message). False if the + * agent expects another agent to respond to the request instead. + */ + bool handleRequest(const cdp::PreparsedRequest& req) override { + // TODO: Change to string::starts_with when we're on C++20. + if (req.method.rfind("Log.", 0) == 0) { + // Since we know Hermes doesn't do anything useful with Log messages, but + // our containing PageAgent will, just bail out early. + // TODO: We need a way to negotiate this more dynamically with Hermes + // through the API. + return false; + } + // Forward everything else to Hermes's CDPAgent. + hermes_->handleCommand(req.toJson()); + // Let the call know that this request is handled (i.e. it is Hermes's + // responsibility to respond with either success or an error). + return true; + } + + private: + std::unique_ptr hermes_; +}; + +#else // !HERMES_ENABLE_DEBUGGER + +/** + * A stub for HermesRuntimeAgentDelegateNew when Hermes is compiled without + * debugging support. + */ +class HermesRuntimeAgentDelegateNew::Impl final + : public FallbackRuntimeAgentDelegate { + public: + Impl( + FrontendChannel frontendChannel, + SessionState& sessionState, + std::unique_ptr, + const ExecutionContextDescription&, + HermesRuntime& runtime, + HermesRuntimeTargetDelegate& runtimeTargetDelegate, + RuntimeExecutor) + : FallbackRuntimeAgentDelegate( + std::move(frontendChannel), + sessionState, + runtime.description()) {} +}; + +#endif // HERMES_ENABLE_DEBUGGER + +HermesRuntimeAgentDelegateNew::HermesRuntimeAgentDelegateNew( + FrontendChannel frontendChannel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription, + HermesRuntime& runtime, + HermesRuntimeTargetDelegate& runtimeTargetDelegate, + RuntimeExecutor runtimeExecutor) + : impl_(std::make_unique( + std::move(frontendChannel), + sessionState, + std::move(previouslyExportedState), + executionContextDescription, + runtime, + runtimeTargetDelegate, + std::move(runtimeExecutor))) {} + +bool HermesRuntimeAgentDelegateNew::handleRequest( + const cdp::PreparsedRequest& req) { + return impl_->handleRequest(req); +} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h new file mode 100644 index 00000000000000..2505451eb27deb --- /dev/null +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "HermesRuntimeTargetDelegate.h" + +#include +#include +#include + +namespace facebook::react::jsinspector_modern { + +/** + * A RuntimeAgentDelegate that handles requests from the Chrome DevTools + * Protocol for an instance of Hermes, using the new CDPAgent API. + */ +class HermesRuntimeAgentDelegateNew : public RuntimeAgentDelegate { + public: + /** + * \param frontendChannel A channel used to send responses and events to the + * frontend. + * \param sessionState The state of the current CDP session. This will only + * be accessed on the main thread (during the constructor, in handleRequest, + * etc). + * \param previouslyExportedState The exported state from a previous instance + * of RuntimeAgentDelegate (NOT necessarily HermesRuntimeAgentDelegateNew). + * This may be nullptr, and if not nullptr it may be of any concrete type that + * implements RuntimeAgentDelegate::ExportedState. + * \param executionContextDescription A description of the execution context + * represented by this runtime. This is used for disambiguating the + * source/destination of CDP messages when there are multiple runtimes + * (concurrently or over the life of a Page). + * \param runtime The HermesRuntime that this agent is attached to. The caller + * is responsible for keeping this object alive for the duration of the + * \c HermesRuntimeAgentDelegateNew lifetime. + * \param runtimeTargetDelegate The \c HermesRuntimeTargetDelegate object + * object for the passed runtime. + * \param runtimeExecutor A callback for scheduling work on the JS thread. + * \c runtimeExecutor may drop scheduled work if the runtime is destroyed + * first. + */ + HermesRuntimeAgentDelegateNew( + FrontendChannel frontendChannel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription, + hermes::HermesRuntime& runtime, + HermesRuntimeTargetDelegate& runtimeTargetDelegate, + RuntimeExecutor runtimeExecutor); + + /** + * Handle a CDP request. The response will be sent over the provided + * \c FrontendChannel synchronously or asynchronously. + * \param req The parsed request. + * \returns true if this agent has responded, or will respond asynchronously, + * to the request (with either a success or error message). False if the + * agent expects another agent to respond to the request instead. + */ + bool handleRequest(const cdp::PreparsedRequest& req) override; + + private: + // We use the private implementation idiom to keep HERMES_ENABLE_DEBUGGER + // checks out of the header. + class Impl; + + const std::unique_ptr impl_; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index 810d9f35af3810..c9f651d75c549c 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -8,6 +8,12 @@ #include "HermesRuntimeTargetDelegate.h" #include "HermesRuntimeAgentDelegate.h" +#ifdef HERMES_ENABLE_DEBUGGER +#include + +using namespace facebook::hermes::cdp; +#endif // HERMES_ENABLE_DEBUGGER + #include using namespace facebook::hermes; @@ -16,8 +22,18 @@ namespace facebook::react::jsinspector_modern { class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { public: +#ifdef HERMES_ENABLE_DEBUGGER + explicit Impl(std::shared_ptr hermesRuntime) + : runtime_(std::move(hermesRuntime)), + cdpDebugAPI_(CDPDebugAPI::create(*runtime_)) {} + + CDPDebugAPI& getCDPDebugAPI() { + return *cdpDebugAPI_; + } +#else explicit Impl(std::shared_ptr hermesRuntime) : runtime_(std::move(hermesRuntime)) {} +#endif // RuntimeTargetDelegate methods @@ -39,6 +55,10 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { private: std::shared_ptr runtime_; + +#ifdef HERMES_ENABLE_DEBUGGER + const std::unique_ptr cdpDebugAPI_; +#endif }; HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( @@ -63,4 +83,10 @@ HermesRuntimeTargetDelegate::createAgentDelegate( std::move(runtimeExecutor)); } +#ifdef HERMES_ENABLE_DEBUGGER +CDPDebugAPI& HermesRuntimeTargetDelegate::getCDPDebugAPI() { + return impl_->getCDPDebugAPI(); +} +#endif + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h index 08a4da81084c3a..2196568c09972c 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h @@ -13,6 +13,10 @@ #include #include +#ifdef HERMES_ENABLE_DEBUGGER +#include +#endif + #include namespace facebook::react::jsinspector_modern { @@ -42,8 +46,20 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { RuntimeExecutor runtimeExecutor) override; private: + // We use the private implementation idiom to ensure this class has the same + // layout regardless of whether HERMES_ENABLE_DEBUGGER is defined. The net + // effect is that callers can include HermesRuntimeTargetDelegate.h without + // setting HERMES_ENABLE_DEBUGGER one way or the other. class Impl; +// Callers within this library may set HERMES_ENABLE_DEBUGGER to see this extra +// API. +#ifdef HERMES_ENABLE_DEBUGGER + friend class HermesRuntimeAgentDelegateNew; + + hermes::cdp::CDPDebugAPI& getCDPDebugAPI(); +#endif + std::unique_ptr impl_; }; diff --git a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec index 335004f1e87e3d..32d71f78fd7ada 100644 --- a/packages/react-native/sdks/hermes-engine/hermes-engine.podspec +++ b/packages/react-native/sdks/hermes-engine/hermes-engine.podspec @@ -79,6 +79,12 @@ Pod::Spec.new do |spec| ss.header_dir = 'hermes' end + spec.subspec 'cdp' do |ss| + ss.source_files = '' + ss.public_header_files = 'API/hermes/cdp/*.h' + ss.header_dir = 'hermes/cdp' + end + spec.subspec 'inspector' do |ss| ss.source_files = '' ss.public_header_files = 'API/hermes/inspector/*.h' diff --git a/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh b/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh index a4fe7d79024cb4..d3af54bb9cedb9 100755 --- a/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh +++ b/packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh @@ -135,6 +135,9 @@ function build_apple_framework { mkdir -p destroot/include/hermes cp API/hermes/*.h destroot/include/hermes + mkdir -p destroot/include/hermes/cdp + cp API/hermes/cdp/*.h destroot/include/hermes/cdp + mkdir -p destroot/include/hermes/inspector cp API/hermes/inspector/*.h destroot/include/hermes/inspector @@ -162,6 +165,9 @@ function prepare_dest_root_for_ci { mkdir -p destroot/include/hermes cp API/hermes/*.h destroot/include/hermes + mkdir -p destroot/include/hermes/cdp + cp API/hermes/cdp/*.h destroot/include/hermes/cdp + mkdir -p destroot/include/hermes/inspector cp API/hermes/inspector/*.h destroot/include/hermes/inspector From cfa39c0a6993f94a716a97c01c586bbbe7632c35 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Fri, 8 Mar 2024 07:29:22 -0800 Subject: [PATCH 127/361] Integrate CDPAgent into HermesRuntimeTargetDelegate behind flag (#43353) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43353 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Integrates `HermesRuntimeAgentDelegateNew` (using the new Hermes `CDPAgent` setup) into `HermesRuntimeTargetDelegate` behind a new feature flag, `inspectorEnableHermesCDPAgent`. This completes the initial integration for all platforms. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54586162 fbshipit-source-id: 5f26c28af4414d961b1c8c9cb4cd7135bd00b410 --- .../featureflags/ReactNativeFeatureFlags.kt | 8 +++- .../ReactNativeFeatureFlagsCxxAccessor.kt | 12 ++++- .../ReactNativeFeatureFlagsCxxInterop.kt | 4 +- .../ReactNativeFeatureFlagsDefaults.kt | 4 +- .../ReactNativeFeatureFlagsLocalAccessor.kt | 13 ++++- .../ReactNativeFeatureFlagsProvider.kt | 4 +- .../JReactNativeFeatureFlagsCxxInterop.cpp | 16 ++++++- .../JReactNativeFeatureFlagsCxxInterop.h | 5 +- .../chrome/HermesRuntimeTargetDelegate.cpp | 48 ++++++++++++++----- .../jsinspector-modern/InspectorFlags.cpp | 13 ++++- .../jsinspector-modern/InspectorFlags.h | 6 +++ .../featureflags/ReactNativeFeatureFlags.cpp | 6 ++- .../featureflags/ReactNativeFeatureFlags.h | 7 ++- .../ReactNativeFeatureFlagsAccessor.cpp | 26 ++++++++-- .../ReactNativeFeatureFlagsAccessor.h | 6 ++- .../ReactNativeFeatureFlagsDefaults.h | 6 ++- .../ReactNativeFeatureFlagsProvider.h | 3 +- .../NativeReactNativeFeatureFlags.cpp | 7 ++- .../NativeReactNativeFeatureFlags.h | 4 +- .../ReactNativeFeatureFlags.config.js | 5 ++ .../NativeReactNativeFeatureFlags.js | 3 +- .../featureflags/ReactNativeFeatureFlags.js | 7 ++- 22 files changed, 176 insertions(+), 37 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt index 975a7182c5be44..e196d856d5a922 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<62ec63a2aebd866803cde1c1ca7d44c6>> */ /** @@ -82,6 +82,12 @@ public object ReactNativeFeatureFlags { @JvmStatic public fun inspectorEnableCxxInspectorPackagerConnection(): Boolean = accessor.inspectorEnableCxxInspectorPackagerConnection() + /** + * Flag determining if the new Hermes CDPAgent API should be enabled in the modern CDP backend. This flag is global and should not be changed across React Host lifetimes. + */ + @JvmStatic + public fun inspectorEnableHermesCDPAgent(): Boolean = accessor.inspectorEnableHermesCDPAgent() + /** * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt index fc217774592d47..a6eac99fa294ee 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<8539cf7ba13ab52ca878efd2c4858d7a>> + * @generated SignedSource<> */ /** @@ -29,6 +29,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso private var enableMountHooksAndroidCache: Boolean? = null private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null + private var inspectorEnableHermesCDPAgentCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null private var skipMountHookNotificationsCache: Boolean? = null private var useModernRuntimeSchedulerCache: Boolean? = null @@ -114,6 +115,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso return cached } + override fun inspectorEnableHermesCDPAgent(): Boolean { + var cached = inspectorEnableHermesCDPAgentCache + if (cached == null) { + cached = ReactNativeFeatureFlagsCxxInterop.inspectorEnableHermesCDPAgent() + inspectorEnableHermesCDPAgentCache = cached + } + return cached + } + override fun inspectorEnableModernCDPRegistry(): Boolean { var cached = inspectorEnableModernCDPRegistryCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt index d97a2dd6b4ab17..16eee48dec1fe3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<9b38540981705aea015b0a5d0ac07c6e>> */ /** @@ -46,6 +46,8 @@ public object ReactNativeFeatureFlagsCxxInterop { @DoNotStrip @JvmStatic public external fun inspectorEnableCxxInspectorPackagerConnection(): Boolean + @DoNotStrip @JvmStatic public external fun inspectorEnableHermesCDPAgent(): Boolean + @DoNotStrip @JvmStatic public external fun inspectorEnableModernCDPRegistry(): Boolean @DoNotStrip @JvmStatic public external fun skipMountHookNotifications(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt index 006caa1e9505b6..12fbeaeb870f99 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<99263973c4a06fdc91e7c9edf4aa4e19>> + * @generated SignedSource<> */ /** @@ -41,6 +41,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi override fun inspectorEnableCxxInspectorPackagerConnection(): Boolean = false + override fun inspectorEnableHermesCDPAgent(): Boolean = false + override fun inspectorEnableModernCDPRegistry(): Boolean = false override fun skipMountHookNotifications(): Boolean = false diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt index 88558da84c97f0..5cf84abc81568b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<7e3e2b716f8f6caf60b888350041745e>> */ /** @@ -33,6 +33,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces private var enableMountHooksAndroidCache: Boolean? = null private var enableSpannableBuildingUnificationCache: Boolean? = null private var inspectorEnableCxxInspectorPackagerConnectionCache: Boolean? = null + private var inspectorEnableHermesCDPAgentCache: Boolean? = null private var inspectorEnableModernCDPRegistryCache: Boolean? = null private var skipMountHookNotificationsCache: Boolean? = null private var useModernRuntimeSchedulerCache: Boolean? = null @@ -127,6 +128,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces return cached } + override fun inspectorEnableHermesCDPAgent(): Boolean { + var cached = inspectorEnableHermesCDPAgentCache + if (cached == null) { + cached = currentProvider.inspectorEnableHermesCDPAgent() + accessedFeatureFlags.add("inspectorEnableHermesCDPAgent") + inspectorEnableHermesCDPAgentCache = cached + } + return cached + } + override fun inspectorEnableModernCDPRegistry(): Boolean { var cached = inspectorEnableModernCDPRegistryCache if (cached == null) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt index 905ee909744af3..92ef509d076c87 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<268a87860fea5f281567d2142f90b0d4>> + * @generated SignedSource<> */ /** @@ -41,6 +41,8 @@ public interface ReactNativeFeatureFlagsProvider { @DoNotStrip public fun inspectorEnableCxxInspectorPackagerConnection(): Boolean + @DoNotStrip public fun inspectorEnableHermesCDPAgent(): Boolean + @DoNotStrip public fun inspectorEnableModernCDPRegistry(): Boolean @DoNotStrip public fun skipMountHookNotifications(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp index fec585cacd02c9..1e8f4599349757 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -93,6 +93,12 @@ class ReactNativeFeatureFlagsProviderHolder return method(javaProvider_); } + bool inspectorEnableHermesCDPAgent() override { + static const auto method = + getReactNativeFeatureFlagsProviderJavaClass()->getMethod("inspectorEnableHermesCDPAgent"); + return method(javaProvider_); + } + bool inspectorEnableModernCDPRegistry() override { static const auto method = getReactNativeFeatureFlagsProviderJavaClass()->getMethod("inspectorEnableModernCDPRegistry"); @@ -160,6 +166,11 @@ bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableCxxInspectorPackagerConn return ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection(); } +bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableHermesCDPAgent( + facebook::jni::alias_ref /*unused*/) { + return ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent(); +} + bool JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry( facebook::jni::alias_ref /*unused*/) { return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); @@ -219,6 +230,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() { makeNativeMethod( "inspectorEnableCxxInspectorPackagerConnection", JReactNativeFeatureFlagsCxxInterop::inspectorEnableCxxInspectorPackagerConnection), + makeNativeMethod( + "inspectorEnableHermesCDPAgent", + JReactNativeFeatureFlagsCxxInterop::inspectorEnableHermesCDPAgent), makeNativeMethod( "inspectorEnableModernCDPRegistry", JReactNativeFeatureFlagsCxxInterop::inspectorEnableModernCDPRegistry), diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h index 45ccaf577a0b8f..c10fc302342ce9 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +++ b/packages/react-native/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<24dfb31a32c16f44b9a0ed64d8fff25b>> */ /** @@ -57,6 +57,9 @@ class JReactNativeFeatureFlagsCxxInterop static bool inspectorEnableCxxInspectorPackagerConnection( facebook::jni::alias_ref); + static bool inspectorEnableHermesCDPAgent( + facebook::jni::alias_ref); + static bool inspectorEnableModernCDPRegistry( facebook::jni::alias_ref); diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index c9f651d75c549c..fbbb1a51c37964 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -5,8 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -#include "HermesRuntimeTargetDelegate.h" +#include +#include + #include "HermesRuntimeAgentDelegate.h" +#include "HermesRuntimeAgentDelegateNew.h" +#include "HermesRuntimeTargetDelegate.h" #ifdef HERMES_ENABLE_DEBUGGER #include @@ -23,16 +27,21 @@ namespace facebook::react::jsinspector_modern { class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { public: #ifdef HERMES_ENABLE_DEBUGGER - explicit Impl(std::shared_ptr hermesRuntime) - : runtime_(std::move(hermesRuntime)), + explicit Impl( + HermesRuntimeTargetDelegate& delegate, + std::shared_ptr hermesRuntime) + : delegate_(delegate), + runtime_(std::move(hermesRuntime)), cdpDebugAPI_(CDPDebugAPI::create(*runtime_)) {} CDPDebugAPI& getCDPDebugAPI() { return *cdpDebugAPI_; } #else - explicit Impl(std::shared_ptr hermesRuntime) - : runtime_(std::move(hermesRuntime)) {} + explicit Impl( + HermesRuntimeTargetDelegate& delegate, + std::shared_ptr hermesRuntime) + : delegate_(delegate), runtime_(std::move(hermesRuntime)) {} #endif // RuntimeTargetDelegate methods @@ -44,16 +53,29 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { previouslyExportedState, const ExecutionContextDescription& executionContextDescription, RuntimeExecutor runtimeExecutor) override { - return std::unique_ptr(new HermesRuntimeAgentDelegate( - frontendChannel, - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - runtime_, - std::move(runtimeExecutor))); + auto& inspectorFlags = InspectorFlags::getInstance(); + + return inspectorFlags.getEnableHermesCDPAgent() + ? std::unique_ptr( + new HermesRuntimeAgentDelegateNew( + frontendChannel, + sessionState, + std::move(previouslyExportedState), + executionContextDescription, + *runtime_, + delegate_, + std::move(runtimeExecutor))) + : std::unique_ptr(new HermesRuntimeAgentDelegate( + frontendChannel, + sessionState, + std::move(previouslyExportedState), + executionContextDescription, + runtime_, + std::move(runtimeExecutor))); } private: + HermesRuntimeTargetDelegate& delegate_; std::shared_ptr runtime_; #ifdef HERMES_ENABLE_DEBUGGER @@ -63,7 +85,7 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( std::shared_ptr hermesRuntime) - : impl_(std::make_unique(std::move(hermesRuntime))) {} + : impl_(std::make_unique(*this, std::move(hermesRuntime))) {} HermesRuntimeTargetDelegate::~HermesRuntimeTargetDelegate() = default; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp index 4a2c9df723a6d5..b473ee70e2a43d 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp @@ -22,7 +22,9 @@ InspectorFlags::InspectorFlags() ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry()), enableCxxInspectorPackagerConnection_( ReactNativeFeatureFlags:: - inspectorEnableCxxInspectorPackagerConnection()) {} + inspectorEnableCxxInspectorPackagerConnection()), + enableHermesCDPAgent_( + ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent()) {} bool InspectorFlags::getEnableModernCDPRegistry() const { assertFlagsMatchUpstream(); @@ -37,6 +39,11 @@ bool InspectorFlags::getEnableCxxInspectorPackagerConnection() const { enableModernCDPRegistry_; } +bool InspectorFlags::getEnableHermesCDPAgent() const { + assertFlagsMatchUpstream(); + return enableHermesCDPAgent_; +} + void InspectorFlags::dangerouslyResetFlags() { *this = InspectorFlags{}; } @@ -50,7 +57,9 @@ void InspectorFlags::assertFlagsMatchUpstream() const { ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry() || enableCxxInspectorPackagerConnection_ != ReactNativeFeatureFlags:: - inspectorEnableCxxInspectorPackagerConnection()) { + inspectorEnableCxxInspectorPackagerConnection() || + ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent() != + enableHermesCDPAgent_) { LOG(ERROR) << "[InspectorFlags] Error: One or more ReactNativeFeatureFlags values " << "have changed during the global app lifetime. This may lead to " diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h index 596f98d1344d98..249ae167dd5ef2 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h @@ -30,6 +30,11 @@ class InspectorFlags { */ bool getEnableCxxInspectorPackagerConnection() const; + /** + * Flag determining if the new Hermes CDPAgent API should be enabled. + */ + bool getEnableHermesCDPAgent() const; + /** * Reset flags to their upstream values. The caller must ensure any resources * that have read previous flag values have been cleaned up. @@ -44,6 +49,7 @@ class InspectorFlags { bool enableModernCDPRegistry_; bool enableCxxInspectorPackagerConnection_; + bool enableHermesCDPAgent_; mutable bool inconsistentFlagsStateLogged_{false}; void assertFlagsMatchUpstream() const; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp index 5a1a133eceae81..0457dbc9cae384 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -57,6 +57,10 @@ bool ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection() { return getAccessor().inspectorEnableCxxInspectorPackagerConnection(); } +bool ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent() { + return getAccessor().inspectorEnableHermesCDPAgent(); +} + bool ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry() { return getAccessor().inspectorEnableModernCDPRegistry(); } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h index f0c0c72b367bb9..9e2bdc8cb7b61a 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -82,6 +82,11 @@ class ReactNativeFeatureFlags { */ RN_EXPORT static bool inspectorEnableCxxInspectorPackagerConnection(); + /** + * Flag determining if the new Hermes CDPAgent API should be enabled in the modern CDP backend. This flag is global and should not be changed across React Host lifetimes. + */ + RN_EXPORT static bool inspectorEnableHermesCDPAgent(); + /** * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp index f352ada4f9124c..81d098ee12a6e1 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<6c1e6b6a51cd6fdddae40d3b61ae2b36>> + * @generated SignedSource<<940e03ab78a13e5486802c13861be739>> */ /** @@ -191,6 +191,24 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableCxxInspectorPackagerConnect return flagValue.value(); } +bool ReactNativeFeatureFlagsAccessor::inspectorEnableHermesCDPAgent() { + auto flagValue = inspectorEnableHermesCDPAgent_.load(); + + if (!flagValue.has_value()) { + // This block is not exclusive but it is not necessary. + // If multiple threads try to initialize the feature flag, we would only + // be accessing the provider multiple times but the end state of this + // instance and the returned flag value would be the same. + + markFlagAsAccessed(9, "inspectorEnableHermesCDPAgent"); + + flagValue = currentProvider_->inspectorEnableHermesCDPAgent(); + inspectorEnableHermesCDPAgent_ = flagValue; + } + + return flagValue.value(); +} + bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { auto flagValue = inspectorEnableModernCDPRegistry_.load(); @@ -200,7 +218,7 @@ bool ReactNativeFeatureFlagsAccessor::inspectorEnableModernCDPRegistry() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(9, "inspectorEnableModernCDPRegistry"); + markFlagAsAccessed(10, "inspectorEnableModernCDPRegistry"); flagValue = currentProvider_->inspectorEnableModernCDPRegistry(); inspectorEnableModernCDPRegistry_ = flagValue; @@ -218,7 +236,7 @@ bool ReactNativeFeatureFlagsAccessor::skipMountHookNotifications() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(10, "skipMountHookNotifications"); + markFlagAsAccessed(11, "skipMountHookNotifications"); flagValue = currentProvider_->skipMountHookNotifications(); skipMountHookNotifications_ = flagValue; @@ -236,7 +254,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() { // be accessing the provider multiple times but the end state of this // instance and the returned flag value would be the same. - markFlagAsAccessed(11, "useModernRuntimeScheduler"); + markFlagAsAccessed(12, "useModernRuntimeScheduler"); flagValue = currentProvider_->useModernRuntimeScheduler(); useModernRuntimeScheduler_ = flagValue; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h index 6e51c8fda83255..e1d90051ae9e02 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4c5446d5b72429d090e17523f2d544a7>> + * @generated SignedSource<> */ /** @@ -40,6 +40,7 @@ class ReactNativeFeatureFlagsAccessor { bool enableMountHooksAndroid(); bool enableSpannableBuildingUnification(); bool inspectorEnableCxxInspectorPackagerConnection(); + bool inspectorEnableHermesCDPAgent(); bool inspectorEnableModernCDPRegistry(); bool skipMountHookNotifications(); bool useModernRuntimeScheduler(); @@ -53,7 +54,7 @@ class ReactNativeFeatureFlagsAccessor { std::unique_ptr currentProvider_; bool wasOverridden_; - std::array, 12> accessedFeatureFlags_; + std::array, 13> accessedFeatureFlags_; std::atomic> commonTestFlag_; std::atomic> batchRenderingUpdatesInEventLoop_; @@ -64,6 +65,7 @@ class ReactNativeFeatureFlagsAccessor { std::atomic> enableMountHooksAndroid_; std::atomic> enableSpannableBuildingUnification_; std::atomic> inspectorEnableCxxInspectorPackagerConnection_; + std::atomic> inspectorEnableHermesCDPAgent_; std::atomic> inspectorEnableModernCDPRegistry_; std::atomic> skipMountHookNotifications_; std::atomic> useModernRuntimeScheduler_; diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h index 3324b1239a1840..9086c75f6b03ce 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<95e3fd7cf662623e3c09b093649d4ff2>> + * @generated SignedSource<> */ /** @@ -63,6 +63,10 @@ class ReactNativeFeatureFlagsDefaults : public ReactNativeFeatureFlagsProvider { return false; } + bool inspectorEnableHermesCDPAgent() override { + return false; + } + bool inspectorEnableModernCDPRegistry() override { return false; } diff --git a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h index a28f6e1c2ed1d5..820c97c49f7faa 100644 --- a/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +++ b/packages/react-native/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<26990a0a11bb2d7cf8510773b6ece099>> + * @generated SignedSource<> */ /** @@ -34,6 +34,7 @@ class ReactNativeFeatureFlagsProvider { virtual bool enableMountHooksAndroid() = 0; virtual bool enableSpannableBuildingUnification() = 0; virtual bool inspectorEnableCxxInspectorPackagerConnection() = 0; + virtual bool inspectorEnableHermesCDPAgent() = 0; virtual bool inspectorEnableModernCDPRegistry() = 0; virtual bool skipMountHookNotifications() = 0; virtual bool useModernRuntimeScheduler() = 0; diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp index f2a21bbc09d5cc..45e8c863235d67 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<4f7daa629ad90a9ab2fdc99e7c51e355>> + * @generated SignedSource<> */ /** @@ -82,6 +82,11 @@ bool NativeReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnectio return ReactNativeFeatureFlags::inspectorEnableCxxInspectorPackagerConnection(); } +bool NativeReactNativeFeatureFlags::inspectorEnableHermesCDPAgent( + jsi::Runtime& /*runtime*/) { + return ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent(); +} + bool NativeReactNativeFeatureFlags::inspectorEnableModernCDPRegistry( jsi::Runtime& /*runtime*/) { return ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(); diff --git a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h index 47293751c29528..827681e4f2d41d 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +++ b/packages/react-native/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<> */ /** @@ -54,6 +54,8 @@ class NativeReactNativeFeatureFlags bool inspectorEnableCxxInspectorPackagerConnection(jsi::Runtime& runtime); + bool inspectorEnableHermesCDPAgent(jsi::Runtime& runtime); + bool inspectorEnableModernCDPRegistry(jsi::Runtime& runtime); bool skipMountHookNotifications(jsi::Runtime& runtime); diff --git a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js index 1a10c53c020c6a..ef84a26cf9d1d7 100644 --- a/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js +++ b/packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js @@ -72,6 +72,11 @@ const definitions: FeatureFlagDefinitions = { description: 'Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes.', }, + inspectorEnableHermesCDPAgent: { + defaultValue: false, + description: + 'Flag determining if the new Hermes CDPAgent API should be enabled in the modern CDP backend. This flag is global and should not be changed across React Host lifetimes.', + }, inspectorEnableModernCDPRegistry: { defaultValue: false, description: diff --git a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js index 2fda50641c86f0..3223e8590bdf29 100644 --- a/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/NativeReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<> + * @generated SignedSource<<6a401351e670388135bec038018d3fe8>> * @flow strict-local */ @@ -32,6 +32,7 @@ export interface Spec extends TurboModule { +enableMountHooksAndroid?: () => boolean; +enableSpannableBuildingUnification?: () => boolean; +inspectorEnableCxxInspectorPackagerConnection?: () => boolean; + +inspectorEnableHermesCDPAgent?: () => boolean; +inspectorEnableModernCDPRegistry?: () => boolean; +skipMountHookNotifications?: () => boolean; +useModernRuntimeScheduler?: () => boolean; diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js index 56d0b91cb34090..f28b03b9bfac69 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlags.js @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<5d1eca67ace8cccc336a6c6f65b40c99>> + * @generated SignedSource<<66678139be02293ff532e8e125ccc608>> * @flow strict-local */ @@ -49,6 +49,7 @@ export type ReactNativeFeatureFlags = { enableMountHooksAndroid: Getter, enableSpannableBuildingUnification: Getter, inspectorEnableCxxInspectorPackagerConnection: Getter, + inspectorEnableHermesCDPAgent: Getter, inspectorEnableModernCDPRegistry: Getter, skipMountHookNotifications: Getter, useModernRuntimeScheduler: Getter, @@ -130,6 +131,10 @@ export const enableSpannableBuildingUnification: Getter = createNativeF * Flag determining if the C++ implementation of InspectorPackagerConnection should be used instead of the per-platform one. This flag is global and should not be changed across React Host lifetimes. */ export const inspectorEnableCxxInspectorPackagerConnection: Getter = createNativeFlagGetter('inspectorEnableCxxInspectorPackagerConnection', false); +/** + * Flag determining if the new Hermes CDPAgent API should be enabled in the modern CDP backend. This flag is global and should not be changed across React Host lifetimes. + */ +export const inspectorEnableHermesCDPAgent: Getter = createNativeFlagGetter('inspectorEnableHermesCDPAgent', false); /** * Flag determining if the modern CDP backend should be enabled. This flag is global and should not be changed across React Host lifetimes. */ From 7bb204a16030c8c50a5e686cbbf77d10b683f2ae Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Fri, 8 Mar 2024 08:53:49 -0800 Subject: [PATCH 128/361] Fix public-api-test "expected parse error" assertion (#43378) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43378 ## Overview I noticed while running this test, that there's an existing `console.error` to remove a file from the `FILES_WITH_KNOWN_ERRORS` list, but the tests pass despite the error. This happens because the `console.error` throws to fail the test, but this `console.error` is inside a try/catch, so the error is swallowed. This diff moves the check to a finally, which fails the test. I also fixed the `FILES_WITH_KNOWN_ERRORS` list. Changelog: [Internal] Reviewed By: yungsters Differential Revision: D54587062 fbshipit-source-id: c46e98326ef6654452871337364d7e66ff204e2c --- .../Libraries/__tests__/public-api-test.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/__tests__/public-api-test.js b/packages/react-native/Libraries/__tests__/public-api-test.js index 6fcd7671d763e2..66ff7f27556f8f 100644 --- a/packages/react-native/Libraries/__tests__/public-api-test.js +++ b/packages/react-native/Libraries/__tests__/public-api-test.js @@ -87,19 +87,22 @@ describe('public API', () => { return; } + let success = false; try { expect(await translateFlowToExportedAPI(source)).toMatchSnapshot(); - if (FILES_WITH_KNOWN_ERRORS.has(file)) { + success = true; + } catch (e) { + if (!FILES_WITH_KNOWN_ERRORS.has(file)) { + console.error('Unable to parse file:', file, '\n' + e); + } + } finally { + if (success && FILES_WITH_KNOWN_ERRORS.has(file)) { console.error( 'Expected parse error, please remove file exclude from FILES_WITH_KNOWN_ERRORS:', file, ); } - } catch (e) { - if (!FILES_WITH_KNOWN_ERRORS.has(file)) { - console.error('Unable to parse file:', file, '\n' + e); - } } } else { expect('UNTYPED MODULE').toMatchSnapshot(); From eadcebbb3efe1af70f3f7321617df9bc7fde0371 Mon Sep 17 00:00:00 2001 From: Alexey Litvinov Date: Fri, 8 Mar 2024 09:24:45 -0800 Subject: [PATCH 129/361] add support for text highlighting (#43386) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43386 Changes: - fixes `RCTAttributedTextUtils` to set `RCTAttributedStringIsHighlightedAttributeName` attribute according to `isHighlighted` textAttribute value. - adds block to `drawAttributedString` and passed highlighted bezier curve to it. - updates `drawRect` to visually highlight selected text. ## Changelog: [iOS][Fixed] - Fixed text highlighting in the New Architecture Reviewed By: sammy-SC Differential Revision: D54594472 fbshipit-source-id: ed454e3a1660fa76d96cb131e33fba1c05f47776 --- .../Text/RCTParagraphComponentView.mm | 17 +++++++++- .../RCTAttributedTextUtils.mm | 2 +- .../textlayoutmanager/RCTTextLayoutManager.h | 3 +- .../textlayoutmanager/RCTTextLayoutManager.mm | 33 +++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm index c2cc7f38f439b1..d09c6f760fd1d1 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/Text/RCTParagraphComponentView.mm @@ -35,6 +35,7 @@ @implementation RCTParagraphComponentView { ParagraphAttributes _paragraphAttributes; RCTParagraphComponentAccessibilityProvider *_accessibilityProvider; UILongPressGestureRecognizer *_longPressGestureRecognizer; + CAShapeLayer *_highlightLayer; } - (instancetype)initWithFrame:(CGRect)frame @@ -132,7 +133,21 @@ - (void)drawRect:(CGRect)rect [nativeTextLayoutManager drawAttributedString:_state->getData().attributedString paragraphAttributes:_paragraphAttributes frame:frame - textStorage:unwrapManagedObject(nsTextStorage)]; + textStorage:unwrapManagedObject(nsTextStorage) + drawHighlightPath:^(UIBezierPath *highlightPath) { + if (highlightPath) { + if (!self->_highlightLayer) { + self->_highlightLayer = [CAShapeLayer layer]; + self->_highlightLayer.fillColor = [UIColor colorWithWhite:0 alpha:0.25].CGColor; + [self.layer addSublayer:self->_highlightLayer]; + } + self->_highlightLayer.position = frame.origin; + self->_highlightLayer.path = highlightPath.CGPath; + } else { + [self->_highlightLayer removeFromSuperlayer]; + self->_highlightLayer = nil; + } + }]; } #pragma mark - Accessibility diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm index b76bb2fba04117..74f5b65df1338d 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm @@ -285,7 +285,7 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex } // Special - if (textAttributes.isHighlighted) { + if (textAttributes.isHighlighted.value_or(false)) { attributes[RCTAttributedStringIsHighlightedAttributeName] = @YES; } diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h index b0d906ca10cea8..41809ce12ae31d 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.h @@ -43,7 +43,8 @@ using RCTTextLayoutFragmentEnumerationBlock = - (void)drawAttributedString:(facebook::react::AttributedString)attributedString paragraphAttributes:(facebook::react::ParagraphAttributes)paragraphAttributes frame:(CGRect)frame - textStorage:(NSTextStorage *_Nullable)textStorage; + textStorage:(NSTextStorage *_Nullable)textStorage + drawHighlightPath:(void (^_Nullable)(UIBezierPath *highlightPath))block; - (facebook::react::LinesMeasurements)getLinesForAttributedString:(facebook::react::AttributedString)attributedString paragraphAttributes: diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm index f7d17f52dc37bb..1b917150074a32 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm @@ -76,6 +76,7 @@ - (void)drawAttributedString:(AttributedString)attributedString paragraphAttributes:(ParagraphAttributes)paragraphAttributes frame:(CGRect)frame textStorage:(NSTextStorage *_Nullable)textStorage + drawHighlightPath:(void (^_Nullable)(UIBezierPath *highlightPath))block { BOOL createdStorageForFrame = NO; @@ -118,6 +119,38 @@ - (void)drawAttributedString:(AttributedString)attributedString #if TARGET_OS_MACCATALYST CGContextRestoreGState(context); #endif + + if (block != nil) { + __block UIBezierPath *highlightPath = nil; + NSRange characterRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL]; + + [textStorage + enumerateAttribute:RCTAttributedStringIsHighlightedAttributeName + inRange:characterRange + options:0 + usingBlock:^(NSNumber *value, NSRange range, __unused BOOL *stop) { + if (!value.boolValue) { + return; + } + + [layoutManager + enumerateEnclosingRectsForGlyphRange:range + withinSelectedGlyphRange:range + inTextContainer:textContainer + usingBlock:^(CGRect enclosingRect, __unused BOOL *anotherStop) { + UIBezierPath *path = [UIBezierPath + bezierPathWithRoundedRect:CGRectInset(enclosingRect, -2, -2) + cornerRadius:2]; + if (highlightPath) { + [highlightPath appendPath:path]; + } else { + highlightPath = path; + } + }]; + }]; + + block(highlightPath); + } } - (LinesMeasurements)getLinesForAttributedString:(AttributedString)attributedString From 208be5000088645e84fe546709894cda50b35a0b Mon Sep 17 00:00:00 2001 From: Luna Wei Date: Fri, 8 Mar 2024 09:46:48 -0800 Subject: [PATCH 130/361] Try renaming build_npm_package for nightly job (#43379) Summary: Changelog: [Internal] Try renaming nightly job so we can automate if there are failures See https://circleci.com/docs/configuration-reference/#name Pull Request resolved: https://github.com/facebook/react-native/pull/43379 Reviewed By: cortinico Differential Revision: D54670307 Pulled By: lunaleaps fbshipit-source-id: 85a26f92d7789f6195c9cf07909dd12850010a4b --- .circleci/configurations/workflows.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.circleci/configurations/workflows.yml b/.circleci/configurations/workflows.yml index e5c085ee4ce08a..7bf29679184d82 100644 --- a/.circleci/configurations/workflows.yml +++ b/.circleci/configurations/workflows.yml @@ -116,6 +116,7 @@ workflows: parameters: flavor: ["Debug", "Release"] - build_npm_package: + name: build_nightly_npm_package release_type: "nightly" requires: - build_android From 76ce7890141f22ba75cf62806762179be3c8cfa9 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 8 Mar 2024 10:28:45 -0800 Subject: [PATCH 131/361] Pass jsi::Runtime reference into CallInvoker::invoke* callbacks (#43375) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43375 ## Changelog: [Internal] - As discussed with the team, it makes more sense to pass the reference to the correct `jsi::Runtime` object as an argument to the ` CallInvoker::invoke*` callbacks, that are provided by the user. There are various use cases when user would like to get a hold of the `jsi::Runtime` in the callback, and it makes sense, since it is guaranteed to run on the JS thread. So far people have been coming up with all kinds of workarounds for that, none of them safe enough. Reviewed By: rubennorte Differential Revision: D54643171 fbshipit-source-id: 2f6015426a9e29cb9fcf5a9a3e2f6f33ff692538 --- .../React/CxxBridge/RCTCxxBridge.mm | 2 +- .../callinvoker/ReactCommon/CallInvoker.h | 24 ++++++++++++-- .../ReactCommon/cxxreact/Instance.cpp | 11 +++---- .../ReactCommon/cxxreact/Instance.h | 8 ++--- .../ReactCommon/cxxreact/NativeToJsBridge.cpp | 4 +-- .../ReactCommon/react/bridging/Function.h | 10 +++--- .../react/bridging/tests/BridgingTest.h | 8 ++--- .../core/ReactCommon/TurboCxxModule.cpp | 31 +++++++++---------- .../core/ReactCommon/TurboModule.cpp | 16 +++++----- .../RuntimeSchedulerCallInvoker.cpp | 6 ++-- .../react/runtime/BridgelessJSCallInvoker.cpp | 8 ++--- .../react/runtime/BridgelessJSCallInvoker.h | 4 +-- .../BridgelessNativeMethodCallInvoker.cpp | 4 +-- .../BridgelessNativeMethodCallInvoker.h | 4 +-- 14 files changed, 77 insertions(+), 63 deletions(-) diff --git a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm index 0af826104e4898..232576669771be 100644 --- a/packages/react-native/React/CxxBridge/RCTCxxBridge.mm +++ b/packages/react-native/React/CxxBridge/RCTCxxBridge.mm @@ -1566,7 +1566,7 @@ - (void *)runtime return _reactInstance->getJavaScriptContext(); } -- (void)invokeAsync:(std::function &&)func +- (void)invokeAsync:(CallFunc &&)func { __block auto retainedFunc = std::move(func); __weak __typeof(self) weakSelf = self; diff --git a/packages/react-native/ReactCommon/callinvoker/ReactCommon/CallInvoker.h b/packages/react-native/ReactCommon/callinvoker/ReactCommon/CallInvoker.h index 85d9aa8bc4812b..e5b4167264d7b9 100644 --- a/packages/react-native/ReactCommon/callinvoker/ReactCommon/CallInvoker.h +++ b/packages/react-native/ReactCommon/callinvoker/ReactCommon/CallInvoker.h @@ -12,9 +12,13 @@ #include "SchedulerPriority.h" +namespace facebook::jsi { +class Runtime; +} + namespace facebook::react { -using CallFunc = std::function; +using CallFunc = std::function; /** * An interface for a generic native-to-JS call invoker. See BridgeJSCallInvoker @@ -31,15 +35,29 @@ class CallInvoker { invokeAsync(std::move(func)); } virtual void invokeSync(CallFunc&& func) = 0; + + // Backward compatibility only, prefer the CallFunc methods instead + virtual void invokeAsync(std::function&& func) noexcept { + invokeAsync([func](jsi::Runtime&) { func(); }); + } + + virtual void invokeSync(std::function&& func) { + invokeSync([func](jsi::Runtime&) { func(); }); + } + virtual ~CallInvoker() {} }; +using NativeMethodCallFunc = std::function; + class NativeMethodCallInvoker { public: virtual void invokeAsync( const std::string& methodName, - CallFunc&& func) noexcept = 0; - virtual void invokeSync(const std::string& methodName, CallFunc&& func) = 0; + NativeMethodCallFunc&& func) noexcept = 0; + virtual void invokeSync( + const std::string& methodName, + NativeMethodCallFunc&& func) = 0; virtual ~NativeMethodCallInvoker() {} }; diff --git a/packages/react-native/ReactCommon/cxxreact/Instance.cpp b/packages/react-native/ReactCommon/cxxreact/Instance.cpp index 287212782191ef..ed0a2443efcf5d 100644 --- a/packages/react-native/ReactCommon/cxxreact/Instance.cpp +++ b/packages/react-native/ReactCommon/cxxreact/Instance.cpp @@ -279,14 +279,13 @@ void Instance::JSCallInvoker::setNativeToJsBridgeAndFlushCalls( } } -void Instance::JSCallInvoker::invokeSync(std::function&& work) { +void Instance::JSCallInvoker::invokeSync(CallFunc&& /*work*/) { // TODO: Replace JS Callinvoker with RuntimeExecutor. throw std::runtime_error( "Synchronous native -> JS calls are currently not supported."); } -void Instance::JSCallInvoker::invokeAsync( - std::function&& work) noexcept { +void Instance::JSCallInvoker::invokeAsync(CallFunc&& work) noexcept { std::scoped_lock guard(m_mutex); /** @@ -311,12 +310,12 @@ void Instance::JSCallInvoker::invokeAsync( scheduleAsync(std::move(work)); } -void Instance::JSCallInvoker::scheduleAsync( - std::function&& work) noexcept { +void Instance::JSCallInvoker::scheduleAsync(CallFunc&& work) noexcept { if (auto strongNativeToJsBridge = m_nativeToJsBridge.lock()) { strongNativeToJsBridge->runOnExecutorQueue( [work = std::move(work)](JSExecutor* executor) { - work(); + auto* runtime = (jsi::Runtime*)executor->getJavaScriptContext(); + work(*runtime); executor->flush(); }); } diff --git a/packages/react-native/ReactCommon/cxxreact/Instance.h b/packages/react-native/ReactCommon/cxxreact/Instance.h index 630c7946d2eab5..547c971dfe98c6 100644 --- a/packages/react-native/ReactCommon/cxxreact/Instance.h +++ b/packages/react-native/ReactCommon/cxxreact/Instance.h @@ -164,15 +164,15 @@ class RN_EXPORT Instance : private jsinspector_modern::InstanceTargetDelegate { std::weak_ptr m_nativeToJsBridge; std::mutex m_mutex; bool m_shouldBuffer = true; - std::list> m_workBuffer; + std::list m_workBuffer; - void scheduleAsync(std::function&& work) noexcept; + void scheduleAsync(CallFunc&& work) noexcept; public: void setNativeToJsBridgeAndFlushCalls( std::weak_ptr nativeToJsBridge); - void invokeAsync(std::function&& work) noexcept override; - void invokeSync(std::function&& work) override; + void invokeAsync(CallFunc&& work) noexcept override; + void invokeSync(CallFunc&& work) override; }; std::shared_ptr jsCallInvoker_ = diff --git a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp index f23ce412fae178..6595550001faed 100644 --- a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -326,14 +326,14 @@ NativeToJsBridge::getDecoratedNativeMethodCallInvoker( void invokeAsync( const std::string& methodName, - std::function&& func) noexcept override { + NativeMethodCallFunc&& func) noexcept override { if (auto strongJsToNativeBridge = m_jsToNativeBridge.lock()) { strongJsToNativeBridge->recordTurboModuleAsyncMethodCall(); } m_nativeInvoker->invokeAsync(methodName, std::move(func)); } - void invokeSync(const std::string& methodName, std::function&& func) + void invokeSync(const std::string& methodName, NativeMethodCallFunc&& func) override { m_nativeInvoker->invokeSync(methodName, std::move(func)); } diff --git a/packages/react-native/ReactCommon/react/bridging/Function.h b/packages/react-native/ReactCommon/react/bridging/Function.h index 0760e6abbc4cdc..fc124bc0a7f266 100644 --- a/packages/react-native/ReactCommon/react/bridging/Function.h +++ b/packages/react-native/ReactCommon/react/bridging/Function.h @@ -64,9 +64,8 @@ class AsyncCallback { if (auto wrapper = callback_->wrapper_.lock()) { auto fn = [callback = callback_, argsPtr = std::make_shared>( - std::make_tuple(std::forward(args)...))] { - callback->apply(std::move(*argsPtr)); - }; + std::make_tuple(std::forward(args)...))]( + jsi::Runtime&) { callback->apply(std::move(*argsPtr)); }; auto& jsInvoker = wrapper->jsInvoker(); if (priority) { @@ -85,9 +84,10 @@ class AsyncCallback { // Capture callback_ and not wrapper_. If callback_ is deallocated or the // JSVM is shutdown before the async task is scheduled, the underlying // function will have been deallocated. - auto fn = [callback = callback_, callImpl = std::move(callImpl)]() { + auto fn = [callback = callback_, + callImpl = std::move(callImpl)](jsi::Runtime& rt) { if (auto wrapper2 = callback->wrapper_.lock()) { - callImpl(wrapper2->runtime(), wrapper2->callback()); + callImpl(rt, wrapper2->callback()); } }; diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h index 9b60ec82f691ed..ffc4b49d67be9a 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h @@ -17,18 +17,18 @@ namespace facebook::react { class TestCallInvoker : public CallInvoker { public: - void invokeAsync(std::function&& fn) noexcept override { + void invokeAsync(CallFunc&& fn) noexcept override { queue_.push_back(std::move(fn)); } - void invokeSync(std::function&&) override { + void invokeSync(CallFunc&&) override { FAIL() << "JSCallInvoker does not support invokeSync()"; } private: friend class BridgingTest; - std::list> queue_; + std::list queue_; }; class BridgingTest : public ::testing::Test { @@ -63,7 +63,7 @@ class BridgingTest : public ::testing::Test { void flushQueue() { while (!invoker->queue_.empty()) { - invoker->queue_.front()(); + invoker->queue_.front()(*runtime); invoker->queue_.pop_front(); rt.drainMicrotasks(); // Run microtasks every cycle. } diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp index d1704b57b9f53e..f0de6f80d20c97 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboCxxModule.cpp @@ -33,24 +33,23 @@ CxxModule::Callback makeTurboCxxModuleCallback( return; } - strongWrapper->jsInvoker().invokeAsync([weakWrapper, args]() { - auto strongWrapper2 = weakWrapper.lock(); - if (!strongWrapper2) { - return; - } + strongWrapper->jsInvoker().invokeAsync( + [weakWrapper, args](jsi::Runtime& rt) { + auto strongWrapper2 = weakWrapper.lock(); + if (!strongWrapper2) { + return; + } - std::vector innerArgs; - for (auto& a : args) { - innerArgs.push_back( - jsi::valueFromDynamic(strongWrapper2->runtime(), a)); - } - strongWrapper2->callback().call( - strongWrapper2->runtime(), - (const jsi::Value*)innerArgs.data(), - innerArgs.size()); + std::vector innerArgs; + innerArgs.reserve(args.size()); + for (auto& a : args) { + innerArgs.push_back(jsi::valueFromDynamic(rt, a)); + } + strongWrapper2->callback().call( + rt, (const jsi::Value*)innerArgs.data(), innerArgs.size()); - strongWrapper2->destroy(); - }); + strongWrapper2->destroy(); + }); wrapperWasCalled = true; }; diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp index b0924be26e1ab8..cf165e30e1215f 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp @@ -43,22 +43,20 @@ void TurboModule::emitDeviceEvent( jsi::Runtime& runtime, const std::string& eventName, ArgFactory argFactory) { - jsInvoker_->invokeAsync([&runtime, eventName, argFactory]() { - jsi::Value emitter = - runtime.global().getProperty(runtime, "__rctDeviceEventEmitter"); + jsInvoker_->invokeAsync([eventName, argFactory](jsi::Runtime& rt) { + jsi::Value emitter = rt.global().getProperty(rt, "__rctDeviceEventEmitter"); if (!emitter.isUndefined()) { - jsi::Object emitterObject = emitter.asObject(runtime); + jsi::Object emitterObject = emitter.asObject(rt); // TODO: consider caching these jsi::Function emitFunction = - emitterObject.getPropertyAsFunction(runtime, "emit"); + emitterObject.getPropertyAsFunction(rt, "emit"); std::vector args; - args.emplace_back( - jsi::String::createFromAscii(runtime, eventName.c_str())); + args.emplace_back(jsi::String::createFromAscii(rt, eventName.c_str())); if (argFactory) { - argFactory(runtime, args); + argFactory(rt, args); } emitFunction.callWithThis( - runtime, emitterObject, (const jsi::Value*)args.data(), args.size()); + rt, emitterObject, (const jsi::Value*)args.data(), args.size()); } }); } diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp index 081118f2c31ed5..10bd57157f747e 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerCallInvoker.cpp @@ -19,14 +19,14 @@ RuntimeSchedulerCallInvoker::RuntimeSchedulerCallInvoker( void RuntimeSchedulerCallInvoker::invokeAsync(CallFunc&& func) noexcept { if (auto runtimeScheduler = runtimeScheduler_.lock()) { runtimeScheduler->scheduleWork( - [func = std::move(func)](jsi::Runtime&) { func(); }); + [func = std::move(func)](jsi::Runtime& rt) { func(rt); }); } } void RuntimeSchedulerCallInvoker::invokeSync(CallFunc&& func) { if (auto runtimeScheduler = runtimeScheduler_.lock()) { runtimeScheduler->executeNowOnTheSameThread( - [func = std::move(func)](jsi::Runtime&) { func(); }); + [func = std::move(func)](jsi::Runtime& rt) { func(rt); }); } } @@ -35,7 +35,7 @@ void RuntimeSchedulerCallInvoker::invokeAsync( CallFunc&& func) noexcept { if (auto runtimeScheduler = runtimeScheduler_.lock()) { runtimeScheduler->scheduleTask( - priority, [func = std::move(func)](jsi::Runtime&) { func(); }); + priority, [func = std::move(func)](jsi::Runtime& rt) { func(rt); }); } } diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.cpp b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.cpp index 33b151a1e1fd5f..20519e6a3b4c88 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.cpp +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.cpp @@ -15,12 +15,12 @@ BridgelessJSCallInvoker::BridgelessJSCallInvoker( RuntimeExecutor runtimeExecutor) : runtimeExecutor_(std::move(runtimeExecutor)) {} -void BridgelessJSCallInvoker::invokeAsync( - std::function&& func) noexcept { - runtimeExecutor_([func = std::move(func)](jsi::Runtime& runtime) { func(); }); +void BridgelessJSCallInvoker::invokeAsync(CallFunc&& func) noexcept { + runtimeExecutor_( + [func = std::move(func)](jsi::Runtime& runtime) { func(runtime); }); } -void BridgelessJSCallInvoker::invokeSync(std::function&& func) { +void BridgelessJSCallInvoker::invokeSync(CallFunc&& /*func*/) { // TODO: Implement this method. The TurboModule infra doesn't call invokeSync. throw std::runtime_error( "Synchronous native -> JS calls are currently not supported."); diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h index b6308c4169c4f8..a411c5e8a03aca 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessJSCallInvoker.h @@ -20,8 +20,8 @@ namespace facebook::react { class BridgelessJSCallInvoker : public CallInvoker { public: explicit BridgelessJSCallInvoker(RuntimeExecutor runtimeExecutor); - void invokeAsync(std::function&& func) noexcept override; - void invokeSync(std::function&& func) override; + void invokeAsync(CallFunc&& func) noexcept override; + void invokeSync(CallFunc&& func) override; private: RuntimeExecutor runtimeExecutor_; diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.cpp b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.cpp index e5f3e6813dc923..f81cba0e9e1356 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.cpp +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.cpp @@ -15,13 +15,13 @@ BridgelessNativeMethodCallInvoker::BridgelessNativeMethodCallInvoker( void BridgelessNativeMethodCallInvoker::invokeAsync( const std::string& methodName, - std::function&& func) noexcept { + NativeMethodCallFunc&& func) noexcept { messageQueueThread_->runOnQueue(std::move(func)); } void BridgelessNativeMethodCallInvoker::invokeSync( const std::string& methodName, - std::function&& func) { + NativeMethodCallFunc&& func) { messageQueueThread_->runOnQueueSync(std::move(func)); } diff --git a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h index 952a48427ef325..60509b098678e4 100644 --- a/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h +++ b/packages/react-native/ReactCommon/react/runtime/BridgelessNativeMethodCallInvoker.h @@ -20,8 +20,8 @@ class BridgelessNativeMethodCallInvoker : public NativeMethodCallInvoker { std::shared_ptr messageQueueThread); void invokeAsync( const std::string& methodName, - std::function&& func) noexcept override; - void invokeSync(const std::string& methodName, std::function&& func) + NativeMethodCallFunc&& func) noexcept override; + void invokeSync(const std::string& methodName, NativeMethodCallFunc&& func) override; private: From 6c28c87c4d5d8a9f5be5e02cd7d3eba5b4aaca8c Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Fri, 8 Mar 2024 10:28:45 -0800 Subject: [PATCH 132/361] TurboModule::emitDeviceEvent doesn't require jsi::Runtime argument anymore (#43376) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43376 ## Changelog: [Internal] - Make it possible to call `emitDeviceEvent` from C++ TurboModules without the need to explicitly provide the reference to `jsi::Runtime`, as in some contexts (when we call e.g. not from the JS thread itself) it may be hard to get hold of. Reviewed By: rubennorte Differential Revision: D54643903 fbshipit-source-id: 25cea413e66c6e76c958395879db1169899e3bc9 --- .../nativemodule/core/ReactCommon/TurboModule.cpp | 1 - .../react/nativemodule/core/ReactCommon/TurboModule.h | 10 +++++++++- .../NativeCxxModuleExample/NativeCxxModuleExample.cpp | 1 - 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp index cf165e30e1215f..fe2411974d20cd 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.cpp @@ -40,7 +40,6 @@ TurboModule::TurboModule( : name_(std::move(name)), jsInvoker_(std::move(jsInvoker)) {} void TurboModule::emitDeviceEvent( - jsi::Runtime& runtime, const std::string& eventName, ArgFactory argFactory) { jsInvoker_->invokeAsync([eventName, argFactory](jsi::Runtime& rt) { diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h index ccd9d1f85968ef..aad026af97b7fb 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModule.h @@ -106,10 +106,18 @@ class JSI_EXPORT TurboModule : public facebook::jsi::HostObject { * }); */ void emitDeviceEvent( - jsi::Runtime& runtime, const std::string& eventName, ArgFactory argFactory = nullptr); + // Backwards compatibility version + void emitDeviceEvent( + jsi::Runtime& /*runtime*/, + + const std::string& eventName, + ArgFactory argFactory = nullptr) { + emitDeviceEvent(eventName, std::move(argFactory)); + } + virtual jsi::Value create( jsi::Runtime& runtime, const jsi::PropNameID& propName) { diff --git a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp index abec005d02e00b..0bbc831d838156 100644 --- a/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp +++ b/packages/rn-tester/NativeCxxModuleExample/NativeCxxModuleExample.cpp @@ -184,7 +184,6 @@ void NativeCxxModuleExample::emitCustomDeviceEvent( // Test emitting device events (RCTDeviceEventEmitter.emit) from C++ // TurboModule with arbitrary arguments emitDeviceEvent( - rt, eventName.utf8(rt).c_str(), [](jsi::Runtime& rt, std::vector& args) { args.emplace_back(jsi::Value(true)); From e2157f063ac726c1ae2c0467fc85055f88996858 Mon Sep 17 00:00:00 2001 From: Ruslan Lesiutin Date: Fri, 8 Mar 2024 13:07:49 -0800 Subject: [PATCH 133/361] bump react-devtools-* packages to ^5.0.2 (#43384) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43384 Changelog: [Internal] via `js1 upgrade react-devtools -v ^5.0.2` 5.0.1 and 5.0.2 mostly include fixes, biggest change is the way how we find source location of the element and the symbolication. Backend from `react-devtools-core` 5.0.2 is required for symbolication. allow-large-files Reviewed By: huntie Differential Revision: D54679238 fbshipit-source-id: 13656b2d9bad106246c019e1627b87ffbc2735fe --- packages/react-native/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-native/package.json b/packages/react-native/package.json index e0101e009268e2..286bfb3d4d7662 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -125,7 +125,7 @@ "nullthrows": "^1.1.1", "pretty-format": "^26.5.2", "promise": "^8.3.0", - "react-devtools-core": "^5.0.0", + "react-devtools-core": "^5.0.2", "react-refresh": "^0.14.0", "react-shallow-renderer": "^16.15.0", "regenerator-runtime": "^0.13.2", diff --git a/yarn.lock b/yarn.lock index f42a55b4d49a08..fe7f8b6cd828e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8120,10 +8120,10 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -react-devtools-core@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-5.0.0.tgz#50b04a4dbfa62badbe4d86529e9478c396988b31" - integrity sha512-SAAMLacNDfFjMJjmbXURNWtrTyARi9xTqGkY48Btw5cIWlr1wgxfWYZKxoUZav1qqmhbpgTzSmmF+cpMHGHY3A== +react-devtools-core@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-5.0.2.tgz#c3c11c7b91857131d694457885ef49b7ae590857" + integrity sha512-+fDp3kDfPpF5xbAACJmihPHL0iDKpnKr7MyRvW0nZq71xwHWDW3zRCNpiiAJWd85vAGT+GbV9O87zAIDgvV1gw== dependencies: shell-quote "^1.6.1" ws "^7" From 3dee6d31b9059e319bf4849797e3ed21c298be70 Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Mon, 11 Mar 2024 03:48:49 -0700 Subject: [PATCH 134/361] fix(dev-middleware): allow inspector proxy to fetch sourcemaps on lan connections (#43307) Summary: The inspector proxy is inlining source maps on `Debugger.scriptParsed` CDP events. The inlining prevents Chrome DevTools from downloading this remotely, as that's not supported in newer versions anymore. The current implementation locks this inlining mechanism to just `localhost` and/or `127.0.0.1` addresses, making it incompatible with LAN or tunnel device connections. This PR removes that limitation to allow source map inlining on these LAN and tunnel connections. ## Changelog: [GENERAL][FIXED] Allow Inspector proxy to inline source maps on LAN connections Pull Request resolved: https://github.com/facebook/react-native/pull/43307 Test Plan: - See added test - Start Metro and connect a device over LAN, open the chrome devtools Reviewed By: huntie Differential Revision: D54485247 Pulled By: robhogan fbshipit-source-id: 6fcb0c6dd762d2f0a013497ba0a1126095b9130b --- packages/dev-middleware/src/inspector-proxy/Device.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 26befc0b1185c4..455a89fd09f051 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -758,10 +758,6 @@ export default class Device { // Fetch text, raising an exception if the text could not be fetched, // or is too large. async #fetchText(url: URL): Promise { - if (!['localhost', '127.0.0.1'].includes(url.hostname)) { - throw new Error('remote fetches not permitted'); - } - // $FlowFixMe[incompatible-call] Suppress arvr node-fetch flow error const response = await fetch(url); if (!response.ok) { From 80891468d2051304478fa48fede7097b2b5e757c Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 11 Mar 2024 05:29:07 -0700 Subject: [PATCH 135/361] Update InspectorFlags to lazily pull upstream values (#43390) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43390 Refactor after D54639775. This avoids the unfortunate side effect where `InspectorFlags::dangerouslyResetFlags()` would immediately reread `ReactNativeFeatureFlags `. This call is now relocated in our test util. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54684692 fbshipit-source-id: 962c7d78bbf71b1d81af412081d3ef5cfe443fa1 --- .../jsinspector-modern/InspectorFlags.cpp | 60 +++++++++---------- .../jsinspector-modern/InspectorFlags.h | 17 ++++-- .../utils/InspectorFlagOverridesGuard.cpp | 2 +- 3 files changed, 40 insertions(+), 39 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp index b473ee70e2a43d..22c29f84e27662 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.cpp @@ -17,55 +17,51 @@ InspectorFlags& InspectorFlags::getInstance() { return instance; } -InspectorFlags::InspectorFlags() - : enableModernCDPRegistry_( - ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry()), - enableCxxInspectorPackagerConnection_( - ReactNativeFeatureFlags:: - inspectorEnableCxxInspectorPackagerConnection()), - enableHermesCDPAgent_( - ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent()) {} - bool InspectorFlags::getEnableModernCDPRegistry() const { - assertFlagsMatchUpstream(); - return enableModernCDPRegistry_; + return loadFlagsAndAssertUnchanged().enableModernCDPRegistry; } bool InspectorFlags::getEnableCxxInspectorPackagerConnection() const { - assertFlagsMatchUpstream(); - return enableCxxInspectorPackagerConnection_ || + auto& values = loadFlagsAndAssertUnchanged(); + + return values.enableCxxInspectorPackagerConnection || // If we are using the modern CDP registry, then we must also use the C++ // InspectorPackagerConnection implementation. - enableModernCDPRegistry_; + values.enableModernCDPRegistry; } bool InspectorFlags::getEnableHermesCDPAgent() const { - assertFlagsMatchUpstream(); - return enableHermesCDPAgent_; + return loadFlagsAndAssertUnchanged().enableHermesCDPAgent; } void InspectorFlags::dangerouslyResetFlags() { *this = InspectorFlags{}; } -void InspectorFlags::assertFlagsMatchUpstream() const { - if (inconsistentFlagsStateLogged_) { - return; - } +const InspectorFlags::Values& InspectorFlags::loadFlagsAndAssertUnchanged() + const { + InspectorFlags::Values newValues = { + .enableCxxInspectorPackagerConnection = ReactNativeFeatureFlags:: + inspectorEnableCxxInspectorPackagerConnection(), + .enableHermesCDPAgent = + ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent(), + .enableModernCDPRegistry = + ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry(), + }; - if (enableModernCDPRegistry_ != - ReactNativeFeatureFlags::inspectorEnableModernCDPRegistry() || - enableCxxInspectorPackagerConnection_ != - ReactNativeFeatureFlags:: - inspectorEnableCxxInspectorPackagerConnection() || - ReactNativeFeatureFlags::inspectorEnableHermesCDPAgent() != - enableHermesCDPAgent_) { - LOG(ERROR) - << "[InspectorFlags] Error: One or more ReactNativeFeatureFlags values " - << "have changed during the global app lifetime. This may lead to " - << "inconsistent inspector behaviour. Please quit and restart the app."; - inconsistentFlagsStateLogged_ = true; + if (cachedValues_.has_value() && !inconsistentFlagsStateLogged_) { + if (cachedValues_ != newValues) { + LOG(ERROR) + << "[InspectorFlags] Error: One or more ReactNativeFeatureFlags values " + << "have changed during the global app lifetime. This may lead to " + << "inconsistent inspector behaviour. Please quit and restart the app."; + inconsistentFlagsStateLogged_ = true; + } } + + cachedValues_ = newValues; + + return cachedValues_.value(); } } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h index 249ae167dd5ef2..775ee2b5844bf3 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/InspectorFlags.h @@ -42,17 +42,22 @@ class InspectorFlags { void dangerouslyResetFlags(); private: - InspectorFlags(); + struct Values { + bool enableCxxInspectorPackagerConnection; + bool enableHermesCDPAgent; + bool enableModernCDPRegistry; + bool operator==(const Values&) const = default; + }; + + InspectorFlags() = default; InspectorFlags(const InspectorFlags&) = delete; InspectorFlags& operator=(const InspectorFlags&) = default; ~InspectorFlags() = default; - bool enableModernCDPRegistry_; - bool enableCxxInspectorPackagerConnection_; - bool enableHermesCDPAgent_; - + mutable std::optional cachedValues_; mutable bool inconsistentFlagsStateLogged_{false}; - void assertFlagsMatchUpstream() const; + + const Values& loadFlagsAndAssertUnchanged() const; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp index aa1b87b8f57f10..cc5caf11953acd 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp @@ -40,12 +40,12 @@ class ReactNativeFeatureFlagsOverrides InspectorFlagOverridesGuard::InspectorFlagOverridesGuard( const InspectorFlagOverrides& overrides) { + InspectorFlags::getInstance().dangerouslyResetFlags(); ReactNativeFeatureFlags::override( std::make_unique(overrides)); } InspectorFlagOverridesGuard::~InspectorFlagOverridesGuard() { - InspectorFlags::getInstance().dangerouslyResetFlags(); ReactNativeFeatureFlags::dangerouslyReset(); } From 1ea269f42c2ef10e95fcf4751e71fba8bb5fe80d Mon Sep 17 00:00:00 2001 From: D N <4661784+retyui@users.noreply.github.com> Date: Mon, 11 Mar 2024 06:00:36 -0700 Subject: [PATCH 136/361] fix: [TypeScript] Allow to pass empty string as style (#43404) Summary: ```tsx import {Text} from 'react-native' interface Props { foregroundColor?: string | undefined | null } function Test({foregroundColor}: Props){ return // ^^^ Error: Type "" is not assignable to type TextStyle | Falsy | RegisteredStyle | RecursiveArray; ``` Reviewed By: rshest Differential Revision: D54744517 Pulled By: javache fbshipit-source-id: c5b934616cc0501c2b6a7907e6be522187a2cc20 --- .../Libraries/StyleSheet/StyleSheet.d.ts | 2 +- .../react-native/types/__typetests__/index.tsx | 14 +++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheet.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheet.d.ts index 6d9fda4dac2e85..17ab55d6bc9fbd 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheet.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheet.d.ts @@ -14,7 +14,7 @@ export interface StyleSheetProperties { flatten(style: T): T; } -type Falsy = undefined | null | false; +type Falsy = undefined | null | false | ''; interface RecursiveArray extends Array | RecursiveArray> {} /** Keep a brand of 'T' so that calls to `StyleSheet.flatten` can take `RegisteredStyle` and return `T`. */ diff --git a/packages/react-native/types/__typetests__/index.tsx b/packages/react-native/types/__typetests__/index.tsx index 33a3a2bba745b4..80a615b036c418 100644 --- a/packages/react-native/types/__typetests__/index.tsx +++ b/packages/react-native/types/__typetests__/index.tsx @@ -411,7 +411,9 @@ class CustomView extends React.Component { } } -class Welcome extends React.Component & {color: string}> { +class Welcome extends React.Component< + ElementProps & {color: string; bgColor?: null | undefined | string} +> { rootViewRef = React.useRef(null); customViewRef = React.useRef(null); @@ -436,12 +438,18 @@ class Welcome extends React.Component & {color: string}> { } render() { - const {color, ...props} = this.props; + const {color, bgColor, ...props} = this.props; return ( + style={[ + [styles.container], + undefined, + null, + false, + bgColor && {backgroundColor: bgColor}, + ]}> Welcome to React Native To get started, edit index.ios.js From 7c5a014c0d9868c03df33a426f5360f1aecd4726 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 11 Mar 2024 06:29:32 -0700 Subject: [PATCH 137/361] Pass whole RuntimeTargetDelegate from RN instead of aggregating its methods (#43346) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43346 Changelog: [Internal] (Continuing the theme of reducing integration boilerplate from D54537844.) This diff changes both `JSExecutor` (Bridge) and `JSRuntime` (Bridgeless) to no longer implement `RuntimeTargetDelegate`. Instead, each of them exposes a `getRuntimeTargetDelegate()` method that returns a stable reference to a target delegate that it *owns*. To facilitate this, we create a new `FallbackRuntimeTargetDelegate` for use in non-Hermes cases. This replaces *almost* all direct uses of `FallbackRuntimeAgentDelegate` outside of `jsinspector`. I'll follow up in a separate diff to deal with the last case and make the fallback agent delegate fully private. As a result, changing the `RuntimeTargetDelegate` interface (which we'll need to do for console support) becomes much easier: we only have unit test mocks + two concrete `RuntimeTargetDelegate` implementations (one fallback, one Hermes) to update for each API change. Reviewed By: huntie Differential Revision: D54585658 fbshipit-source-id: 08b61c74008ddc36c2b134a40755ef8e43ab21ed --- .../ReactCommon/cxxreact/JSExecutor.cpp | 18 +++------ .../ReactCommon/cxxreact/JSExecutor.h | 26 +++++++------ .../ReactCommon/cxxreact/NativeToJsBridge.cpp | 2 +- .../hermes/executor/HermesExecutorFactory.cpp | 18 ++------- .../hermes/executor/HermesExecutorFactory.h | 11 +----- .../chrome/HermesRuntimeAgentDelegate.cpp | 3 ++ .../FallbackRuntimeTargetDelegate.cpp | 29 ++++++++++++++ .../FallbackRuntimeTargetDelegate.h | 38 +++++++++++++++++++ .../ReactCommon/jsinspector-modern/ReactCdp.h | 2 +- .../tests/JsiIntegrationTest.cpp | 6 ++- ...JsiIntegrationTestGenericEngineAdapter.cpp | 22 ++++------- .../JsiIntegrationTestGenericEngineAdapter.h | 12 ++---- .../JsiIntegrationTestHermesEngineAdapter.cpp | 21 +++------- .../JsiIntegrationTestHermesEngineAdapter.h | 12 ++---- .../react/runtime/JSRuntimeFactory.cpp | 18 +++------ .../react/runtime/JSRuntimeFactory.h | 25 +++++++----- .../react/runtime/ReactInstance.cpp | 4 +- .../react/runtime/hermes/HermesInstance.cpp | 17 ++------- 18 files changed, 148 insertions(+), 136 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp index f188cfe93304ca..263ab90bb5cb31 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.cpp @@ -35,18 +35,12 @@ double JSExecutor::performanceNow() { return duration / NANOSECONDS_IN_MILLISECOND; } -std::unique_ptr -JSExecutor::createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) { - (void)executionContextDescription; - (void)runtimeExecutor; - return std::make_unique( - std::move(frontendChannel), sessionState, getDescription()); +jsinspector_modern::RuntimeTargetDelegate& +JSExecutor::getRuntimeTargetDelegate() { + if (!runtimeTargetDelegate_) { + runtimeTargetDelegate_.emplace(getDescription()); + } + return *runtimeTargetDelegate_; } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h index 757997aec84067..469f4ca6fd73d5 100644 --- a/packages/react-native/ReactCommon/cxxreact/JSExecutor.h +++ b/packages/react-native/ReactCommon/cxxreact/JSExecutor.h @@ -55,7 +55,7 @@ class JSExecutorFactory { virtual ~JSExecutorFactory() {} }; -class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate { +class RN_EXPORT JSExecutor { public: /** * Prepares the JS runtime for React Native by installing global variables. @@ -130,7 +130,7 @@ class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate { virtual void handleMemoryPressure([[maybe_unused]] int pressureLevel) {} virtual void destroy() {} - virtual ~JSExecutor() override {} + virtual ~JSExecutor() = default; virtual void flush() {} @@ -141,17 +141,19 @@ class RN_EXPORT JSExecutor : public jsinspector_modern::RuntimeTargetDelegate { static double performanceNow(); /** - * Create a RuntimeAgentDelegate that can be used to debug the JS VM instance. + * Get a reference to the \c RuntimeTargetDelegate owned (or implemented) by + * this executor. This reference must remain valid for the duration of the + * executor's lifetime. */ - virtual std::unique_ptr - createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) override; + virtual jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate(); + + private: + /** + * Initialized by \c getRuntimeTargetDelegate if not overridden, and then + * never changes. + */ + std::optional + runtimeTargetDelegate_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp index 6595550001faed..aeec3b7a144520 100644 --- a/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp +++ b/packages/react-native/ReactCommon/cxxreact/NativeToJsBridge.cpp @@ -345,7 +345,7 @@ NativeToJsBridge::getDecoratedNativeMethodCallInvoker( jsinspector_modern::RuntimeTargetDelegate& NativeToJsBridge::getInspectorTargetDelegate() { - return *m_executor; + return m_executor->getRuntimeTargetDelegate(); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp index 9a537f4cf01f85..56a8398f0b544a 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp @@ -256,21 +256,9 @@ HermesExecutor::HermesExecutor( targetDelegate_{ std::shared_ptr(runtime_, &hermesRuntime)} {} -std::unique_ptr -HermesExecutor::createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) { - return targetDelegate_.createAgentDelegate( - std::move(frontendChannel), - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - std::move(runtimeExecutor)); +jsinspector_modern::RuntimeTargetDelegate& +HermesExecutor::getRuntimeTargetDelegate() { + return targetDelegate_; } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h index c0ee1b8edc0a94..4056d42ef5259b 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h @@ -55,15 +55,8 @@ class HermesExecutor : public JSIExecutor { RuntimeInstaller runtimeInstaller, hermes::HermesRuntime& hermesRuntime); - virtual std::unique_ptr - createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) override; + jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate() + override; private: JSIScopedTimeoutInvoker timeoutInvoker_; diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp index b12b32e5aa51db..3b1d1caa11c1e0 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp @@ -14,6 +14,9 @@ #include #include #else // HERMES_ENABLE_DEBUGGER +// TODO(moti): FallbackRuntimeAgentDelegate should be private. We should fall +// back at the *TargetDelegate* level, in HermesRuntimeTargetDelegate, rather +// than within HermesRuntimeAgentDelegate. #include #endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp new file mode 100644 index 00000000000000..cd2cb9ab44f74e --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "FallbackRuntimeTargetDelegate.h" +#include "FallbackRuntimeAgentDelegate.h" + +namespace facebook::react::jsinspector_modern { + +FallbackRuntimeTargetDelegate::FallbackRuntimeTargetDelegate( + std::string engineDescription) + : engineDescription_{std::move(engineDescription)} {} + +std::unique_ptr +FallbackRuntimeTargetDelegate::createAgentDelegate( + FrontendChannel channel, + SessionState& sessionState, + std::unique_ptr + /*previouslyExportedState*/, + const ExecutionContextDescription& /*executionContextDescription*/, + RuntimeExecutor /*runtimeExecutor*/) { + return std::make_unique( + std::move(channel), sessionState, engineDescription_); +} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h new file mode 100644 index 00000000000000..923a0d301ee022 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "InspectorInterfaces.h" +#include "RuntimeTarget.h" +#include "SessionState.h" + +#include + +namespace facebook::react::jsinspector_modern { + +/** + * A RuntimeTargetDelegate that stubs out debugging functionality for a + * JavaScript runtime that does not natively support debugging. + */ +class FallbackRuntimeTargetDelegate : public RuntimeTargetDelegate { + public: + explicit FallbackRuntimeTargetDelegate(std::string engineDescription); + + std::unique_ptr createAgentDelegate( + FrontendChannel channel, + SessionState& sessionState, + std::unique_ptr + previouslyExportedState, + const ExecutionContextDescription& executionContextDescription, + RuntimeExecutor runtimeExecutor) override; + + private: + std::string engineDescription_; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h b/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h index 979232da29ff1e..23c9d3eaeeea52 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/ReactCdp.h @@ -8,7 +8,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index 4c4ff8b475abc3..ae8300ef9799e6 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -55,7 +55,8 @@ class JsiIntegrationPortableTest : public Test, private HostTargetDelegate { JsiIntegrationPortableTest() : engineAdapter_{immediateExecutor_} { instance_ = &page_->registerInstance(instanceTargetDelegate_); runtimeTarget_ = &instance_->registerRuntime( - *engineAdapter_, engineAdapter_->getRuntimeExecutor()); + engineAdapter_->getRuntimeTargetDelegate(), + engineAdapter_->getRuntimeExecutor()); } ~JsiIntegrationPortableTest() override { @@ -96,7 +97,8 @@ class JsiIntegrationPortableTest : public Test, private HostTargetDelegate { engineAdapter_.emplace(immediateExecutor_); instance_ = &page_->registerInstance(instanceTargetDelegate_); runtimeTarget_ = &instance_->registerRuntime( - *engineAdapter_, engineAdapter_->getRuntimeExecutor()); + engineAdapter_->getRuntimeTargetDelegate(), + engineAdapter_->getRuntimeExecutor()); } MockRemoteConnection& fromPage() { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp index b9de7fd82a674a..e7afe3e74667bd 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp @@ -18,20 +18,14 @@ namespace facebook::react::jsinspector_modern { JsiIntegrationTestGenericEngineAdapter::JsiIntegrationTestGenericEngineAdapter( folly::Executor& jsExecutor) - : runtime_{hermes::makeHermesRuntime()}, jsExecutor_{jsExecutor} {} - -std::unique_ptr -JsiIntegrationTestGenericEngineAdapter::createAgentDelegate( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr, - const ExecutionContextDescription& /*executionContextDescription*/, - RuntimeExecutor /*runtimeExecutor*/) { - return std::unique_ptr( - new FallbackRuntimeAgentDelegate( - frontendChannel, - sessionState, - "Generic engine (" + runtime_->description() + ")")); + : runtime_{hermes::makeHermesRuntime()}, + jsExecutor_{jsExecutor}, + runtimeTargetDelegate_{ + "Generic engine (" + runtime_->description() + ")"} {} + +RuntimeTargetDelegate& +JsiIntegrationTestGenericEngineAdapter::getRuntimeTargetDelegate() { + return runtimeTargetDelegate_; } jsi::Runtime& JsiIntegrationTestGenericEngineAdapter::getRuntime() diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h index 5a03ae654f0bab..b6016e25c32179 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include @@ -21,17 +22,11 @@ namespace facebook::react::jsinspector_modern { * JSI-compatible engine, with no engine-specific CDP support. Uses Hermes under * the hood, without Hermes's CDP support. */ -class JsiIntegrationTestGenericEngineAdapter : public RuntimeTargetDelegate { +class JsiIntegrationTestGenericEngineAdapter { public: explicit JsiIntegrationTestGenericEngineAdapter(folly::Executor& jsExecutor); - virtual std::unique_ptr createAgentDelegate( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const ExecutionContextDescription& executionContextDescription, - RuntimeExecutor runtimeExecutor) override; + RuntimeTargetDelegate& getRuntimeTargetDelegate(); jsi::Runtime& getRuntime() const noexcept; @@ -40,6 +35,7 @@ class JsiIntegrationTestGenericEngineAdapter : public RuntimeTargetDelegate { private: std::unique_ptr runtime_; folly::Executor& jsExecutor_; + jsinspector_modern::FallbackRuntimeTargetDelegate runtimeTargetDelegate_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp index bffc056dd7ec4f..eb4fdfdedf9ecf 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp @@ -17,22 +17,11 @@ JsiIntegrationTestHermesEngineAdapter::JsiIntegrationTestHermesEngineAdapter( folly::Executor& jsExecutor) : runtime_{hermes::makeHermesRuntime()}, jsExecutor_{jsExecutor}, - targetDelegate_{runtime_} {} - -std::unique_ptr -JsiIntegrationTestHermesEngineAdapter::createAgentDelegate( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const ExecutionContextDescription& executionContextDescription, - RuntimeExecutor runtimeExecutor) { - return targetDelegate_.createAgentDelegate( - std::move(frontendChannel), - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - std::move(runtimeExecutor)); + runtimeTargetDelegate_{runtime_} {} + +RuntimeTargetDelegate& +JsiIntegrationTestHermesEngineAdapter::getRuntimeTargetDelegate() { + return runtimeTargetDelegate_; } jsi::Runtime& JsiIntegrationTestHermesEngineAdapter::getRuntime() diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h index d2291661394bcb..dd0f273eb17b28 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h @@ -22,17 +22,11 @@ namespace facebook::react::jsinspector_modern { * An engine adapter for JsiIntegrationTest that uses Hermes (and Hermes's * CDP support). */ -class JsiIntegrationTestHermesEngineAdapter : public RuntimeTargetDelegate { +class JsiIntegrationTestHermesEngineAdapter { public: explicit JsiIntegrationTestHermesEngineAdapter(folly::Executor& jsExecutor); - virtual std::unique_ptr createAgentDelegate( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const ExecutionContextDescription& executionContextDescription, - RuntimeExecutor runtimeExecutor) override; + RuntimeTargetDelegate& getRuntimeTargetDelegate(); jsi::Runtime& getRuntime() const noexcept; @@ -41,7 +35,7 @@ class JsiIntegrationTestHermesEngineAdapter : public RuntimeTargetDelegate { private: std::shared_ptr runtime_; folly::Executor& jsExecutor_; - HermesRuntimeTargetDelegate targetDelegate_; + HermesRuntimeTargetDelegate runtimeTargetDelegate_; }; } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp index e868f1c12691d4..ed5b97fa432f5d 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.cpp @@ -18,18 +18,12 @@ JSIRuntimeHolder::JSIRuntimeHolder(std::unique_ptr runtime) assert(runtime_ != nullptr); } -std::unique_ptr -JSIRuntimeHolder::createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) { - (void)executionContextDescription; - (void)runtimeExecutor; - return std::make_unique( - std::move(frontendChannel), sessionState, runtime_->description()); +jsinspector_modern::RuntimeTargetDelegate& +JSRuntime::getRuntimeTargetDelegate() { + if (!runtimeTargetDelegate_) { + runtimeTargetDelegate_.emplace(getRuntime().description()); + } + return *runtimeTargetDelegate_; } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h index 34d1cace4e5ce3..dca9c1ac25c7b0 100644 --- a/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h +++ b/packages/react-native/ReactCommon/react/runtime/JSRuntimeFactory.h @@ -17,11 +17,26 @@ namespace facebook::react { /** * An interface that represents an instance of a JS VM */ -class JSRuntime : public jsinspector_modern::RuntimeTargetDelegate { +class JSRuntime { public: virtual jsi::Runtime& getRuntime() noexcept = 0; virtual ~JSRuntime() = default; + + /** + * Get a reference to the \c RuntimeTargetDelegate owned (or implemented) by + * this JSRuntime. This reference must remain valid for the duration of the + * JSRuntime's lifetime. + */ + virtual jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate(); + + private: + /** + * Initialized by \c getRuntimeTargetDelegate if not overridden, and then + * never changes. + */ + std::optional + runtimeTargetDelegate_; }; /** @@ -41,14 +56,6 @@ class JSRuntimeFactory { class JSIRuntimeHolder : public JSRuntime { public: jsi::Runtime& getRuntime() noexcept override; - std::unique_ptr createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) override; explicit JSIRuntimeHolder(std::unique_ptr runtime); diff --git a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp index 392ab7513d0b91..c95b10d7575c17 100644 --- a/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/ReactInstance.cpp @@ -103,8 +103,8 @@ ReactInstance::ReactInstance( // * On Android it's because we explicitly wait for the instance // creation task to finish before starting the destruction. inspectorTarget_ = &hostTarget.registerInstance(*this); - runtimeInspectorTarget_ = - &inspectorTarget_->registerRuntime(*runtime_, runtimeExecutor); + runtimeInspectorTarget_ = &inspectorTarget_->registerRuntime( + runtime_->getRuntimeTargetDelegate(), runtimeExecutor); runtimeExecutorThatWaitsForInspectorSetup->flush(); }); diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index 58e8af3c62d19d..3a32d353ce851c 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -101,20 +101,9 @@ class HermesJSRuntime : public JSRuntime { return *runtime_; } - std::unique_ptr createAgentDelegate( - jsinspector_modern::FrontendChannel frontendChannel, - jsinspector_modern::SessionState& sessionState, - std::unique_ptr - previouslyExportedState, - const jsinspector_modern::ExecutionContextDescription& - executionContextDescription, - RuntimeExecutor runtimeExecutor) override { - return targetDelegate_.createAgentDelegate( - std::move(frontendChannel), - sessionState, - std::move(previouslyExportedState), - executionContextDescription, - std::move(runtimeExecutor)); + jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate() + override { + return targetDelegate_; } private: From 641a9c468f902841171038ea229f12d72241fa1b Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 11 Mar 2024 09:09:52 -0700 Subject: [PATCH 138/361] Move lifecycle listener inside JavaTimerManager (#43338) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43338 Reafactor JavaTimerManager so more code is shared between bridge and bridgeless. Note that HeadlessJSTaskContext is not currently configured when using bridgeless. Changelog: [Internal] Reviewed By: rshest Differential Revision: D54496604 fbshipit-source-id: 2a61294267df372e69f8316dd8f8059625d0a2bd --- .../ReactAndroid/api/ReactAndroid.api | 19 +-- .../react/modules/core/JavaTimerManager.java | 13 +- .../react/modules/core/TimingModule.java | 77 +++------- .../facebook/react/runtime/ReactInstance.java | 21 +-- .../react/modules/timing/TimingModuleTest.kt | 141 ++++++++++-------- 5 files changed, 119 insertions(+), 152 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 8eadbcf684f539..24fe604b68b387 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3032,7 +3032,7 @@ public abstract interface class com/facebook/react/modules/core/JavaScriptTimerE public abstract fun emitTimeDriftWarning (Ljava/lang/String;)V } -public class com/facebook/react/modules/core/JavaTimerManager { +public class com/facebook/react/modules/core/JavaTimerManager : com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/jstasks/HeadlessJsTaskEventListener { public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/react/modules/core/JavaScriptTimerExecutor;Lcom/facebook/react/modules/core/ReactChoreographer;Lcom/facebook/react/devsupport/interfaces/DevSupportManager;)V public fun createAndMaybeCallTimer (IIDZ)V public fun createTimer (IJZ)V @@ -3078,27 +3078,18 @@ public final class com/facebook/react/modules/core/ReactChoreographer$CallbackTy public static fun values ()[Lcom/facebook/react/modules/core/ReactChoreographer$CallbackType; } -public final class com/facebook/react/modules/core/TimingModule : com/facebook/fbreact/specs/NativeTimingSpec, com/facebook/react/bridge/LifecycleEventListener, com/facebook/react/jstasks/HeadlessJsTaskEventListener { +public final class com/facebook/react/modules/core/TimingModule : com/facebook/fbreact/specs/NativeTimingSpec, com/facebook/react/modules/core/JavaScriptTimerExecutor { public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/react/devsupport/interfaces/DevSupportManager;)V + public fun callIdleCallbacks (D)V + public fun callTimers (Lcom/facebook/react/bridge/WritableArray;)V public fun createTimer (DDDZ)V public fun deleteTimer (D)V + public fun emitTimeDriftWarning (Ljava/lang/String;)V public fun initialize ()V public fun invalidate ()V - public fun onHeadlessJsTaskFinish (I)V - public fun onHeadlessJsTaskStart (I)V - public fun onHostDestroy ()V - public fun onHostPause ()V - public fun onHostResume ()V public fun setSendIdleEvents (Z)V } -public class com/facebook/react/modules/core/TimingModule$BridgeTimerExecutor : com/facebook/react/modules/core/JavaScriptTimerExecutor { - public fun (Lcom/facebook/react/modules/core/TimingModule;)V - public fun callIdleCallbacks (D)V - public fun callTimers (Lcom/facebook/react/bridge/WritableArray;)V - public fun emitTimeDriftWarning (Ljava/lang/String;)V -} - public class com/facebook/react/modules/debug/DevSettingsModule : com/facebook/fbreact/specs/NativeDevSettingsSpec { public fun (Lcom/facebook/react/bridge/ReactApplicationContext;Lcom/facebook/react/devsupport/interfaces/DevSupportManager;)V public fun addListener (Ljava/lang/String;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java index 5f5e1abb8f64d3..95a74b35bfb318 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/JavaTimerManager.java @@ -12,12 +12,14 @@ import androidx.annotation.Nullable; import com.facebook.proguard.annotations.DoNotStrip; import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.UiThreadUtil; import com.facebook.react.bridge.WritableArray; import com.facebook.react.common.SystemClock; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.jstasks.HeadlessJsTaskContext; +import com.facebook.react.jstasks.HeadlessJsTaskEventListener; import java.util.Comparator; import java.util.PriorityQueue; import java.util.concurrent.atomic.AtomicBoolean; @@ -28,7 +30,7 @@ * *

This is used by the NativeModule {@link TimingModule}. */ -public class JavaTimerManager { +public class JavaTimerManager implements LifecycleEventListener, HeadlessJsTaskEventListener { // These timing constants should be kept in sync with the ones in `JSTimers.js`. // The minimum time in milliseconds left in the frame to call idle callbacks. @@ -196,19 +198,24 @@ public int compare(Timer lhs, Timer rhs) { } }); mTimerIdsToTimers = new SparseArray<>(); + + mReactApplicationContext.addLifecycleEventListener(this); } + @Override public void onHostPause() { isPaused.set(true); clearFrameCallback(); maybeIdleCallback(); } + @Override public void onHostDestroy() { clearFrameCallback(); maybeIdleCallback(); } + @Override public void onHostResume() { isPaused.set(false); // TODO(5195192) Investigate possible problems related to restarting all tasks at the same @@ -217,6 +224,7 @@ public void onHostResume() { maybeSetChoreographerIdleCallback(); } + @Override public void onHeadlessJsTaskStart(int taskId) { if (!isRunningTasks.getAndSet(true)) { setChoreographerCallback(); @@ -224,6 +232,7 @@ public void onHeadlessJsTaskStart(int taskId) { } } + @Override public void onHeadlessJsTaskFinish(int taskId) { HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(mReactApplicationContext); @@ -235,6 +244,8 @@ public void onHeadlessJsTaskFinish(int taskId) { } public void onInstanceDestroy() { + mReactApplicationContext.removeLifecycleEventListener(this); + clearFrameCallback(); clearChoreographerIdleCallback(); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java index 73149ef7374250..af70e66e3ebe2b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/core/TimingModule.java @@ -8,49 +8,16 @@ package com.facebook.react.modules.core; import com.facebook.fbreact.specs.NativeTimingSpec; -import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.WritableArray; import com.facebook.react.common.annotations.VisibleForTesting; import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.jstasks.HeadlessJsTaskContext; -import com.facebook.react.jstasks.HeadlessJsTaskEventListener; import com.facebook.react.module.annotations.ReactModule; /** Native module for JS timer execution. Timers fire on frame boundaries. */ @ReactModule(name = NativeTimingSpec.NAME) -public final class TimingModule extends NativeTimingSpec - implements LifecycleEventListener, HeadlessJsTaskEventListener { - - public class BridgeTimerExecutor implements JavaScriptTimerExecutor { - @Override - public void callTimers(WritableArray timerIDs) { - ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); - - if (reactApplicationContext != null) { - reactApplicationContext.getJSModule(JSTimers.class).callTimers(timerIDs); - } - } - - @Override - public void callIdleCallbacks(double frameTime) { - ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); - - if (reactApplicationContext != null) { - reactApplicationContext.getJSModule(JSTimers.class).callIdleCallbacks(frameTime); - } - } - - @Override - public void emitTimeDriftWarning(String warningMessage) { - ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); - - if (reactApplicationContext != null) { - reactApplicationContext.getJSModule(JSTimers.class).emitTimeDriftWarning(warningMessage); - } - } - } - +public final class TimingModule extends NativeTimingSpec implements JavaScriptTimerExecutor { private final JavaTimerManager mJavaTimerManager; public TimingModule(ReactApplicationContext reactContext, DevSupportManager devSupportManager) { @@ -58,18 +25,14 @@ public TimingModule(ReactApplicationContext reactContext, DevSupportManager devS mJavaTimerManager = new JavaTimerManager( - reactContext, - new BridgeTimerExecutor(), - ReactChoreographer.getInstance(), - devSupportManager); + reactContext, this, ReactChoreographer.getInstance(), devSupportManager); } @Override public void initialize() { - getReactApplicationContext().addLifecycleEventListener(this); HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext()); - headlessJsTaskContext.addTaskEventListener(this); + headlessJsTaskContext.addTaskEventListener(mJavaTimerManager); } @Override @@ -97,28 +60,30 @@ public void setSendIdleEvents(final boolean sendIdleEvents) { } @Override - public void onHostResume() { - mJavaTimerManager.onHostResume(); - } + public void callTimers(WritableArray timerIDs) { + ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); - @Override - public void onHostPause() { - mJavaTimerManager.onHostPause(); + if (reactApplicationContext != null) { + reactApplicationContext.getJSModule(JSTimers.class).callTimers(timerIDs); + } } @Override - public void onHostDestroy() { - mJavaTimerManager.onHostDestroy(); - } + public void callIdleCallbacks(double frameTime) { + ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); - @Override - public void onHeadlessJsTaskStart(int taskId) { - mJavaTimerManager.onHeadlessJsTaskStart(taskId); + if (reactApplicationContext != null) { + reactApplicationContext.getJSModule(JSTimers.class).callIdleCallbacks(frameTime); + } } @Override - public void onHeadlessJsTaskFinish(int taskId) { - mJavaTimerManager.onHeadlessJsTaskFinish(taskId); + public void emitTimeDriftWarning(String warningMessage) { + ReactApplicationContext reactApplicationContext = getReactApplicationContextIfActiveOrWarn(); + + if (reactApplicationContext != null) { + reactApplicationContext.getJSModule(JSTimers.class).emitTimeDriftWarning(warningMessage); + } } @Override @@ -127,9 +92,9 @@ public void invalidate() { HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(reactApplicationContext); - headlessJsTaskContext.removeTaskEventListener(this); + headlessJsTaskContext.removeTaskEventListener(mJavaTimerManager); + mJavaTimerManager.onInstanceDestroy(); - reactApplicationContext.removeLifecycleEventListener(this); } @VisibleForTesting diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 1a748d6c7298a4..2de6a51fa0ff4b 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -21,7 +21,6 @@ import com.facebook.react.bridge.JSBundleLoader; import com.facebook.react.bridge.JSBundleLoaderDelegate; import com.facebook.react.bridge.JavaScriptContextHolder; -import com.facebook.react.bridge.LifecycleEventListener; import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeMap; import com.facebook.react.bridge.NativeModule; @@ -143,6 +142,7 @@ final class ReactInstance { if (useDevSupport) { devSupportManager.startInspector(); } + JSTimerExecutor jsTimerExecutor = createJSTimerExecutor(); mJavaTimerManager = new JavaTimerManager( @@ -151,24 +151,6 @@ final class ReactInstance { ReactChoreographer.getInstance(), devSupportManager); - mBridgelessReactContext.addLifecycleEventListener( - new LifecycleEventListener() { - @Override - public void onHostResume() { - mJavaTimerManager.onHostResume(); - } - - @Override - public void onHostPause() { - mJavaTimerManager.onHostPause(); - } - - @Override - public void onHostDestroy() { - mJavaTimerManager.onHostDestroy(); - } - }); - JSRuntimeFactory jsRuntimeFactory = mDelegate.getJsRuntimeFactory(); BindingsInstaller bindingsInstaller = mDelegate.getBindingsInstaller(); // Notify JS if profiling is enabled @@ -448,6 +430,7 @@ public Collection getNativeModules() { mQueueConfiguration.destroy(); mTurboModuleManager.invalidate(); mFabricUIManager.invalidate(); + mJavaTimerManager.onInstanceDestroy(); mHybridData.resetNative(); mComponentNameResolverManager = null; mUIConstantsProviderManager = null; diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt index 116f1c122872eb..86011414ab33a7 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt @@ -7,14 +7,19 @@ package com.facebook.react.modules.timing +import android.content.Context import android.view.Choreographer.FrameCallback import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.CatalystInstance import com.facebook.react.bridge.JavaOnlyArray +import com.facebook.react.bridge.JavaOnlyMap import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.bridge.WritableArray import com.facebook.react.common.SystemClock import com.facebook.react.devsupport.interfaces.DevSupportManager +import com.facebook.react.jstasks.HeadlessJsTaskConfig +import com.facebook.react.jstasks.HeadlessJsTaskContext +import com.facebook.react.modules.appregistry.AppRegistry import com.facebook.react.modules.core.JSTimers import com.facebook.react.modules.core.ReactChoreographer import com.facebook.react.modules.core.ReactChoreographer.CallbackType @@ -27,9 +32,12 @@ import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.eq import org.mockito.MockedStatic +import org.mockito.Mockito.doAnswer +import org.mockito.Mockito.doReturn import org.mockito.Mockito.mock import org.mockito.Mockito.mockStatic import org.mockito.Mockito.reset +import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.`when` as whenever @@ -43,12 +51,14 @@ class TimingModuleTest { const val FRAME_TIME_NS = 17 * 1000 * 1000 } + private lateinit var reactContext: ReactApplicationContext + private lateinit var headlessContext: HeadlessJsTaskContext private lateinit var timingModule: TimingModule private lateinit var reactChoreographerMock: ReactChoreographer private lateinit var postFrameCallbackHandler: PostFrameCallbackHandler private lateinit var idlePostFrameCallbackHandler: PostFrameCallbackHandler private var currentTimeNs = 0L - private lateinit var jSTimersMock: JSTimers + private lateinit var jsTimersMock: JSTimers private lateinit var arguments: MockedStatic private lateinit var systemClock: MockedStatic private lateinit var reactChoreographer: MockedStatic @@ -82,9 +92,11 @@ class TimingModuleTest { .thenAnswer { reactChoreographerMock } val reactInstance = mock(CatalystInstance::class.java) - val reactContext = mock(ReactApplicationContext::class.java) - whenever(reactContext.catalystInstance).thenReturn(reactInstance) - whenever(reactContext.hasActiveReactInstance()).thenReturn(true) + reactContext = spy(ReactApplicationContext(mock(Context::class.java))) + doReturn(reactInstance).`when`(reactContext).catalystInstance + doReturn(true).`when`(reactContext).hasActiveReactInstance() + + headlessContext = HeadlessJsTaskContext.getInstance(reactContext) postFrameCallbackHandler = PostFrameCallbackHandler() idlePostFrameCallbackHandler = PostFrameCallbackHandler() @@ -95,7 +107,6 @@ class TimingModuleTest { .thenAnswer { return@thenAnswer postFrameCallbackHandler.answer(it) } - whenever( reactChoreographerMock.postFrameCallback( eq(CallbackType.IDLE_EVENT), any(FrameCallback::class.java))) @@ -104,12 +115,17 @@ class TimingModuleTest { } timingModule = TimingModule(reactContext, mock(DevSupportManager::class.java)) - jSTimersMock = mock(JSTimers::class.java) - whenever(reactContext.getJSModule(JSTimers::class.java)).thenReturn(jSTimersMock) - whenever(reactContext.runOnJSQueueThread(any(Runnable::class.java))).thenAnswer { invocation -> - (invocation.arguments[0] as Runnable).run() - return@thenAnswer true - } + jsTimersMock = mock(JSTimers::class.java) + doReturn(jsTimersMock).`when`(reactContext).getJSModule(JSTimers::class.java) + doReturn(mock(AppRegistry::class.java)) + .`when`(reactContext) + .getJSModule(AppRegistry::class.java) + doAnswer({ invocation -> + (invocation.arguments[0] as Runnable).run() + return@doAnswer true + }) + .`when`(reactContext) + .runOnJSQueueThread(any(Runnable::class.java)) timingModule.initialize() } @@ -134,111 +150,113 @@ class TimingModuleTest { @Test fun testSimpleTimer() { - timingModule.onHostResume() + reactContext.onHostResume(null) timingModule.createTimer(1.0, 1.0, 0.0, false) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(1.0)) - reset(jSTimersMock) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(1.0)) + reset(jsTimersMock) stepChoreographerFrame() - verifyNoMoreInteractions(jSTimersMock) + verifyNoMoreInteractions(jsTimersMock) } @Test fun testSimpleRecurringTimer() { timingModule.createTimer(100.0, 1.0, 0.0, true) - timingModule.onHostResume() + reactContext.onHostResume(null) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(100.0)) - reset(jSTimersMock) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(100.0)) + reset(jsTimersMock) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(100.0)) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(100.0)) } @Test fun testCancelRecurringTimer() { - timingModule.onHostResume() + reactContext.onHostResume(null) timingModule.createTimer(105.0, 1.0, 0.0, true) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(105.0)) - reset(jSTimersMock) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(105.0)) + reset(jsTimersMock) timingModule.deleteTimer(105.0) stepChoreographerFrame() - verifyNoMoreInteractions(jSTimersMock) + verifyNoMoreInteractions(jsTimersMock) } @Test fun testPausingAndResuming() { - timingModule.onHostResume() + reactContext.onHostResume(null) timingModule.createTimer(41.0, 1.0, 0.0, true) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHostPause() + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + reactContext.onHostPause() stepChoreographerFrame() - verifyNoMoreInteractions(jSTimersMock) - reset(jSTimersMock) - timingModule.onHostResume() + verifyNoMoreInteractions(jsTimersMock) + reset(jsTimersMock) + reactContext.onHostResume(null) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) } @Test fun testHeadlessJsTaskInBackground() { - timingModule.onHostPause() - timingModule.onHeadlessJsTaskStart(42) + reactContext.onHostPause() + val taskConfig = HeadlessJsTaskConfig("foo", JavaOnlyMap()) + val taskId = headlessContext.startTask(taskConfig) timingModule.createTimer(41.0, 1.0, 0.0, true) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHeadlessJsTaskFinish(42) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + headlessContext.finishTask(taskId) stepChoreographerFrame() - verifyNoMoreInteractions(jSTimersMock) + verifyNoMoreInteractions(jsTimersMock) } @Test fun testHeadlessJsTaskInForeground() { - timingModule.onHostResume() - timingModule.onHeadlessJsTaskStart(42) + val taskConfig = HeadlessJsTaskConfig("foo", JavaOnlyMap()) + val taskId = headlessContext.startTask(taskConfig) + reactContext.onHostResume(null) timingModule.createTimer(41.0, 1.0, 0.0, true) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHeadlessJsTaskFinish(42) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + headlessContext.finishTask(taskId) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHostPause() - verifyNoMoreInteractions(jSTimersMock) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + reactContext.onHostPause() + verifyNoMoreInteractions(jsTimersMock) } @Test fun testHeadlessJsTaskIntertwine() { - timingModule.onHostResume() - timingModule.onHeadlessJsTaskStart(42) timingModule.createTimer(41.0, 1.0, 0.0, true) - timingModule.onHostPause() + reactContext.onHostPause() + val taskConfig = HeadlessJsTaskConfig("foo", JavaOnlyMap()) + val taskId = headlessContext.startTask(taskConfig) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHostResume() - timingModule.onHeadlessJsTaskFinish(42) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + reactContext.onHostResume(null) + headlessContext.finishTask(taskId) stepChoreographerFrame() - verify(jSTimersMock).callTimers(JavaOnlyArray.of(41.0)) - reset(jSTimersMock) - timingModule.onHostPause() + verify(jsTimersMock).callTimers(JavaOnlyArray.of(41.0)) + reset(jsTimersMock) + reactContext.onHostPause() stepChoreographerFrame() - verifyNoMoreInteractions(jSTimersMock) + verifyNoMoreInteractions(jsTimersMock) } @Test fun testSetTimeoutZero() { timingModule.createTimer(100.0, 0.0, 0.0, false) - verify(jSTimersMock).callTimers(JavaOnlyArray.of(100.0)) + verify(jsTimersMock).callTimers(JavaOnlyArray.of(100.0)) } @Test fun testActiveTimersInRange() { - timingModule.onHostResume() + reactContext.onHostResume(null) assertThat(timingModule.hasActiveTimersInRange(100)).isFalse timingModule.createTimer(41.0, 1.0, 0.0, true) assertThat(timingModule.hasActiveTimersInRange(100)).isFalse // Repeating @@ -250,13 +268,12 @@ class TimingModuleTest { @Test fun testIdleCallback() { timingModule.setSendIdleEvents(true) - timingModule.onHostResume() + reactContext.onHostResume(null) stepChoreographerFrame() - verify(jSTimersMock).callIdleCallbacks(SystemClock.currentTimeMillis().toDouble()) + verify(jsTimersMock).callIdleCallbacks(SystemClock.currentTimeMillis().toDouble()) } private class PostFrameCallbackHandler : Answer { - private var frameCallback: FrameCallback? = null override fun answer(invocation: InvocationOnMock) { From aeb250430dc272d9a185a0466569b5132225262e Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Mon, 11 Mar 2024 09:30:53 -0700 Subject: [PATCH 139/361] Make FallbackRuntimeAgentDelegate private (#43348) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43348 Changelog: [Internal] Followup from D54585658. Moves the branching on `HERMES_DEBUGGER_ENABLED` into `HermesRuntimeTargetDelegate`, and correspondingly makes `FallbackRuntimeAgentDelegate` private (not exposed directly to integrators). Reviewed By: huntie Differential Revision: D54587558 fbshipit-source-id: 554b41356c1421a508c1a788d7c27f53445ecb6b --- .../chrome/HermesRuntimeAgentDelegate.cpp | 40 ++----------------- .../chrome/HermesRuntimeAgentDelegate.h | 9 ++++- .../chrome/HermesRuntimeAgentDelegateNew.cpp | 35 ++-------------- .../chrome/HermesRuntimeAgentDelegateNew.h | 9 ++++- .../chrome/HermesRuntimeTargetDelegate.cpp | 39 ++++++++++++------ ...JsiIntegrationTestGenericEngineAdapter.cpp | 2 - 6 files changed, 48 insertions(+), 86 deletions(-) diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp index 3b1d1caa11c1e0..2641d55c009830 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp @@ -5,20 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -#include "HermesRuntimeAgentDelegate.h" +#ifdef HERMES_ENABLE_DEBUGGER -// If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes -// CDPHandler headers or types. +#include "HermesRuntimeAgentDelegate.h" -#ifdef HERMES_ENABLE_DEBUGGER #include #include -#else // HERMES_ENABLE_DEBUGGER -// TODO(moti): FallbackRuntimeAgentDelegate should be private. We should fall -// back at the *TargetDelegate* level, in HermesRuntimeTargetDelegate, rather -// than within HermesRuntimeAgentDelegate. -#include -#endif // HERMES_ENABLE_DEBUGGER #include #include @@ -27,8 +19,6 @@ using namespace facebook::hermes; namespace facebook::react::jsinspector_modern { -#ifdef HERMES_ENABLE_DEBUGGER - namespace { /** @@ -178,30 +168,6 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate { std::shared_ptr hermes_; }; -#else // !HERMES_ENABLE_DEBUGGER - -/** - * A stub for HermesRuntimeAgentDelegate when Hermes is compiled without - * debugging support. - */ -class HermesRuntimeAgentDelegate::Impl final - : public FallbackRuntimeAgentDelegate { - public: - Impl( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr, - const ExecutionContextDescription&, - std::shared_ptr runtime, - RuntimeExecutor) - : FallbackRuntimeAgentDelegate( - std::move(frontendChannel), - sessionState, - runtime->description()) {} -}; - -#endif // HERMES_ENABLE_DEBUGGER - HermesRuntimeAgentDelegate::HermesRuntimeAgentDelegate( FrontendChannel frontendChannel, SessionState& sessionState, @@ -229,3 +195,5 @@ HermesRuntimeAgentDelegate::getExportedState() { } } // namespace facebook::react::jsinspector_modern + +#endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h index 52614c9474a8fa..22bf33bf86272c 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.h @@ -7,6 +7,8 @@ #pragma once +#ifdef HERMES_ENABLE_DEBUGGER + #include #include @@ -61,11 +63,14 @@ class HermesRuntimeAgentDelegate : public RuntimeAgentDelegate { virtual std::unique_ptr getExportedState() override; private: - // We use the private implementation idiom to keep HERMES_ENABLE_DEBUGGER - // checks out of the header. class Impl; const std::unique_ptr impl_; }; } // namespace facebook::react::jsinspector_modern + +#else +#error \ + "HERMES_ENABLE_DEBUGGER must be enabled to use HermesRuntimeAgentDelegate." +#endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp index 429b7e69132edd..2f628aef9d1540 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp @@ -5,18 +5,16 @@ * LICENSE file in the root directory of this source tree. */ +#ifdef HERMES_ENABLE_DEBUGGER + #include "HermesRuntimeAgentDelegateNew.h" // If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes // CDP headers or types. -#ifdef HERMES_ENABLE_DEBUGGER #include #include #include -#else // HERMES_ENABLE_DEBUGGER -#include -#endif // HERMES_ENABLE_DEBUGGER #include #include @@ -25,8 +23,6 @@ using namespace facebook::hermes; namespace facebook::react::jsinspector_modern { -#ifdef HERMES_ENABLE_DEBUGGER - class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { public: Impl( @@ -81,31 +77,6 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { std::unique_ptr hermes_; }; -#else // !HERMES_ENABLE_DEBUGGER - -/** - * A stub for HermesRuntimeAgentDelegateNew when Hermes is compiled without - * debugging support. - */ -class HermesRuntimeAgentDelegateNew::Impl final - : public FallbackRuntimeAgentDelegate { - public: - Impl( - FrontendChannel frontendChannel, - SessionState& sessionState, - std::unique_ptr, - const ExecutionContextDescription&, - HermesRuntime& runtime, - HermesRuntimeTargetDelegate& runtimeTargetDelegate, - RuntimeExecutor) - : FallbackRuntimeAgentDelegate( - std::move(frontendChannel), - sessionState, - runtime.description()) {} -}; - -#endif // HERMES_ENABLE_DEBUGGER - HermesRuntimeAgentDelegateNew::HermesRuntimeAgentDelegateNew( FrontendChannel frontendChannel, SessionState& sessionState, @@ -130,3 +101,5 @@ bool HermesRuntimeAgentDelegateNew::handleRequest( } } // namespace facebook::react::jsinspector_modern + +#endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h index 2505451eb27deb..3a8e959b23fc39 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h @@ -7,6 +7,8 @@ #pragma once +#ifdef HERMES_ENABLE_DEBUGGER + #include "HermesRuntimeTargetDelegate.h" #include @@ -65,11 +67,14 @@ class HermesRuntimeAgentDelegateNew : public RuntimeAgentDelegate { bool handleRequest(const cdp::PreparsedRequest& req) override; private: - // We use the private implementation idiom to keep HERMES_ENABLE_DEBUGGER - // checks out of the header. class Impl; const std::unique_ptr impl_; }; } // namespace facebook::react::jsinspector_modern + +#else +#error \ + "HERMES_ENABLE_DEBUGGER must be enabled to use HermesRuntimeAgentDelegateNew." +#endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index fbbb1a51c37964..9c5542b08ebe78 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -8,14 +8,19 @@ #include #include -#include "HermesRuntimeAgentDelegate.h" -#include "HermesRuntimeAgentDelegateNew.h" #include "HermesRuntimeTargetDelegate.h" +// If HERMES_ENABLE_DEBUGGER isn't defined, we can't access any Hermes +// CDPHandler headers or types. #ifdef HERMES_ENABLE_DEBUGGER +#include "HermesRuntimeAgentDelegate.h" +#include "HermesRuntimeAgentDelegateNew.h" + #include using namespace facebook::hermes::cdp; +#else +#include #endif // HERMES_ENABLE_DEBUGGER #include @@ -24,9 +29,9 @@ using namespace facebook::hermes; namespace facebook::react::jsinspector_modern { -class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { - public: #ifdef HERMES_ENABLE_DEBUGGER +class HermesRuntimeTargetDelegate::Impl final : public RuntimeTargetDelegate { + public: explicit Impl( HermesRuntimeTargetDelegate& delegate, std::shared_ptr hermesRuntime) @@ -37,12 +42,6 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { CDPDebugAPI& getCDPDebugAPI() { return *cdpDebugAPI_; } -#else - explicit Impl( - HermesRuntimeTargetDelegate& delegate, - std::shared_ptr hermesRuntime) - : delegate_(delegate), runtime_(std::move(hermesRuntime)) {} -#endif // RuntimeTargetDelegate methods @@ -77,12 +76,26 @@ class HermesRuntimeTargetDelegate::Impl : public RuntimeTargetDelegate { private: HermesRuntimeTargetDelegate& delegate_; std::shared_ptr runtime_; - -#ifdef HERMES_ENABLE_DEBUGGER const std::unique_ptr cdpDebugAPI_; -#endif }; +#else + +/** + * A stub for HermesRuntimeTargetDelegate when Hermes is compiled without + * debugging support. + */ +class HermesRuntimeTargetDelegate::Impl final + : public FallbackRuntimeTargetDelegate { + public: + explicit Impl( + HermesRuntimeTargetDelegate&, + std::shared_ptr hermesRuntime) + : FallbackRuntimeTargetDelegate{hermesRuntime->description()} {} +}; + +#endif // HERMES_ENABLE_DEBUGGER + HermesRuntimeTargetDelegate::HermesRuntimeTargetDelegate( std::shared_ptr hermesRuntime) : impl_(std::make_unique(*this, std::move(hermesRuntime))) {} diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp index e7afe3e74667bd..db0e3693787729 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -#include - #include #include From 3283202248a36dbda553745afc46a3e3e2ab41a6 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 11 Mar 2024 09:40:33 -0700 Subject: [PATCH 140/361] Remove createRootView(initialProps) from ReactDelegate (#43365) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43365 Changelog: [Android][Changed] Simplified ReactActivityDelegate to expose a single createRootView method. Reviewed By: cortinico Differential Revision: D54434648 fbshipit-source-id: 305c54910a1eac25664507972879c7c6bd633466 --- .../ReactAndroid/api/ReactAndroid.api | 3 --- .../facebook/react/ReactActivityDelegate.java | 22 +++++++------------ .../com/facebook/react/ReactDelegate.java | 13 ++--------- .../com/facebook/react/ReactRootView.java | 2 +- .../defaults/DefaultReactActivityDelegate.kt | 8 ------- .../react/ReactActivityDelegateTest.kt | 10 +++------ 6 files changed, 14 insertions(+), 44 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 24fe604b68b387..462410ae4ff6bc 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -108,7 +108,6 @@ public class com/facebook/react/ReactActivityDelegate { public fun (Lcom/facebook/react/ReactActivity;Ljava/lang/String;)V protected fun composeLaunchOptions ()Landroid/os/Bundle; protected fun createRootView ()Lcom/facebook/react/ReactRootView; - protected fun createRootView (Landroid/os/Bundle;)Lcom/facebook/react/ReactRootView; protected fun getContext ()Landroid/content/Context; protected fun getLaunchOptions ()Landroid/os/Bundle; public fun getMainComponentName ()Ljava/lang/String; @@ -1954,8 +1953,6 @@ public class com/facebook/react/defaults/DefaultReactActivityDelegate : com/face public fun (Lcom/facebook/react/ReactActivity;Ljava/lang/String;Z)V public synthetic fun (Lcom/facebook/react/ReactActivity;Ljava/lang/String;ZILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun (Lcom/facebook/react/ReactActivity;Ljava/lang/String;ZZ)V - protected fun createRootView ()Lcom/facebook/react/ReactRootView; - protected fun createRootView (Landroid/os/Bundle;)Lcom/facebook/react/ReactRootView; protected fun isFabricEnabled ()Z } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index b305b390945a4c..92b63c91607615 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -31,8 +31,12 @@ public class ReactActivityDelegate { private @Nullable PermissionListener mPermissionListener; private @Nullable Callback mPermissionsCallback; - private ReactDelegate mReactDelegate; + private @Nullable ReactDelegate mReactDelegate; + /** + * Prefer using ReactActivity when possible, as it hooks up all Activity lifecycle methods by + * default. It also implements DefaultHardwareBackBtnHandler, which ReactDelegate requires. + */ @Deprecated public ReactActivityDelegate(@Nullable Activity activity, @Nullable String mainComponentName) { mActivity = activity; @@ -56,21 +60,11 @@ public ReactActivityDelegate( } protected @Nullable Bundle composeLaunchOptions() { - Bundle composedLaunchOptions = getLaunchOptions(); - if (isFabricEnabled()) { - if (composedLaunchOptions == null) { - composedLaunchOptions = new Bundle(); - } - } - return composedLaunchOptions; + return getLaunchOptions(); } protected ReactRootView createRootView() { - return new ReactRootView(getContext()); - } - - protected ReactRootView createRootView(Bundle initialProps) { - return new ReactRootView(getContext()); + return Assertions.assertNotNull(mReactDelegate).createRootView(); } /** @@ -108,7 +102,7 @@ public void onCreate(Bundle savedInstanceState) { getPlainActivity(), getReactNativeHost(), mainComponentName, launchOptions) { @Override protected ReactRootView createRootView() { - return ReactActivityDelegate.this.createRootView(launchOptions); + return ReactActivityDelegate.this.createRootView(); } }; } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 1f89ceee0f6a58..7b83e71d5d8c64 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -11,7 +11,6 @@ import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; -import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Assertions; import com.facebook.react.config.ReactFeatureFlags; @@ -75,7 +74,7 @@ public ReactDelegate( mFabricEnabled = fabricEnabled; mActivity = activity; mMainComponentName = appKey; - mLaunchOptions = composeLaunchOptions(launchOptions); + mLaunchOptions = launchOptions; mDoubleTapReloadRecognizer = new DoubleTapReloadRecognizer(); mReactNativeHost = reactNativeHost; } @@ -181,6 +180,7 @@ public ReactRootView getReactRootView() { } } + // Not used in bridgeless protected ReactRootView createRootView() { ReactRootView reactRootView = new ReactRootView(mActivity); reactRootView.setIsFabric(isFabricEnabled()); @@ -233,13 +233,4 @@ public ReactInstanceManager getReactInstanceManager() { protected boolean isFabricEnabled() { return mFabricEnabled; } - - private @NonNull Bundle composeLaunchOptions(Bundle composedLaunchOptions) { - if (isFabricEnabled()) { - if (composedLaunchOptions == null) { - composedLaunchOptions = new Bundle(); - } - } - return composedLaunchOptions; - } } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java index 766836fd0b16d1..a01f7213e1604a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactRootView.java @@ -452,7 +452,7 @@ public void startReactApplication(ReactInstanceManager reactInstanceManager, Str /** * Schedule rendering of the react component rendered by the JS application from the given JS * module (@{param moduleName}) using provided {@param reactInstanceManager} to attach to the JS - * context of that manager. Extra parameter {@param launchOptions} can be used to pass initial + * context of that manager. Extra parameter {@param initialProperties} can be used to pass initial * properties for the react component. */ @ThreadConfined(UI) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt index 07f7ce270b2da9..4cb4263c41c4d9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/defaults/DefaultReactActivityDelegate.kt @@ -7,10 +7,8 @@ package com.facebook.react.defaults -import android.os.Bundle import com.facebook.react.ReactActivity import com.facebook.react.ReactActivityDelegate -import com.facebook.react.ReactRootView /** * A utility class that allows you to simplify the setup of a [ReactActivityDelegate] for new apps @@ -43,10 +41,4 @@ public open class DefaultReactActivityDelegate( ) : this(activity, mainComponentName, fabricEnabled) override fun isFabricEnabled(): Boolean = fabricEnabled - - override fun createRootView(): ReactRootView = - ReactRootView(context).apply { setIsFabric(fabricEnabled) } - - override fun createRootView(bundle: Bundle?): ReactRootView = - ReactRootView(context).apply { setIsFabric(fabricEnabled) } } diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt index f0eb097b697008..44d33df9c4545e 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/ReactActivityDelegateTest.kt @@ -28,9 +28,7 @@ class ReactActivityDelegateTest { get() = composeLaunchOptions() } - assertNotNull(delegate.inspectLaunchOptions) - // False because oncurrentRoot is hardcoded to true for Fabric inside renderApplication - assertFalse(delegate.inspectLaunchOptions!!.containsKey("concurrentRoot")) + assertNull(delegate.inspectLaunchOptions) } @Test @@ -60,9 +58,7 @@ class ReactActivityDelegateTest { } assertNotNull(delegate.inspectLaunchOptions) - // False because oncurrentRoot is hardcoded to true for Fabric inside renderApplication - assertFalse(delegate.inspectLaunchOptions!!.containsKey("concurrentRoot")) - assertTrue(delegate.inspectLaunchOptions!!.containsKey("test-property")) - assertEquals("test-value", delegate.inspectLaunchOptions!!.getString("test-property")) + assertTrue(delegate.inspectLaunchOptions?.containsKey("test-property") ?: false) + assertEquals("test-value", delegate.inspectLaunchOptions?.getString("test-property")) } } From d66b9a5b28f6566a24298e46a304a179cd0d4b7c Mon Sep 17 00:00:00 2001 From: hurali97 Date: Mon, 11 Mar 2024 10:18:36 -0700 Subject: [PATCH 141/361] Changelog: 0.73.6 (#43412) Summary: ## Changelog: Changelog: [Internal] Generated changelog Pull Request resolved: https://github.com/facebook/react-native/pull/43412 Reviewed By: cortinico Differential Revision: D54753626 Pulled By: huntie fbshipit-source-id: c0a2348601b3d78b08ccaab570f346716d3793e6 --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ec7976b9fe596..25fbe8ec85424d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -532,6 +532,23 @@ - Bump activesupport to minimum 6.1.7.5 CVE-2023-38037. ([07a159f279](https://github.com/facebook/react-native/commit/07a159f279cdcbed29c9c437dec1c0b8ac2d852f) by [@lunaleaps](https://github.com/lunaleaps)) +## v0.73.6 + +### Breaking + +#### iOS specific + +- Rename `BUILD_FROM_SOURCE` to `RCT_BUILD_HERMES_FROM_SOURCE` ([51b80477c7](https://github.com/facebook/react-native/commit/51b80477c7836058fb29ef92c1a1908e3c8dba58) by [@cipolleschi](https://github.com/cipolleschi)) + +### Fixed + +- Fix component stacks for tsx, ts, and jsx files ([28f604a97d](https://github.com/facebook/react-native/commit/28f604a97dc57afa631a24052ae6660c13c2c761) by [@lunaleaps](https://github.com/lunaleaps)) + +#### iOS specific + +- Prevent unwanted border animation([d979491](https://github.com/facebook/react-native/commit/d9794916b0549330513fe530abf090fa48b8a776) by [@sammy-SC](https://github.com/sammy-SC)) +- Fix flipper for Xcode 15.3 ([9d22a7fd0e](https://github.com/facebook/react-native/commit/9d22a7fd0e82d6c2660217c1fb3c004ab30d6844) by [@cipolleschi](https://github.com/cipolleschi)) + ## v0.73.5 ### Security From e9e668f0eca625248a95c53a506d33a4ec389f70 Mon Sep 17 00:00:00 2001 From: Rick Hanlon Date: Mon, 11 Mar 2024 10:29:06 -0700 Subject: [PATCH 142/361] Symbolicate component stacks (#43166) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43166 # Overview This diff adds support for symbolicating component stacks that provide the new stack frame formatting. It currently switches between a `componentStackType` value to enable stack frame parsing, but once the feature flag lands we can clean this up so that the type of `ComponentStack` is always just `Array` ## Screen ### With stack frame component stacks {F1459181398} ## Legacy version {F1463451637} Changelog: [General][Fixed] - Support component stacks without source info. Reviewed By: yungsters Differential Revision: D53984570 fbshipit-source-id: 68afbe70b65c7a8861d049bebe0659dbe1db146f --- .../Libraries/LogBox/Data/LogBoxLog.js | 109 ++++++++++++++++++ .../Data/__tests__/parseLogBoxLog-test.js | 51 ++++++++ .../Libraries/LogBox/Data/parseLogBoxLog.js | 85 ++++++++++---- .../LogBox/UI/LogBoxInspectorReactFrames.js | 13 ++- .../LogBoxInspector-test.js.snap | 12 ++ .../LogBoxInspectorContainer-test.js.snap | 24 ++++ .../LogBoxNotificationContainer-test.js.snap | 12 ++ .../__snapshots__/public-api-test.js.snap | 25 +++- 8 files changed, 301 insertions(+), 30 deletions(-) diff --git a/packages/react-native/Libraries/LogBox/Data/LogBoxLog.js b/packages/react-native/Libraries/LogBox/Data/LogBoxLog.js index a7f5a9fb5ba11c..bf5d92c451cd96 100644 --- a/packages/react-native/Libraries/LogBox/Data/LogBoxLog.js +++ b/packages/react-native/Libraries/LogBox/Data/LogBoxLog.js @@ -13,6 +13,7 @@ import type { Category, CodeFrame, ComponentStack, + ComponentStackType, Message, } from './parseLogBoxLog'; @@ -22,12 +23,45 @@ type SymbolicationStatus = 'NONE' | 'PENDING' | 'COMPLETE' | 'FAILED'; export type LogLevel = 'warn' | 'error' | 'fatal' | 'syntax'; +// TODO: once component stacks are fully supported, we can refactor +// ComponentStack to just be Stack and remove these conversions fns. +function convertComponentStateToStack(componentStack: ComponentStack): Stack { + return componentStack.map(frame => ({ + column: frame?.location?.column, + file: frame.fileName, + lineNumber: frame?.location?.row, + methodName: frame.content, + collapse: false, + })); +} + +function convertStackToComponentStack(stack: Stack): ComponentStack { + const componentStack = []; + for (let i = 0; i < stack.length; i++) { + const frame = stack[i]; + // NOTE: Skip stack frames missing location. + if (frame.lineNumber != null && frame.column != null) { + componentStack.push({ + fileName: frame?.file || '', + location: { + row: frame.lineNumber, + column: frame.column, + }, + content: frame.methodName, + collapse: false, + }); + } + } + return componentStack; +} + export type LogBoxLogData = $ReadOnly<{| level: LogLevel, type?: ?string, message: Message, stack: Stack, category: string, + componentStackType?: ComponentStackType, componentStack: ComponentStack, codeFrame?: ?CodeFrame, isComponentError: boolean, @@ -39,6 +73,7 @@ class LogBoxLog { type: ?string; category: Category; componentStack: ComponentStack; + componentStackType: ComponentStackType; stack: Stack; count: number; level: LogLevel; @@ -54,6 +89,19 @@ class LogBoxLog { stack: null, status: 'NONE', }; + symbolicatedComponentStack: + | $ReadOnly<{|error: null, componentStack: null, status: 'NONE'|}> + | $ReadOnly<{|error: null, componentStack: null, status: 'PENDING'|}> + | $ReadOnly<{| + error: null, + componentStack: ComponentStack, + status: 'COMPLETE', + |}> + | $ReadOnly<{|error: Error, componentStack: null, status: 'FAILED'|}> = { + error: null, + componentStack: null, + status: 'NONE', + }; constructor(data: LogBoxLogData) { this.level = data.level; @@ -62,6 +110,7 @@ class LogBoxLog { this.stack = data.stack; this.category = data.category; this.componentStack = data.componentStack; + this.componentStackType = data.componentStackType || 'legacy'; this.codeFrame = data.codeFrame; this.isComponentError = data.isComponentError; this.extraData = data.extraData; @@ -78,6 +127,15 @@ class LogBoxLog { : this.stack; } + getAvailableComponentStack(): ComponentStack { + if (this.componentStackType === 'legacy') { + return this.componentStack; + } + return this.symbolicatedComponentStack.status === 'COMPLETE' + ? this.symbolicatedComponentStack.componentStack + : this.componentStack; + } + retrySymbolicate(callback?: (status: SymbolicationStatus) => void): void { if (this.symbolicated.status !== 'COMPLETE') { LogBoxSymbolication.deleteStack(this.stack); @@ -102,6 +160,25 @@ class LogBoxLog { this.updateStatus(error, null, null, callback); }, ); + if (this.componentStack != null && this.componentStackType === 'stack') { + this.updateComponentStackStatus(null, null, null, callback); + const componentStackFrames = convertComponentStateToStack( + this.componentStack, + ); + LogBoxSymbolication.symbolicate(componentStackFrames, []).then( + data => { + this.updateComponentStackStatus( + null, + convertStackToComponentStack(data.stack), + null, + callback, + ); + }, + error => { + this.updateComponentStackStatus(error, null, null, callback); + }, + ); + } } } @@ -140,6 +217,38 @@ class LogBoxLog { callback(this.symbolicated.status); } } + + updateComponentStackStatus( + error: ?Error, + componentStack: ?ComponentStack, + codeFrame: ?CodeFrame, + callback?: (status: SymbolicationStatus) => void, + ): void { + const lastStatus = this.symbolicatedComponentStack.status; + if (error != null) { + this.symbolicatedComponentStack = { + error, + componentStack: null, + status: 'FAILED', + }; + } else if (componentStack != null) { + this.symbolicatedComponentStack = { + error: null, + componentStack, + status: 'COMPLETE', + }; + } else { + this.symbolicatedComponentStack = { + error: null, + componentStack: null, + status: 'PENDING', + }; + } + + if (callback && lastStatus !== this.symbolicatedComponentStack.status) { + callback(this.symbolicatedComponentStack.status); + } + } } export default LogBoxLog; diff --git a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js index 9d98a9d29c4459..895ccf57ec50f4 100644 --- a/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js +++ b/packages/react-native/Libraries/LogBox/Data/__tests__/parseLogBoxLog-test.js @@ -18,6 +18,7 @@ const {parseLogBoxException, parseLogBoxLog} = require('../parseLogBoxLog'); describe('parseLogBoxLog', () => { it('parses strings', () => { expect(parseLogBoxLog(['A'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: 'A', message: { @@ -29,6 +30,7 @@ describe('parseLogBoxLog', () => { it('parses strings with arguments', () => { expect(parseLogBoxLog(['A', 'B', 'C'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: 'A B C', message: { @@ -40,6 +42,7 @@ describe('parseLogBoxLog', () => { it('parses formatted strings', () => { expect(parseLogBoxLog(['%s', 'A'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: '\ufeff%s', message: { @@ -56,6 +59,7 @@ describe('parseLogBoxLog', () => { it('parses formatted strings with insufficient arguments', () => { expect(parseLogBoxLog(['%s %s', 'A'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: '\ufeff%s %s', message: { @@ -76,6 +80,7 @@ describe('parseLogBoxLog', () => { it('parses formatted strings with excess arguments', () => { expect(parseLogBoxLog(['%s', 'A', 'B'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: '\ufeff%s B', message: { @@ -92,6 +97,7 @@ describe('parseLogBoxLog', () => { it('treats "%s" in arguments as literals', () => { expect(parseLogBoxLog(['%s', '%s', 'A'])).toEqual({ + componentStackType: 'legacy', componentStack: [], category: '\ufeff%s A', message: { @@ -114,6 +120,7 @@ describe('parseLogBoxLog', () => { '\n in MyComponent (at filename.js:1)\n in MyOtherComponent (at filename2.js:1)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -147,6 +154,7 @@ describe('parseLogBoxLog', () => { 'Some kind of message\n in MyComponent (at filename.js:1)\n in MyOtherComponent (at filename2.js:1)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -174,6 +182,7 @@ describe('parseLogBoxLog', () => { '\n in MyComponent (at filename.js:1)\n in MyOtherComponent (at filename2.js:1)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -203,6 +212,7 @@ describe('parseLogBoxLog', () => { 'Some third kind of message', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -231,6 +241,7 @@ describe('parseLogBoxLog', () => { originalMessage: 'TransformError failed to transform file.', name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -245,6 +256,7 @@ describe('parseLogBoxLog', () => { substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: 'TransformError failed to transform file.', }); @@ -268,6 +280,7 @@ describe('parseLogBoxLog', () => { 200 |`, name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -291,6 +304,7 @@ describe('parseLogBoxLog', () => { substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js-199-0', }); @@ -328,6 +342,7 @@ If you are sure the module exists, try these steps: \u001b[0m \u001b[90m 15 | \u001b[39m\u001b[36mimport\u001b[39m fbRemoteAsset from \u001b[32m'fbRemoteAsset'\u001b[39m\u001b[33m;\u001b[39m\u001b[0m`, name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -359,6 +374,7 @@ If you are sure the module exists, try these steps: substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: '/path/to/file.js-1-1', }); @@ -382,6 +398,7 @@ If you are sure the module exists, try these steps: 200 |`, name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -405,6 +422,7 @@ If you are sure the module exists, try these steps: substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js-199-0', }); @@ -430,6 +448,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets 200 |`, name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -455,6 +474,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js-1-1', }); @@ -476,6 +496,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets \u001b[0m \u001b[90m 46 | \u001b[39m headline\u001b[33m=\u001b[39m\u001b[32m"CrashReact Error Boundary"\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 47 | \u001b[39m body\u001b[33m=\u001b[39m{\u001b[32m\`\${this.state.errorMessage}\`\u001b[39m}\u001b[0m\n\u001b[0m\u001b[31m\u001b[1m>\u001b[22m\u001b[39m\u001b[90m 48 | \u001b[39m icon\u001b[33m=\u001b[39m{fbRemoteAsset(\u001b[32m'null_state_glyphs'\u001b[39m\u001b[33m,\u001b[39m {\u001b[0m\n\u001b[0m \u001b[90m | \u001b[39m \u001b[31m\u001b[1m^\u001b[22m\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 49 | \u001b[39m name\u001b[33m:\u001b[39m \u001b[32m'codexxx'\u001b[39m\u001b[33m,\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 50 | \u001b[39m size\u001b[33m:\u001b[39m \u001b[32m'112'\u001b[39m\u001b[33m,\u001b[39m\u001b[0m\n\u001b[0m \u001b[90m 51 | \u001b[39m })}\u001b[0m`, name: '', isComponentError: false, + componentStackType: 'legacy', componentStack: '', stack: ([]: Array), id: 0, @@ -498,6 +519,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, substitutions: [], }, stack: [], + componentStackType: 'legacy', componentStack: [], category: '/path/to/RKJSModules/Apps/CrashReact/CrashReactApp.js-1-1', }); @@ -511,6 +533,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, message: '### Error', originalMessage: '### Error', name: '', + componentStackType: 'legacy', componentStack: '\n in MyComponent (at filename.js:1)\n in MyOtherComponent (at filename2.js:1)', stack: [ @@ -532,6 +555,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Error', substitutions: [], }, + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -566,6 +590,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, originalMessage: 'Some kind of message\n in MyComponent (at filename.js:1)\n in MyOtherComponent (at filename2.js:1)', name: '', + componentStackType: 'legacy', componentStack: null, stack: [ { @@ -589,6 +614,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, methodName: 'bar', }, ], + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -616,6 +642,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, isComponentError: false, message: '### Fatal', originalMessage: '### Fatal', + componentStackType: 'legacy', componentStack: null, name: '', stack: [ @@ -637,6 +664,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Fatal', substitutions: [], }, + componentStackType: 'legacy', componentStack: [], stack: [ { @@ -678,6 +706,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Fatal', substitutions: [], }, + componentStackType: 'legacy', componentStack: [], stack: [ { @@ -724,6 +753,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, substitutions: [], }, isComponentError: false, + componentStackType: 'legacy', componentStack: [], stack: [ { @@ -746,6 +776,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n in MyComponent (created by MyOtherComponent)\n in MyOtherComponent (created by MyComponent)\n in MyAppComponent (created by MyOtherComponent)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -784,6 +815,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Some kind of message\n in MyComponent (created by MyOtherComponent)\n in MyOtherComponent (created by MyComponent)\n in MyAppComponent (created by MyOtherComponent)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -816,6 +848,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n in MyComponent (created by MyOtherComponent)\n in MyOtherComponent (created by MyComponent)\n in MyAppComponent (created by MyOtherComponent)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -850,6 +883,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n in MyComponent (created by MyOtherComponent)\n in MyOtherComponent (created by MyComponent)\n in MyAppComponent (created by MyOtherComponent)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -895,6 +929,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Error: Some kind of message\n\nThis error is located at:\n in MyComponent (created by MyOtherComponent)\n', originalMessage: 'Some kind of message', name: '', + componentStackType: 'legacy', componentStack: '\n in MyComponent (created by MyOtherComponent)\n', stack: [ { @@ -919,6 +954,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, methodName: 'bar', }, ], + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -963,6 +999,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Error', substitutions: [], }, + componentStackType: 'legacy', componentStack: [ { content: 'MyComponent', @@ -1014,6 +1051,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1051,6 +1089,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Some kind of message\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1082,6 +1121,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1115,6 +1155,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\n at MyComponent (/path/to/filename.js:1:2)\n at MyOtherComponent\n at MyAppComponent (/path/to/app.js:100:20)', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1179,6 +1220,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Error', substitutions: [], }, + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1218,6 +1260,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1259,6 +1302,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Some kind of message\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1293,6 +1337,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Some kind of message\n in MyTSComponent (at MyTSXComponent.ts:1)\n in MyTSXComponent (at MyTSCComponent.tsx:1)\n in MyJSXComponent (at MyJSXComponent.jsx:1)\n in MyJSComponent (at MyJSComponent.js:1)', ]), ).toEqual({ + componentStackType: 'legacy', componentStack: [ { content: 'MyTSComponent', @@ -1341,6 +1386,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, 'Some kind of message\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1376,6 +1422,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1413,6 +1460,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, '\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', ]), ).toEqual({ + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1481,6 +1529,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, content: '### Error', substitutions: [], }, + componentStackType: 'stack', componentStack: [ { collapse: false, @@ -1523,6 +1572,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, originalMessage: 'Some kind of message\nMyComponent@/path/to/filename.js:1:2\nforEach@[native code]\nMyAppComponent@/path/to/app.js:100:20', name: '', + componentStackType: 'stack', componentStack: null, stack: [ { @@ -1546,6 +1596,7 @@ Please follow the instructions at: fburl.com/rn-remote-assets`, methodName: 'bar', }, ], + componentStackType: 'stack', componentStack: [ { collapse: false, diff --git a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js index c4dad211746088..f4519b3eb574ea 100644 --- a/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js +++ b/packages/react-native/Libraries/LogBox/Data/parseLogBoxLog.js @@ -123,6 +123,7 @@ export type Message = $ReadOnly<{| |}>; export type ComponentStack = $ReadOnlyArray; +export type ComponentStackType = 'legacy' | 'stack'; const SUBSTITUTION = UTFSequence.BOM + '%s'; @@ -216,24 +217,29 @@ function isComponentStack(consoleArgument: string) { ); } -export function parseComponentStack(message: string): ComponentStack { +export function parseComponentStack(message: string): { + type: ComponentStackType, + stack: ComponentStack, +} { // In newer versions of React, the component stack is formatted as a call stack frame. // First try to parse the component stack as a call stack frame, and if that doesn't // work then we'll fallback to the old custom component stack format parsing. const stack = parseErrorStack(message); if (stack && stack.length > 0) { - return stack.map(frame => ({ - content: frame.methodName, - collapse: frame.collapse || false, - fileName: frame.file == null ? 'unknown' : frame.file, - location: { - column: frame.column == null ? -1 : frame.column, - row: frame.lineNumber == null ? -1 : frame.lineNumber, - }, - })); + return { + type: 'stack', + stack: stack.map(frame => ({ + content: frame.methodName, + collapse: frame.collapse || false, + fileName: frame.file == null ? 'unknown' : frame.file, + location: { + column: frame.column == null ? -1 : frame.column, + row: frame.lineNumber == null ? -1 : frame.lineNumber, + }, + })), + }; } - - return message + const legacyStack = message .split(RE_COMPONENT_STACK_LINE_GLOBAL) .map(s => { if (!s) { @@ -262,6 +268,11 @@ export function parseComponentStack(message: string): ComponentStack { return null; }) .filter(Boolean); + + return { + type: 'legacy', + stack: legacyStack, + }; } export function parseLogBoxException( @@ -280,6 +291,7 @@ export function parseLogBoxException( type: 'Metro Error', stack: [], isComponentError: false, + componentStackType: 'legacy', componentStack: [], codeFrame: { fileName, @@ -308,6 +320,7 @@ export function parseLogBoxException( level: 'syntax', stack: [], isComponentError: false, + componentStackType: 'legacy', componentStack: [], codeFrame: { fileName, @@ -338,6 +351,7 @@ export function parseLogBoxException( level: 'syntax', stack: [], isComponentError: false, + componentStackType: 'legacy', componentStack: [], codeFrame: { fileName, @@ -359,6 +373,7 @@ export function parseLogBoxException( level: 'syntax', stack: error.stack, isComponentError: error.isComponentError, + componentStackType: 'legacy', componentStack: [], message: { content: message, @@ -371,24 +386,39 @@ export function parseLogBoxException( const componentStack = error.componentStack; if (error.isFatal || error.isComponentError) { - return { - level: 'fatal', - stack: error.stack, - isComponentError: error.isComponentError, - componentStack: - componentStack != null ? parseComponentStack(componentStack) : [], - extraData: error.extraData, - ...parseInterpolation([message]), - }; + if (componentStack != null) { + const {type, stack} = parseComponentStack(componentStack); + return { + level: 'fatal', + stack: error.stack, + isComponentError: error.isComponentError, + componentStackType: type, + componentStack: stack, + extraData: error.extraData, + ...parseInterpolation([message]), + }; + } else { + return { + level: 'fatal', + stack: error.stack, + isComponentError: error.isComponentError, + componentStackType: 'legacy', + componentStack: [], + extraData: error.extraData, + ...parseInterpolation([message]), + }; + } } if (componentStack != null) { // It is possible that console errors have a componentStack. + const {type, stack} = parseComponentStack(componentStack); return { level: 'error', stack: error.stack, isComponentError: error.isComponentError, - componentStack: parseComponentStack(componentStack), + componentStackType: type, + componentStack: stack, extraData: error.extraData, ...parseInterpolation([message]), }; @@ -407,12 +437,14 @@ export function parseLogBoxException( export function parseLogBoxLog(args: $ReadOnlyArray): {| componentStack: ComponentStack, + componentStackType: ComponentStackType, category: Category, message: Message, |} { const message = args[0]; let argsWithoutComponentStack: Array = []; let componentStack: ComponentStack = []; + let componentStackType = 'legacy'; // Extract component stack from warnings like "Some warning%s". if ( @@ -424,7 +456,9 @@ export function parseLogBoxLog(args: $ReadOnlyArray): {| if (typeof lastArg === 'string' && isComponentStack(lastArg)) { argsWithoutComponentStack = args.slice(0, -1); argsWithoutComponentStack[0] = message.slice(0, -2); - componentStack = parseComponentStack(lastArg); + const {type, stack} = parseComponentStack(lastArg); + componentStack = stack; + componentStackType = type; } } @@ -442,7 +476,9 @@ export function parseLogBoxLog(args: $ReadOnlyArray): {| argsWithoutComponentStack.push(arg.slice(0, messageEndIndex)); } - componentStack = parseComponentStack(arg); + const {type, stack} = parseComponentStack(arg); + componentStack = stack; + componentStackType = type; } else { argsWithoutComponentStack.push(arg); } @@ -452,5 +488,6 @@ export function parseLogBoxLog(args: $ReadOnlyArray): {| return { ...parseInterpolation(argsWithoutComponentStack), componentStack, + componentStackType, }; } diff --git a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js index 4c1cf9b3c1c482..428dc83a5ce85e 100644 --- a/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js +++ b/packages/react-native/Libraries/LogBox/UI/LogBoxInspectorReactFrames.js @@ -50,24 +50,27 @@ function getPrettyFileName(path: string) { } function LogBoxInspectorReactFrames(props: Props): React.Node { const [collapsed, setCollapsed] = React.useState(true); - if (props.log.componentStack == null || props.log.componentStack.length < 1) { + if ( + props.log.getAvailableComponentStack() == null || + props.log.getAvailableComponentStack().length < 1 + ) { return null; } function getStackList() { if (collapsed) { - return props.log.componentStack.slice(0, 3); + return props.log.getAvailableComponentStack().slice(0, 3); } else { - return props.log.componentStack; + return props.log.getAvailableComponentStack(); } } function getCollapseMessage() { - if (props.log.componentStack.length <= 3) { + if (props.log.getAvailableComponentStack().length <= 3) { return; } - const count = props.log.componentStack.length - 3; + const count = props.log.getAvailableComponentStack().length - 3; if (collapsed) { return `See ${count} more components`; } else { diff --git a/packages/react-native/Libraries/LogBox/UI/__tests__/__snapshots__/LogBoxInspector-test.js.snap b/packages/react-native/Libraries/LogBox/UI/__tests__/__snapshots__/LogBoxInspector-test.js.snap index 0574a088ddf244..307cc240878b4b 100644 --- a/packages/react-native/Libraries/LogBox/UI/__tests__/__snapshots__/LogBoxInspector-test.js.snap +++ b/packages/react-native/Libraries/LogBox/UI/__tests__/__snapshots__/LogBoxInspector-test.js.snap @@ -21,6 +21,7 @@ exports[`LogBoxContainer should render fatal with selectedIndex 2 1`] = ` "category": "Some kind of message (third)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -35,6 +36,11 @@ exports[`LogBoxContainer should render fatal with selectedIndex 2 1`] = ` "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } @@ -71,6 +77,7 @@ exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = ` "category": "Some kind of message (first)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -85,6 +92,11 @@ exports[`LogBoxContainer should render warning with selectedIndex 0 1`] = ` "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } diff --git a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxInspectorContainer-test.js.snap b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxInspectorContainer-test.js.snap index 591971a62af560..445cfb2365bb2d 100644 --- a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxInspectorContainer-test.js.snap +++ b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxInspectorContainer-test.js.snap @@ -27,6 +27,7 @@ exports[`LogBoxNotificationContainer should render both an error and warning not "category": "Some kind of message", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -41,6 +42,11 @@ exports[`LogBoxNotificationContainer should render both an error and warning not "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } @@ -65,6 +71,7 @@ exports[`LogBoxNotificationContainer should render both an error and warning not "category": "Some kind of message (latest)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -79,6 +86,11 @@ exports[`LogBoxNotificationContainer should render both an error and warning not "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } @@ -125,6 +137,7 @@ exports[`LogBoxNotificationContainer should render the latest error notification "category": "Some kind of message (latest)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -139,6 +152,11 @@ exports[`LogBoxNotificationContainer should render the latest error notification "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } @@ -177,6 +195,7 @@ exports[`LogBoxNotificationContainer should render the latest warning notificati "category": "Some kind of message (latest)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -191,6 +210,11 @@ exports[`LogBoxNotificationContainer should render the latest warning notificati "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, } } diff --git a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap index 5402cb1504e05e..05c2778c4f6b91 100644 --- a/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap +++ b/packages/react-native/Libraries/LogBox/__tests__/__snapshots__/LogBoxNotificationContainer-test.js.snap @@ -19,6 +19,7 @@ exports[`LogBoxNotificationContainer should render inspector with logs, even whe "category": "Some kind of message", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -33,12 +34,18 @@ exports[`LogBoxNotificationContainer should render inspector with logs, even whe "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, }, LogBoxLog { "category": "Some kind of message (latest)", "codeFrame": undefined, "componentStack": Array [], + "componentStackType": "legacy", "count": 1, "extraData": undefined, "isComponentError": false, @@ -53,6 +60,11 @@ exports[`LogBoxNotificationContainer should render inspector with logs, even whe "stack": null, "status": "NONE", }, + "symbolicatedComponentStack": Object { + "componentStack": null, + "error": null, + "status": "NONE", + }, "type": undefined, }, ] diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 4dcde7ead1a1c5..6b62f086b1dd09 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -5280,6 +5280,7 @@ export type LogBoxLogData = $ReadOnly<{| message: Message, stack: Stack, category: string, + componentStackType?: ComponentStackType, componentStack: ComponentStack, codeFrame?: ?CodeFrame, isComponentError: boolean, @@ -5290,6 +5291,7 @@ declare class LogBoxLog { type: ?string; category: Category; componentStack: ComponentStack; + componentStackType: ComponentStackType; stack: Stack; count: number; level: LogLevel; @@ -5301,9 +5303,19 @@ declare class LogBoxLog { | $ReadOnly<{| error: null, stack: null, status: \\"PENDING\\" |}> | $ReadOnly<{| error: null, stack: Stack, status: \\"COMPLETE\\" |}> | $ReadOnly<{| error: Error, stack: null, status: \\"FAILED\\" |}>; + symbolicatedComponentStack: + | $ReadOnly<{| error: null, componentStack: null, status: \\"NONE\\" |}> + | $ReadOnly<{| error: null, componentStack: null, status: \\"PENDING\\" |}> + | $ReadOnly<{| + error: null, + componentStack: ComponentStack, + status: \\"COMPLETE\\", + |}> + | $ReadOnly<{| error: Error, componentStack: null, status: \\"FAILED\\" |}>; constructor(data: LogBoxLogData): void; incrementCount(): void; getAvailableStack(): Stack; + getAvailableComponentStack(): ComponentStack; retrySymbolicate(callback?: (status: SymbolicationStatus) => void): void; symbolicate(callback?: (status: SymbolicationStatus) => void): void; handleSymbolicate(callback?: (status: SymbolicationStatus) => void): void; @@ -5313,6 +5325,12 @@ declare class LogBoxLog { codeFrame: ?CodeFrame, callback?: (status: SymbolicationStatus) => void ): void; + updateComponentStackStatus( + error: ?Error, + componentStack: ?ComponentStack, + codeFrame: ?CodeFrame, + callback?: (status: SymbolicationStatus) => void + ): void; } declare export default typeof LogBoxLog; " @@ -5354,18 +5372,23 @@ export type Message = $ReadOnly<{| >, |}>; export type ComponentStack = $ReadOnlyArray; +export type ComponentStackType = \\"legacy\\" | \\"stack\\"; declare export function parseInterpolation( args: $ReadOnlyArray ): $ReadOnly<{| category: Category, message: Message, |}>; -declare export function parseComponentStack(message: string): ComponentStack; +declare export function parseComponentStack(message: string): { + type: ComponentStackType, + stack: ComponentStack, +}; declare export function parseLogBoxException( error: ExtendedExceptionData ): LogBoxLogData; declare export function parseLogBoxLog(args: $ReadOnlyArray): {| componentStack: ComponentStack, + componentStackType: ComponentStackType, category: Category, message: Message, |}; From b696a7dc5e78dd42eb712e7c4b7d6f389526d933 Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Mon, 11 Mar 2024 10:38:55 -0700 Subject: [PATCH 143/361] Reduce warning level of distributed Yoga builds (#43405) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43405 X-link: https://github.com/facebook/yoga/pull/1592 Fixes https://github.com/facebook/yoga/issues/1590 Yoga may be built with a high warning level. This is helpful in letting Yoga be used in more places, and finding defects. We currently set these in the internal BUCK build, the CMake reference build, and the Yoga Standalone (not RN) CocoaPods build. Yoga's reference CMake build and spec are consumed today by users of Yoga, instead of just Yoga developers. Here, it makes more sense to avoid anything that could break compiler-to-compiler compatibility. We default these to a less intense (`-Wall -Werror`). I kept `/W4`, for pragmatic reasons, and since it is relatively standard for MSVC. We continue to build with strict flags on Buck build on Clang. Reviewed By: cortinico Differential Revision: D54735661 fbshipit-source-id: 130e35ac9dcffa2f7e70e48d18770f1275864e2a --- .../react-native/ReactCommon/yoga/cmake/project-defaults.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake b/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake index c262bac8af89af..987529c549c9b8 100644 --- a/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake +++ b/packages/react-native/ReactCommon/yoga/cmake/project-defaults.cmake @@ -33,9 +33,7 @@ add_compile_options( -fexceptions # Enable warnings and warnings as errors -Wall - -Wextra -Werror - -Wconversion # Disable RTTI $<$:-fno-rtti> # Use -O2 (prioritize speed) From c6ca7d61af19030bbd5e9b7bb59e07b81433f977 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 11 Mar 2024 10:39:52 -0700 Subject: [PATCH 144/361] Add changelog for 0.74.0-rc3 Summary: Changelog: [Internal] Reviewed By: cortinico Differential Revision: D54755786 fbshipit-source-id: 76dfac43143d95a8765d67c93a2d8a30edec4259 --- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25fbe8ec85424d..209201a145b5f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## v0.74.0-rc.3 + +### Added + +- Add inspector proxy `nativeNetworkInspection` target capability flag ([f3ce7cd76e](https://github.com/facebook/react-native/commit/f3ce7cd76ee4f1772e2623c87b21bbbcb1edbc27) by [@byCedric](https://github.com/byCedric)) + +#### iOS specific + +- Implement cursor style prop ([73664f576a](https://github.com/facebook/react-native/commit/73664f576aaa472d5c8fb2a02e0ddd017bbb2ea4) by [@Saadnajmi](https://github.com/Saadnajmi)) + +### Changed + +#### Android specific + +- Expose `react_render_textlayoutmanager` via prefab. ([642b4e5c2c](https://github.com/facebook/react-native/commit/642b4e5c2c80b6f46429b41f36489eb81ac8a06e) by [@tomekzaw](https://github.com/tomekzaw)) +- Expose `rrc_text` via prefab. ([1c69100a2b](https://github.com/facebook/react-native/commit/1c69100a2b822309c210733a33a57ebb560a1c71) by [@tomekzaw](https://github.com/tomekzaw)) +- Expose `rrc_textinput` via prefab. ([adc9e5b0fa](https://github.com/facebook/react-native/commit/adc9e5b0faaf8c997fe0d09aecd56747026f8b01) by [@tomekzaw](https://github.com/tomekzaw)) + +### Fixed + +- Support .tsx, .ts, and .jsx in component stacks ([adaf5eba3e](https://github.com/facebook/react-native/commit/adaf5eba3e8381d0b499257ab04d30d6f3fb4c93) by [@rickhanlonii](https://github.com/rickhanlonii)) + +#### Android specific + +- Fix registration of ViewManagers in new renderer when not using lazyViewManagers. ([fb9872d4fe](https://github.com/facebook/react-native/commit/fb9872d4fe07ac7028ce536200632b3543d5e8a9) by [@javache](https://github.com/javache)) +- NullPointerException is no longer ignored in MessageQueueThreadHandler ([5f45700bd0](https://github.com/facebook/react-native/commit/5f45700bd06fb253650c8653b511b084b99eeb7f) by [@javache](https://github.com/javache)) + +#### iOS specific + +- RCTRedBox not appearing in Bridgeless when metro is not running ([4adef35e97](https://github.com/facebook/react-native/commit/4adef35e97f31db466e536aa21d5eeec6ee34fc6) by [@okwasniewski](https://github.com/okwasniewski)) + ## v0.74.0-rc.2 ### Changed From a7fde7c885a3827c03b058a21023b18501e2a57a Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Mon, 11 Mar 2024 11:03:58 -0700 Subject: [PATCH 145/361] Enable JSI integration tests for Hermes CDPAgent (#43391) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43391 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Bootstraps `HermesRuntimeAgentDelegateNew` within `JsiIntegrationTest.cpp`. Test cases which currently do not pass with `HermesRuntimeAgentDelegateNew` are selectively matched against a new alias to exclude them: `JsiIntegrationHermesLegacyTest`. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D53810357 fbshipit-source-id: 2d7d7446038530d19d93add71361b4bf581cff18 --- .../tests/JsiIntegrationTest.cpp | 35 +++++++++++++++---- ...JsiIntegrationTestGenericEngineAdapter.cpp | 5 +++ .../JsiIntegrationTestGenericEngineAdapter.h | 4 +++ .../JsiIntegrationTestHermesEngineAdapter.cpp | 10 ++++-- .../JsiIntegrationTestHermesEngineAdapter.h | 4 +++ ...ionTestHermesWithCDPAgentEngineAdapter.cpp | 26 ++++++++++++++ ...ationTestHermesWithCDPAgentEngineAdapter.h | 28 +++++++++++++++ .../utils/InspectorFlagOverridesGuard.cpp | 4 +++ .../tests/utils/InspectorFlagOverridesGuard.h | 1 + 9 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.cpp create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index ae8300ef9799e6..ce89fed224565c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -22,6 +22,7 @@ #include "UniquePtrFactory.h" #include "engines/JsiIntegrationTestGenericEngineAdapter.h" #include "engines/JsiIntegrationTestHermesEngineAdapter.h" +#include "engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h" using namespace ::testing; using folly::sformat; @@ -52,7 +53,9 @@ class JsiIntegrationPortableTest : public Test, private HostTargetDelegate { folly::QueuedImmediateExecutor immediateExecutor_; protected: - JsiIntegrationPortableTest() : engineAdapter_{immediateExecutor_} { + JsiIntegrationPortableTest() + : inspectorFlagsGuard_{EngineAdapter::getInspectorFlagOverrides()}, + engineAdapter_{immediateExecutor_} { instance_ = &page_->registerInstance(instanceTargetDelegate_); runtimeTarget_ = &instance_->registerRuntime( engineAdapter_->getRuntimeTargetDelegate(), @@ -136,6 +139,7 @@ class JsiIntegrationPortableTest : public Test, private HostTargetDelegate { InstanceTarget* instance_{}; RuntimeTarget* runtimeTarget_{}; + InspectorFlagOverridesGuard inspectorFlagsGuard_; MockInstanceTargetDelegate instanceTargetDelegate_; std::optional engineAdapter_; @@ -168,9 +172,14 @@ class JsiIntegrationPortableTest : public Test, private HostTargetDelegate { */ using AllEngines = Types< JsiIntegrationTestHermesEngineAdapter, + JsiIntegrationTestHermesWithCDPAgentEngineAdapter, JsiIntegrationTestGenericEngineAdapter>; -using AllHermesVariants = Types; +using AllHermesVariants = Types< + JsiIntegrationTestHermesEngineAdapter, + JsiIntegrationTestHermesWithCDPAgentEngineAdapter>; + +using LegacyHermesVariants = Types; TYPED_TEST_SUITE(JsiIntegrationPortableTest, AllEngines); @@ -178,7 +187,12 @@ template using JsiIntegrationHermesTest = JsiIntegrationPortableTest; TYPED_TEST_SUITE(JsiIntegrationHermesTest, AllHermesVariants); -//////////////////////////////////////////////////////////////////////////////// +template +using JsiIntegrationHermesLegacyTest = + JsiIntegrationPortableTest; +TYPED_TEST_SUITE(JsiIntegrationHermesLegacyTest, LegacyHermesVariants); + +#pragma region JsiIntegrationPortableTest TYPED_TEST(JsiIntegrationPortableTest, ConnectWithoutCrashing) { this->connect(); @@ -458,7 +472,8 @@ TYPED_TEST(JsiIntegrationPortableTest, ExceptionDuringAddBindingIsIgnored) { EXPECT_TRUE(this->eval("globalThis.foo === 42").getBool()); } -//////////////////////////////////////////////////////////////////////////////// +#pragma endregion +#pragma region JsiIntegrationHermesTest TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpression) { this->connect(); @@ -479,7 +494,11 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpression) { })"); } -TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { +// TODO(T181299386): Restore stale execution context validation under +// HermesRuntimeAgentDelegateNew +TYPED_TEST( + JsiIntegrationHermesLegacyTest, + EvaluateExpressionInExecutionContext) { this->connect(); InSequence s; @@ -538,7 +557,9 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { std::to_string(executionContextId))); } -TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { +// TODO(T178858701): Restore breakpoint reload persistence under +// HermesRuntimeAgentDelegateNew +TYPED_TEST(JsiIntegrationHermesLegacyTest, ResolveBreakpointAfterReload) { this->connect(); InSequence s; @@ -580,4 +601,6 @@ TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { scriptInfo->value()["params"]["scriptId"]); } +#pragma endregion + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp index db0e3693787729..f46c98fab83a87 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.cpp @@ -21,6 +21,11 @@ JsiIntegrationTestGenericEngineAdapter::JsiIntegrationTestGenericEngineAdapter( runtimeTargetDelegate_{ "Generic engine (" + runtime_->description() + ")"} {} +/* static */ InspectorFlagOverrides +JsiIntegrationTestGenericEngineAdapter::getInspectorFlagOverrides() noexcept { + return {.enableModernCDPRegistry = true}; +} + RuntimeTargetDelegate& JsiIntegrationTestGenericEngineAdapter::getRuntimeTargetDelegate() { return runtimeTargetDelegate_; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h index b6016e25c32179..836d09530bfff8 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestGenericEngineAdapter.h @@ -7,6 +7,8 @@ #pragma once +#include "../utils/InspectorFlagOverridesGuard.h" + #include #include @@ -26,6 +28,8 @@ class JsiIntegrationTestGenericEngineAdapter { public: explicit JsiIntegrationTestGenericEngineAdapter(folly::Executor& jsExecutor); + static InspectorFlagOverrides getInspectorFlagOverrides() noexcept; + RuntimeTargetDelegate& getRuntimeTargetDelegate(); jsi::Runtime& getRuntime() const noexcept; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp index eb4fdfdedf9ecf..11da119e77c708 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.cpp @@ -5,9 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -#include - #include "JsiIntegrationTestHermesEngineAdapter.h" +#include "../utils/InspectorFlagOverridesGuard.h" + +#include using facebook::hermes::makeHermesRuntime; @@ -19,6 +20,11 @@ JsiIntegrationTestHermesEngineAdapter::JsiIntegrationTestHermesEngineAdapter( jsExecutor_{jsExecutor}, runtimeTargetDelegate_{runtime_} {} +/* static */ InspectorFlagOverrides +JsiIntegrationTestHermesEngineAdapter::getInspectorFlagOverrides() noexcept { + return {.enableModernCDPRegistry = true}; +} + RuntimeTargetDelegate& JsiIntegrationTestHermesEngineAdapter::getRuntimeTargetDelegate() { return runtimeTargetDelegate_; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h index dd0f273eb17b28..73740f73cb2f1d 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesEngineAdapter.h @@ -7,6 +7,8 @@ #pragma once +#include "../utils/InspectorFlagOverridesGuard.h" + #include #include @@ -26,6 +28,8 @@ class JsiIntegrationTestHermesEngineAdapter { public: explicit JsiIntegrationTestHermesEngineAdapter(folly::Executor& jsExecutor); + static InspectorFlagOverrides getInspectorFlagOverrides() noexcept; + RuntimeTargetDelegate& getRuntimeTargetDelegate(); jsi::Runtime& getRuntime() const noexcept; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.cpp new file mode 100644 index 00000000000000..593826f5cce619 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h" + +namespace facebook::react::jsinspector_modern { + +JsiIntegrationTestHermesWithCDPAgentEngineAdapter:: + JsiIntegrationTestHermesWithCDPAgentEngineAdapter( + folly::Executor& jsExecutor) + : JsiIntegrationTestHermesEngineAdapter(jsExecutor) {} + +/* static */ InspectorFlagOverrides +JsiIntegrationTestHermesWithCDPAgentEngineAdapter:: + getInspectorFlagOverrides() noexcept { + return { + .enableHermesCDPAgent = true, + .enableModernCDPRegistry = true, + }; +} + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h new file mode 100644 index 00000000000000..e61f6b82706035 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/engines/JsiIntegrationTestHermesWithCDPAgentEngineAdapter.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include "../utils/InspectorFlagOverridesGuard.h" +#include "JsiIntegrationTestHermesEngineAdapter.h" + +namespace facebook::react::jsinspector_modern { + +/** + * An engine adapter for JsiIntegrationTest that uses Hermes (and Hermes's + * new CDPAgent API). + */ +class JsiIntegrationTestHermesWithCDPAgentEngineAdapter + : public JsiIntegrationTestHermesEngineAdapter { + public: + explicit JsiIntegrationTestHermesWithCDPAgentEngineAdapter( + folly::Executor& jsExecutor); + + static InspectorFlagOverrides getInspectorFlagOverrides() noexcept; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp index cc5caf11953acd..ea6e640a59da10 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp @@ -30,6 +30,10 @@ class ReactNativeFeatureFlagsOverrides return overrides_.enableCxxInspectorPackagerConnection; } + bool inspectorEnableHermesCDPAgent() override { + return overrides_.enableHermesCDPAgent; + } + bool inspectorEnableModernCDPRegistry() override { return overrides_.enableModernCDPRegistry; } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h index 4d7ad76b7e05cf..5e91bb4cb8abf3 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h @@ -18,6 +18,7 @@ struct InspectorFlagOverrides { // NOTE: Keep these entries in sync with ReactNativeFeatureFlagsOverrides in // the implementation file. bool enableCxxInspectorPackagerConnection = false; + bool enableHermesCDPAgent = false; bool enableModernCDPRegistry = false; }; From c6076bca974b74b8456806cd06e0c1c63c58aaf9 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Mon, 11 Mar 2024 12:19:49 -0700 Subject: [PATCH 146/361] Implement getJSCallInvokerHolder for BridgelessCatalystInstance (#43400) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43400 Implement `getJSCallInvokerHolder()` for BridgelessCatalystInstance Changelog: [Android][Breaking] Implement `getJSCallInvokerHolder()` for Bridgeless Catalyst Instance Reviewed By: cortinico Differential Revision: D54650305 fbshipit-source-id: effac3daaad5173c2fd78ab11bbe3f3156a9c07b --- .../ReactAndroid/api/ReactAndroid.api | 2 +- .../react/runtime/BridgelessCatalystInstance.kt | 7 ++++--- .../react/runtime/BridgelessReactContext.java | 10 ++++------ .../com/facebook/react/runtime/ReactHostImpl.java | 15 +++++++++++++++ .../com/facebook/react/runtime/ReactInstance.java | 2 +- .../react/runtime/BridgelessReactContextTest.kt | 10 ++++++---- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 462410ae4ff6bc..9bb3145b68f208 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -3570,7 +3570,7 @@ public abstract class com/facebook/react/runtime/BindingsInstaller { } public final class com/facebook/react/runtime/BridgelessCatalystInstance : com/facebook/react/bridge/CatalystInstance { - public fun ()V + public fun (Lcom/facebook/react/runtime/ReactHostImpl;)V public fun addBridgeIdleDebugListener (Lcom/facebook/react/bridge/NotThreadSafeBridgeIdleDebugListener;)V public fun addJSIModules (Ljava/util/List;)V public fun callFunction (Ljava/lang/String;Ljava/lang/String;Lcom/facebook/react/bridge/NativeArray;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt index e2d87960b97555..ea9dd2cb203892 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessCatalystInstance.kt @@ -32,7 +32,8 @@ import com.facebook.react.turbomodule.core.interfaces.NativeMethodCallInvokerHol @DoNotStrip @DeprecatedInNewArchitecture -public class BridgelessCatalystInstance : CatalystInstance { +public class BridgelessCatalystInstance(private val reactHost: ReactHostImpl) : CatalystInstance { + override fun handleMemoryPressure(level: Int) { throw UnsupportedOperationException("Unimplemented method 'handleMemoryPressure'") } @@ -161,8 +162,8 @@ public class BridgelessCatalystInstance : CatalystInstance { throw UnsupportedOperationException("Unimplemented method 'addJSIModules'") } - override fun getJSCallInvokerHolder(): CallInvokerHolder { - throw UnsupportedOperationException("Unimplemented method 'getJSCallInvokerHolder'") + override fun getJSCallInvokerHolder(): CallInvokerHolder? { + return reactHost.getJSCallInvokerHolder() } override fun getNativeMethodCallInvokerHolder(): NativeMethodCallInvokerHolder { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java index 5fa3947959105c..d1cdaa976fc1d5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/BridgelessReactContext.java @@ -8,6 +8,7 @@ package com.facebook.react.runtime; import android.content.Context; +import android.util.Log; import com.facebook.infer.annotation.Nullsafe; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; @@ -18,8 +19,6 @@ import com.facebook.react.bridge.NativeArray; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactNoCrashBridgeNotAllowedSoftException; -import com.facebook.react.bridge.ReactSoftExceptionLogger; import com.facebook.react.bridge.RuntimeExecutor; import com.facebook.react.bridge.UIManager; import com.facebook.react.bridge.WritableNativeArray; @@ -84,11 +83,10 @@ public void setSourceURL(String sourceURL) { @Override public CatalystInstance getCatalystInstance() { - ReactSoftExceptionLogger.logSoftExceptionVerbose( + Log.w( TAG, - new ReactNoCrashBridgeNotAllowedSoftException( - "getCatalystInstance() cannot be called when the bridge is disabled")); - throw new UnsupportedOperationException("There is no Catalyst instance in bridgeless mode."); + "[WARNING] Bridgeless doesn't support CatalystInstance. Accessing an API that's not part of the new architecture is not encouraged usage."); + return new BridgelessCatalystInstance(mReactHost); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index ac66e250774c21..c7d852d38507d5 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -61,6 +61,7 @@ import com.facebook.react.runtime.internal.bolts.Continuation; import com.facebook.react.runtime.internal.bolts.Task; import com.facebook.react.runtime.internal.bolts.TaskCompletionSource; +import com.facebook.react.turbomodule.core.interfaces.CallInvokerHolder; import com.facebook.react.uimanager.UIManagerModule; import com.facebook.react.uimanager.events.BlackHoleEventDispatcher; import com.facebook.react.uimanager.events.EventDispatcher; @@ -604,6 +605,20 @@ RuntimeExecutor getRuntimeExecutor() { return null; } + /* package */ + @Nullable + CallInvokerHolder getJSCallInvokerHolder() { + final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); + if (reactInstance != null) { + return reactInstance.getJSCallInvokerHolder(); + } + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Tried to get JSCallInvokerHolder while instance is not ready")); + return null; + } + /** * To be called when the host activity receives an activity result. * diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java index 2de6a51fa0ff4b..8b590833d8df66 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactInstance.java @@ -461,7 +461,7 @@ private native HybridData initHybrid( private native void loadJSBundleFromAssets(AssetManager assetManager, String assetURL); - private native CallInvokerHolderImpl getJSCallInvokerHolder(); + /* package */ native CallInvokerHolderImpl getJSCallInvokerHolder(); private native NativeMethodCallInvokerHolderImpl getNativeMethodCallInvokerHolder(); diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt index d8a8c3b473091d..6f7eb6f474aed9 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt @@ -55,9 +55,11 @@ class BridgelessReactContextTest { Assertions.assertThat(bridgelessReactContext.getFabricUIManager()).isEqualTo(fabricUiManager) } - @Test(expected = UnsupportedOperationException::class) - fun getCatalystInstance_throwsException() { - // Disable this test for now due to mocking FabricUIManager fails - bridgelessReactContext.catalystInstance + @Test + fun getCatalystInstanceTest() { + val bridgelessCatalystInstance = BridgelessCatalystInstance(reactHost) + doReturn(bridgelessCatalystInstance).`when`(bridgelessReactContext).getCatalystInstance() + Assertions.assertThat(bridgelessReactContext.getCatalystInstance()) + .isEqualTo(bridgelessCatalystInstance) } } From 3706bf077e62b82a8c15874ac1ee6f0a7497468d Mon Sep 17 00:00:00 2001 From: Fabrizio Cucci Date: Mon, 11 Mar 2024 13:01:09 -0700 Subject: [PATCH 147/361] Scope LongLivedObjectCollection per runtime [2/n] (#43409) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43409 Changelog: [General] [Breaking] - Make `LongLivedObject` constructor accept a `Runtime` reference. # Context Approach 1 as described in [RFC post](https://fb.workplace.com/groups/615693552291894/permalink/1693347124526526/). # This diff * Embed `Runtime` reference in `LongLivedObject` to keep supporting `allowRelease` method (and update extending classes accordingly) * Update MSFT fork accordingly Reviewed By: RSNara Differential Revision: D54638813 fbshipit-source-id: 0d58d1c32b3689bdd1223c13f5d5ee2f2e15f223 --- .../ReactCommon/react/bridging/CallbackWrapper.h | 5 ++--- .../ReactCommon/react/bridging/LongLivedObject.h | 4 +++- packages/react-native/ReactCommon/react/bridging/Promise.h | 6 ++++-- .../nativemodule/core/ReactCommon/TurboModuleUtils.cpp | 4 +++- .../react/nativemodule/core/ReactCommon/TurboModuleUtils.h | 1 - 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h b/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h index 228f0948d8f3b8..336b9854de7771 100644 --- a/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h +++ b/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h @@ -24,12 +24,11 @@ class CallbackWrapper : public LongLivedObject { jsi::Function&& callback, jsi::Runtime& runtime, std::shared_ptr jsInvoker) - : callback_(std::move(callback)), - runtime_(runtime), + : LongLivedObject(runtime), + callback_(std::move(callback)), jsInvoker_(std::move(jsInvoker)) {} jsi::Function callback_; - jsi::Runtime& runtime_; std::shared_ptr jsInvoker_; public: diff --git a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h index f8ca6671da906e..0a9cdc8c19593e 100644 --- a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h +++ b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -31,8 +32,9 @@ class LongLivedObject { virtual void allowRelease(); protected: - LongLivedObject() = default; + explicit LongLivedObject(jsi::Runtime& runtime) : runtime_(runtime) {} virtual ~LongLivedObject() = default; + jsi::Runtime& runtime_; }; /** diff --git a/packages/react-native/ReactCommon/react/bridging/Promise.h b/packages/react-native/ReactCommon/react/bridging/Promise.h index 058faea13d1f78..35873952f6775a 100644 --- a/packages/react-native/ReactCommon/react/bridging/Promise.h +++ b/packages/react-native/ReactCommon/react/bridging/Promise.h @@ -34,7 +34,8 @@ class AsyncPromise { }, jsInvoker)); - auto promiseHolder = std::make_shared(promise.asObject(rt)); + auto promiseHolder = + std::make_shared(rt, promise.asObject(rt)); LongLivedObjectCollection::get().add(promiseHolder); // The shared state can retain the promise holder weakly now. @@ -71,7 +72,8 @@ class AsyncPromise { private: struct PromiseHolder : LongLivedObject { - PromiseHolder(jsi::Object p) : promise(std::move(p)) {} + PromiseHolder(jsi::Runtime& runtime, jsi::Object p) + : LongLivedObject(runtime), promise(std::move(p)) {} jsi::Object promise; }; diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp index 328c3f71a58415..2a7bbb51429603 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.cpp @@ -63,7 +63,9 @@ jsi::Array deepCopyJSIArray(jsi::Runtime& rt, const jsi::Array& arr) { } Promise::Promise(jsi::Runtime& rt, jsi::Function resolve, jsi::Function reject) - : runtime_(rt), resolve_(std::move(resolve)), reject_(std::move(reject)) {} + : LongLivedObject(rt), + resolve_(std::move(resolve)), + reject_(std::move(reject)) {} void Promise::resolve(const jsi::Value& result) { resolve_.call(runtime_, result); diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h index 786c4cdb3cec02..abc56408aee855 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleUtils.h @@ -26,7 +26,6 @@ struct Promise : public LongLivedObject { void resolve(const jsi::Value& result); void reject(const std::string& error); - jsi::Runtime& runtime_; jsi::Function resolve_; jsi::Function reject_; }; From da21799ca34a47168ed54420b6b1808396b24116 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Mon, 11 Mar 2024 14:49:52 -0700 Subject: [PATCH 148/361] Fix stack overflow in createRootView (#43420) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43420 Calling `mReactDelegate.createRootView` just ends up calling the overridden method in the anonymous inner class. Instead have the base implementation return null, and call super. Changelog: [Internal] Reviewed By: jessebwr, janeli-100005636499545 Differential Revision: D54772205 fbshipit-source-id: fc90e6718f9c287e8b86e5768cf7f74d0db06c49 --- .../com/facebook/react/ReactActivityDelegate.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 92b63c91607615..229f2d9f630d4c 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -63,8 +63,13 @@ public ReactActivityDelegate( return getLaunchOptions(); } + /** + * Override to customize ReactRootView creation. + * + *

Not used on bridgeless + */ protected ReactRootView createRootView() { - return Assertions.assertNotNull(mReactDelegate).createRootView(); + return null; } /** @@ -102,7 +107,11 @@ public void onCreate(Bundle savedInstanceState) { getPlainActivity(), getReactNativeHost(), mainComponentName, launchOptions) { @Override protected ReactRootView createRootView() { - return ReactActivityDelegate.this.createRootView(); + ReactRootView rootView = ReactActivityDelegate.this.createRootView(); + if (rootView == null) { + rootView = super.createRootView(); + } + return rootView; } }; } From 86a52cc2dc294131e138b1f6ee14b3e56e8c8572 Mon Sep 17 00:00:00 2001 From: Fabrizio Cucci Date: Mon, 11 Mar 2024 15:55:45 -0700 Subject: [PATCH 149/361] Scope LongLivedObjectCollection per runtime [3/n] (#43410) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43410 Changelog: [General] [Breaking] - Make `LongLivedObjectCollection::get` accept a Runtime reference as parameter. # Context Approach 1 as described in [RFC post](https://fb.workplace.com/groups/615693552291894/permalink/1693347124526526/). # This diff * Replace the `LongLivedObjectCollection` singleton with a map from `Runtime -> LongLivedObjectCollection` so that each RN instance has its own collection. * Update MSFT fork accordingly Reviewed By: javache, RSNara Differential Revision: D54649209 fbshipit-source-id: ecd2ab3917843ca82388b7b9cce06c05679f2d60 --- .../react/bridging/CallbackWrapper.h | 2 +- .../react/bridging/LongLivedObject.cpp | 19 +++++++++++++++---- .../react/bridging/LongLivedObject.h | 2 +- .../ReactCommon/react/bridging/Promise.h | 2 +- .../react/bridging/tests/BridgingTest.cpp | 2 +- .../react/bridging/tests/BridgingTest.h | 4 ++-- .../core/ReactCommon/TurboModuleBinding.cpp | 12 ++++++++---- .../core/ReactCommon/TurboModuleBinding.h | 2 ++ 8 files changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h b/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h index 336b9854de7771..122d9f75b7db0c 100644 --- a/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h +++ b/packages/react-native/ReactCommon/react/bridging/CallbackWrapper.h @@ -38,7 +38,7 @@ class CallbackWrapper : public LongLivedObject { std::shared_ptr jsInvoker) { auto wrapper = std::shared_ptr(new CallbackWrapper( std::move(callback), runtime, std::move(jsInvoker))); - LongLivedObjectCollection::get().add(wrapper); + LongLivedObjectCollection::get(runtime).add(wrapper); return wrapper; } diff --git a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp index 410f52d22ea9e7..64a93c1b7ec508 100644 --- a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp +++ b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp @@ -6,13 +6,24 @@ */ #include "LongLivedObject.h" +#include namespace facebook::react { // LongLivedObjectCollection -LongLivedObjectCollection& LongLivedObjectCollection::get() { - static LongLivedObjectCollection instance; - return instance; + +LongLivedObjectCollection& LongLivedObjectCollection::get( + jsi::Runtime& runtime) { + static std::unordered_map> + instances; + void* key = static_cast(&runtime); + auto entry = instances.find(key); + if (entry == instances.end()) { + entry = + instances.emplace(key, std::make_shared()) + .first; + } + return *(entry->second); } void LongLivedObjectCollection::add(std::shared_ptr so) { @@ -43,7 +54,7 @@ size_t LongLivedObjectCollection::size() const { // LongLivedObject void LongLivedObject::allowRelease() { - LongLivedObjectCollection::get().remove(this); + LongLivedObjectCollection::get(runtime_).remove(this); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h index 0a9cdc8c19593e..d043a0a9a91940 100644 --- a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h +++ b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.h @@ -42,7 +42,7 @@ class LongLivedObject { */ class LongLivedObjectCollection { public: - static LongLivedObjectCollection& get(); + static LongLivedObjectCollection& get(jsi::Runtime& runtime); LongLivedObjectCollection() = default; LongLivedObjectCollection(const LongLivedObjectCollection&) = delete; diff --git a/packages/react-native/ReactCommon/react/bridging/Promise.h b/packages/react-native/ReactCommon/react/bridging/Promise.h index 35873952f6775a..5a049c8574e5be 100644 --- a/packages/react-native/ReactCommon/react/bridging/Promise.h +++ b/packages/react-native/ReactCommon/react/bridging/Promise.h @@ -36,7 +36,7 @@ class AsyncPromise { auto promiseHolder = std::make_shared(rt, promise.asObject(rt)); - LongLivedObjectCollection::get().add(promiseHolder); + LongLivedObjectCollection::get(rt).add(promiseHolder); // The shared state can retain the promise holder weakly now. state_->promiseHolder = promiseHolder; diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp index e89c4eeaa2b131..45beaeff7b4e8a 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.cpp @@ -316,7 +316,7 @@ TEST_F(BridgingTest, asyncCallbackInvalidation) { [](jsi::Runtime& rt, jsi::Function& f) { f.call(rt, "hello"); }); // LongLivedObjectCollection goes away before callback is executed - LongLivedObjectCollection::get().clear(); + LongLivedObjectCollection::get(rt).clear(); flushQueue(); diff --git a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h index ffc4b49d67be9a..7fef3c9726a258 100644 --- a/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h +++ b/packages/react-native/ReactCommon/react/bridging/tests/BridgingTest.h @@ -43,14 +43,14 @@ class BridgingTest : public ::testing::Test { rt(*runtime) {} ~BridgingTest() { - LongLivedObjectCollection::get().clear(); + LongLivedObjectCollection::get(rt).clear(); } void TearDown() override { flushQueue(); // After flushing the invoker queue, we shouldn't leak memory. - EXPECT_EQ(0, LongLivedObjectCollection::get().size()); + EXPECT_EQ(0, LongLivedObjectCollection::get(rt).size()); } jsi::Value eval(const std::string& js) { diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp index 360ad45f9da864..e4d1a6e79e5a2e 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.cpp @@ -67,9 +67,11 @@ class BridgelessNativeModuleProxy : public jsi::HostObject { */ TurboModuleBinding::TurboModuleBinding( + jsi::Runtime& runtime, TurboModuleProviderFunctionType&& moduleProvider, std::shared_ptr longLivedObjectCollection) - : moduleProvider_(std::move(moduleProvider)), + : runtime_(runtime), + moduleProvider_(std::move(moduleProvider)), longLivedObjectCollection_(std::move(longLivedObjectCollection)) {} void TurboModuleBinding::install( @@ -85,7 +87,7 @@ void TurboModuleBinding::install( jsi::PropNameID::forAscii(runtime, "__turboModuleProxy"), 1, [binding = TurboModuleBinding( - std::move(moduleProvider), longLivedObjectCollection)]( + runtime, std::move(moduleProvider), longLivedObjectCollection)]( jsi::Runtime& rt, const jsi::Value& thisVal, const jsi::Value* args, @@ -102,7 +104,9 @@ void TurboModuleBinding::install( bool rnTurboInterop = legacyModuleProvider != nullptr; auto turboModuleBinding = legacyModuleProvider ? std::make_unique( - std::move(legacyModuleProvider), longLivedObjectCollection) + runtime, + std::move(legacyModuleProvider), + longLivedObjectCollection) : nullptr; auto nativeModuleProxy = std::make_shared( std::move(turboModuleBinding)); @@ -119,7 +123,7 @@ TurboModuleBinding::~TurboModuleBinding() { if (longLivedObjectCollection_) { longLivedObjectCollection_->clear(); } else { - LongLivedObjectCollection::get().clear(); + LongLivedObjectCollection::get(runtime_).clear(); } } diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h index 0556c697f1e7cd..d45a72f25ca282 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/ReactCommon/TurboModuleBinding.h @@ -34,6 +34,7 @@ class TurboModuleBinding { nullptr); TurboModuleBinding( + jsi::Runtime& runtime, TurboModuleProviderFunctionType&& moduleProvider, std::shared_ptr longLivedObjectCollection); @@ -49,6 +50,7 @@ class TurboModuleBinding { jsi::Value getModule(jsi::Runtime& runtime, const std::string& moduleName) const; + jsi::Runtime& runtime_; TurboModuleProviderFunctionType moduleProvider_; std::shared_ptr longLivedObjectCollection_; }; From 620459a07eb9c8f111d591e6e90d9e9f0662d444 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Mon, 11 Mar 2024 21:55:42 -0700 Subject: [PATCH 150/361] change import to RCTBridgeProxy to forward declaration (#43313) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43313 Changelog: [Internal] we can simplify the build graph here Reviewed By: cipolleschi Differential Revision: D54404844 fbshipit-source-id: 52dfbd05106e72687b969357e274d2c4cdd9ca34 --- .../core/platform/ios/ReactCommon/RCTTurboModuleManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h index 014745be16d1ee..68a457ae6c2ed3 100644 --- a/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h +++ b/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModuleManager.h @@ -10,7 +10,6 @@ #import #import -#import #import #import #import @@ -18,6 +17,7 @@ #import "RCTTurboModule.h" +@class RCTBridgeProxy; @class RCTTurboModuleManager; @protocol RCTTurboModuleManagerDelegate From 5522d522bb868d71061091b0393a6bc0170c9c7e Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Mon, 11 Mar 2024 21:55:42 -0700 Subject: [PATCH 151/361] support jsCallInvoker in RCTBridgeProxy (#43314) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43314 Changelog: [Internal] making call invoker a breaking change to runtime executor in 0.74 seems to be causing a lot of discourse. let's simplify things and first add the callinvoker to the backwards compat layer Reviewed By: cipolleschi Differential Revision: D54404845 fbshipit-source-id: 983e86829030557033b95625dab9068492739417 --- .../React/Base/RCTBridgeProxy+Cxx.h | 20 +++++++++++++++++++ .../react-native/React/Base/RCTBridgeProxy.h | 2 ++ .../react-native/React/Base/RCTBridgeProxy.mm | 15 ++++++++++++++ .../platform/ios/ReactCommon/RCTInstance.mm | 14 +++++++------ 4 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 packages/react-native/React/Base/RCTBridgeProxy+Cxx.h diff --git a/packages/react-native/React/Base/RCTBridgeProxy+Cxx.h b/packages/react-native/React/Base/RCTBridgeProxy+Cxx.h new file mode 100644 index 00000000000000..2748178a3dbb6e --- /dev/null +++ b/packages/react-native/React/Base/RCTBridgeProxy+Cxx.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#ifdef __cplusplus +#import +#endif + +#import "RCTBridgeProxy.h" + +@interface RCTBridgeProxy (Cxx) + +#ifdef __cplusplus +@property (nonatomic, readwrite) std::shared_ptr jsCallInvoker; +#endif + +@end diff --git a/packages/react-native/React/Base/RCTBridgeProxy.h b/packages/react-native/React/Base/RCTBridgeProxy.h index 79c75c3b491ae0..3a6de36473ee5b 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.h +++ b/packages/react-native/React/Base/RCTBridgeProxy.h @@ -15,6 +15,7 @@ @class RCTViewRegistry; @interface RCTBridgeProxy : NSProxy + - (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry moduleRegistry:(RCTModuleRegistry *)moduleRegistry bundleManager:(RCTBundleManager *)bundleManager @@ -34,4 +35,5 @@ */ - (id)moduleForClass:(Class)moduleClass; - (id)moduleForName:(NSString *)moduleName lazilyLoadIfNecessary:(BOOL)lazilyLoad; + @end diff --git a/packages/react-native/React/Base/RCTBridgeProxy.mm b/packages/react-native/React/Base/RCTBridgeProxy.mm index 6c1e914c2f86b7..27637daf654c1c 100644 --- a/packages/react-native/React/Base/RCTBridgeProxy.mm +++ b/packages/react-native/React/Base/RCTBridgeProxy.mm @@ -6,10 +6,13 @@ */ #import "RCTBridgeProxy.h" +#import "RCTBridgeProxy+Cxx.h" + #import #import #import #import +#import #import using namespace facebook; @@ -21,6 +24,12 @@ - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel; - (void)forwardInvocation:(NSInvocation *)invocation; @end +@interface RCTBridgeProxy () + +@property (nonatomic, readwrite) std::shared_ptr jsCallInvoker; + +@end + @implementation RCTBridgeProxy { RCTUIManagerProxy *_uiManagerProxy; RCTModuleRegistry *_moduleRegistry; @@ -84,6 +93,12 @@ - (void *)runtime return _runtime; } +- (std::shared_ptr)jsCallInvoker +{ + [self logWarning:@"Please migrate to RuntimeExecutor" cmd:_cmd]; + return _jsCallInvoker; +} + /** * RCTModuleRegistry */ diff --git a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm index 38f17f96129091..639cb889fab0e8 100644 --- a/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm +++ b/packages/react-native/ReactCommon/react/runtime/platform/ios/ReactCommon/RCTInstance.mm @@ -6,7 +6,6 @@ */ #import "RCTInstance.h" -#import #import @@ -16,6 +15,8 @@ #import #import #import +#import +#import #import #import #import @@ -256,6 +257,7 @@ - (void)_start RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor(); timerManager->setRuntimeExecutor(bufferedRuntimeExecutor); + auto jsCallInvoker = make_shared(bufferedRuntimeExecutor); RCTBridgeProxy *bridgeProxy = [[RCTBridgeProxy alloc] initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED moduleRegistry:_bridgeModuleDecorator.moduleRegistry @@ -274,14 +276,14 @@ - (void)_start } } runtime:_reactInstance->getJavaScriptContext()]; + bridgeProxy.jsCallInvoker = jsCallInvoker; [RCTBridge setCurrentBridge:(RCTBridge *)bridgeProxy]; // Set up TurboModules - _turboModuleManager = [[RCTTurboModuleManager alloc] - initWithBridgeProxy:bridgeProxy - bridgeModuleDecorator:_bridgeModuleDecorator - delegate:self - jsInvoker:std::make_shared(bufferedRuntimeExecutor)]; + _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridgeProxy:bridgeProxy + bridgeModuleDecorator:_bridgeModuleDecorator + delegate:self + jsInvoker:jsCallInvoker]; _turboModuleManager.runtimeHandler = self; #if RCT_DEV From bdca2606797f50f9ccb064bc7b25cd849ffe5e6c Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Mon, 11 Mar 2024 23:21:05 -0700 Subject: [PATCH 152/361] Fix Bridgeless React Context test in OSS (#43424) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43424 https://github.com/facebook/react-native/pull/43400/ caused a `getCatalystInstanceTest` to fail in OSS due to `bridgelessReactContext` not being a Mock object. Reviewed By: fkgozali Differential Revision: D54781539 fbshipit-source-id: 1c784804c31d4b57fe438d49f3ee3eb7034dd7a6 --- .../com/facebook/react/runtime/BridgelessReactContextTest.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt index 6f7eb6f474aed9..a3bf2053394eda 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/runtime/BridgelessReactContextTest.kt @@ -57,9 +57,7 @@ class BridgelessReactContextTest { @Test fun getCatalystInstanceTest() { - val bridgelessCatalystInstance = BridgelessCatalystInstance(reactHost) - doReturn(bridgelessCatalystInstance).`when`(bridgelessReactContext).getCatalystInstance() Assertions.assertThat(bridgelessReactContext.getCatalystInstance()) - .isEqualTo(bridgelessCatalystInstance) + .isInstanceOf(BridgelessCatalystInstance::class.java) } } From 9e2bb4efc38ecfdbfca9becdb2f8dc9639b4f39b Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 12 Mar 2024 04:25:17 -0700 Subject: [PATCH 153/361] Fix TimingModuleTest in OSS (#43422) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43422 After my changes in D54496604, this test now requires the main looper to progress as well, to dispatch the right callback. Changelog: [Internal] Reviewed By: rshest Differential Revision: D54776392 fbshipit-source-id: ba272a08d4b88d1c3301618eed1a03253e615b84 --- .../com/facebook/react/modules/timing/TimingModuleTest.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt index 86011414ab33a7..10cf42fde9b9ed 100644 --- a/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt +++ b/packages/react-native/ReactAndroid/src/test/java/com/facebook/react/modules/timing/TimingModuleTest.kt @@ -8,6 +8,7 @@ package com.facebook.react.modules.timing import android.content.Context +import android.os.Looper import android.view.Choreographer.FrameCallback import com.facebook.react.bridge.Arguments import com.facebook.react.bridge.CatalystInstance @@ -44,6 +45,7 @@ import org.mockito.Mockito.`when` as whenever import org.mockito.invocation.InvocationOnMock import org.mockito.stubbing.Answer import org.robolectric.RobolectricTestRunner +import org.robolectric.Shadows.shadowOf @RunWith(RobolectricTestRunner::class) class TimingModuleTest { @@ -138,6 +140,8 @@ class TimingModuleTest { } private fun stepChoreographerFrame() { + shadowOf(Looper.getMainLooper()).idle() + val callback = postFrameCallbackHandler.getAndResetFrameCallback() val idleCallback = idlePostFrameCallbackHandler.getAndResetFrameCallback() currentTimeNs += FRAME_TIME_NS From 2ed1e9ad28401af0cced62e42f7e60f54304450d Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 12 Mar 2024 04:32:01 -0700 Subject: [PATCH 154/361] remove sync events from TextInput (#43429) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43429 changelog: [internal] these experimental props have served their purpose and can be deleted. Reviewed By: rubennorte Differential Revision: D54682805 fbshipit-source-id: aee5072e2aa056c862f369426617d0d51c98997f --- .../TextInput/RCTTextInputViewConfig.js | 8 --- .../Components/TextInput/TextInput.js | 62 ------------------- .../TextInput/__tests__/TextInput-test.js | 19 +----- .../__snapshots__/TextInput-test.js.snap | 2 - .../__snapshots__/public-api-test.js.snap | 3 - .../TextInput/RCTTextInputComponentView.mm | 13 +--- .../iostextinput/TextInputEventEmitter.cpp | 16 ----- .../iostextinput/TextInputEventEmitter.h | 2 - 8 files changed, 3 insertions(+), 122 deletions(-) diff --git a/packages/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js b/packages/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js index f91026796ce9cb..2875ebb776d4c5 100644 --- a/packages/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js +++ b/packages/react-native/Libraries/Components/TextInput/RCTTextInputViewConfig.js @@ -79,18 +79,12 @@ const RCTTextInputViewConfig = { topTextInput: { registrationName: 'onTextInput', }, - topKeyPressSync: { - registrationName: 'onKeyPressSync', - }, topScroll: { registrationName: 'onScroll', }, topSelectionChange: { registrationName: 'onSelectionChange', }, - topChangeSync: { - registrationName: 'onChangeSync', - }, topContentSizeChange: { registrationName: 'onContentSizeChange', }, @@ -159,8 +153,6 @@ const RCTTextInputViewConfig = { onSelectionChange: true, onContentSizeChange: true, onScroll: true, - onChangeSync: true, - onKeyPressSync: true, onTextInput: true, }), }, diff --git a/packages/react-native/Libraries/Components/TextInput/TextInput.js b/packages/react-native/Libraries/Components/TextInput/TextInput.js index c8ead59c119222..7034e6b6320f4b 100644 --- a/packages/react-native/Libraries/Components/TextInput/TextInput.js +++ b/packages/react-native/Libraries/Components/TextInput/TextInput.js @@ -741,33 +741,12 @@ export type Props = $ReadOnly<{| */ onChange?: ?(e: ChangeEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * - * @platform ios - */ - unstable_onChangeSync?: ?(e: ChangeEvent) => mixed, - /** * Callback that is called when the text input's text changes. * Changed text is passed as an argument to the callback handler. */ onChangeText?: ?(text: string) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * Callback that is called when the text input's text changes. - * Changed text is passed as an argument to the callback handler. - * - * @platform ios - */ - unstable_onChangeTextSync?: ?(text: string) => mixed, - /** * Callback that is called when the text input's content size changes. * This will be called with @@ -796,21 +775,6 @@ export type Props = $ReadOnly<{| */ onKeyPress?: ?(e: KeyPressEvent) => mixed, - /** - * DANGER: this API is not stable and will change in the future. - * - * Callback will be called on the main thread and may result in dropped frames. - * - * Callback that is called when a key is pressed. - * This will be called with `{ nativeEvent: { key: keyValue } }` - * where `keyValue` is `'Enter'` or `'Backspace'` for respective keys and - * the typed-in character otherwise including `' '` for space. - * Fires before `onChange` callbacks. - * - * @platform ios - */ - unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed, - /** * Called when a single tap gesture is detected. */ @@ -1308,26 +1272,6 @@ function InternalTextInput(props: Props): React.Node { setMostRecentEventCount(event.nativeEvent.eventCount); }; - const _onChangeSync = (event: ChangeEvent) => { - const currentText = event.nativeEvent.text; - props.unstable_onChangeSync && props.unstable_onChangeSync(event); - props.unstable_onChangeTextSync && - props.unstable_onChangeTextSync(currentText); - - if (inputRef.current == null) { - // calling `props.onChange` or `props.onChangeText` - // may clean up the input itself. Exits here. - return; - } - - setLastNativeText(currentText); - // This must happen last, after we call setLastNativeText. - // Different ordering can cause bugs when editing AndroidTextInputs - // with multiple Fragments. - // We must update this so that controlled input updates work. - setMostRecentEventCount(event.nativeEvent.eventCount); - }; - const _onSelectionChange = (event: SelectionChangeEvent) => { props.onSelectionChange && props.onSelectionChange(event); @@ -1470,10 +1414,6 @@ function InternalTextInput(props: Props): React.Node { style.paddingVertical == null && style.paddingTop == null)); - const useOnChangeSync = - (props.unstable_onChangeSync || props.unstable_onChangeTextSync) && - !(props.onChange || props.onChangeText); - textInput = ( { input = renderTree.root.findByType(TextInput); }); it('has expected instance functions', () => { - expect(inputRef.current.isFocused).toBeInstanceOf(Function); // Would have prevented S168585 + expect(inputRef.current.isFocused).toBeInstanceOf(Function); // Would have prevented S168585 expect(inputRef.current.clear).toBeInstanceOf(Function); expect(inputRef.current.focus).toBeInstanceOf(jest.fn().constructor); expect(inputRef.current.blur).toBeInstanceOf(jest.fn().constructor); @@ -89,7 +78,6 @@ describe('TextInput tests', () => { it('focus() should not do anything if the TextInput is not editable', () => { const textInputRef = createTextInput({editable: false}); - // currentProps is the property actually containing props at runtime textInputRef.current.currentProps = textInputRef.current.props; expect(textInputRef.current.isFocused()).toBe(false); @@ -183,7 +171,6 @@ describe('TextInput tests', () => { mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} @@ -229,7 +216,6 @@ describe('TextInput', () => { mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} @@ -275,7 +261,6 @@ describe('TextInput compat with web', () => { nativeID="id" onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} @@ -407,7 +392,6 @@ describe('TextInput compat with web', () => { mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} @@ -450,7 +434,6 @@ describe('TextInput compat with web', () => { mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} diff --git a/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap b/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap index ac93dc2e644c7c..4c9b1e93b71ad5 100644 --- a/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap +++ b/packages/react-native/Libraries/Components/TextInput/__tests__/__snapshots__/TextInput-test.js.snap @@ -9,7 +9,6 @@ exports[`TextInput tests should render as expected: should deep render when mock mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} @@ -38,7 +37,6 @@ exports[`TextInput tests should render as expected: should deep render when not mostRecentEventCount={0} onBlur={[Function]} onChange={[Function]} - onChangeSync={null} onClick={[Function]} onFocus={[Function]} onResponderGrant={[Function]} diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 6b62f086b1dd09..ab7be2f1001e90 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -3041,14 +3041,11 @@ export type Props = $ReadOnly<{| multiline?: ?boolean, onBlur?: ?(e: BlurEvent) => mixed, onChange?: ?(e: ChangeEvent) => mixed, - unstable_onChangeSync?: ?(e: ChangeEvent) => mixed, onChangeText?: ?(text: string) => mixed, - unstable_onChangeTextSync?: ?(text: string) => mixed, onContentSizeChange?: ?(e: ContentSizeChangeEvent) => mixed, onEndEditing?: ?(e: EditingEvent) => mixed, onFocus?: ?(e: FocusEvent) => mixed, onKeyPress?: ?(e: KeyPressEvent) => mixed, - unstable_onKeyPressSync?: ?(e: KeyPressEvent) => mixed, onPress?: ?(event: PressEvent) => mixed, onPressIn?: ?(event: PressEvent) => mixed, onPressOut?: ?(event: PressEvent) => mixed, diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm index 44e74da5cea06f..7c50d3f81a3e41 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm @@ -341,11 +341,7 @@ - (NSString *)textInputShouldChangeText:(NSString *)text inRange:(NSRange)range keyPressMetrics.eventCount = _mostRecentEventCount; const auto &textInputEventEmitter = static_cast(*_eventEmitter); - if (props.onKeyPressSync) { - textInputEventEmitter.onKeyPressSync(keyPressMetrics); - } else { - textInputEventEmitter.onKeyPress(keyPressMetrics); - } + textInputEventEmitter.onKeyPress(keyPressMetrics); } } @@ -391,12 +387,7 @@ - (void)textInputDidChange if (_eventEmitter) { const auto &textInputEventEmitter = static_cast(*_eventEmitter); - const auto &props = static_cast(*_props); - if (props.onChangeSync) { - textInputEventEmitter.onChangeSync([self _textInputMetrics]); - } else { - textInputEventEmitter.onChange([self _textInputMetrics]); - } + textInputEventEmitter.onChange([self _textInputMetrics]); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp index 88ae3f35a221c6..8f1bf5734add40 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp @@ -91,12 +91,6 @@ void TextInputEventEmitter::onChange( dispatchTextInputEvent("change", textInputMetrics); } -void TextInputEventEmitter::onChangeSync( - const TextInputMetrics& textInputMetrics) const { - dispatchTextInputEvent( - "changeSync", textInputMetrics, EventPriority::SynchronousBatched); -} - void TextInputEventEmitter::onContentSizeChange( const TextInputMetrics& textInputMetrics) const { dispatchTextInputContentSizeChangeEvent( @@ -128,16 +122,6 @@ void TextInputEventEmitter::onKeyPress( EventPriority::AsynchronousBatched); } -void TextInputEventEmitter::onKeyPressSync( - const KeyPressMetrics& keyPressMetrics) const { - dispatchEvent( - "keyPressSync", - [keyPressMetrics](jsi::Runtime& runtime) { - return keyPressMetricsPayload(runtime, keyPressMetrics); - }, - EventPriority::SynchronousBatched); -} - void TextInputEventEmitter::onScroll( const TextInputMetrics& textInputMetrics) const { dispatchTextInputEvent("scroll", textInputMetrics); diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h index 0ab2b18544fc34..a4c68483c235b5 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h @@ -39,13 +39,11 @@ class TextInputEventEmitter : public ViewEventEmitter { void onFocus(const TextInputMetrics& textInputMetrics) const; void onBlur(const TextInputMetrics& textInputMetrics) const; void onChange(const TextInputMetrics& textInputMetrics) const; - void onChangeSync(const TextInputMetrics& textInputMetrics) const; void onContentSizeChange(const TextInputMetrics& textInputMetrics) const; void onSelectionChange(const TextInputMetrics& textInputMetrics) const; void onEndEditing(const TextInputMetrics& textInputMetrics) const; void onSubmitEditing(const TextInputMetrics& textInputMetrics) const; void onKeyPress(const KeyPressMetrics& keyPressMetrics) const; - void onKeyPressSync(const KeyPressMetrics& keyPressMetrics) const; void onScroll(const TextInputMetrics& textInputMetrics) const; private: From 81d39d9e161dac3f786a0a9439dde66684516f73 Mon Sep 17 00:00:00 2001 From: Alfonso Curbelo Date: Tue, 12 Mar 2024 04:36:57 -0700 Subject: [PATCH 155/361] Changelog: 0.72.12 (#43419) Summary: ## Changelog: Changelog: [INTERNAL] Generated changelog Pull Request resolved: https://github.com/facebook/react-native/pull/43419 Reviewed By: cortinico Differential Revision: D54799352 Pulled By: huntie fbshipit-source-id: ad777f8804e14da4b4ed77ea0742560c1d01c7b5 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 209201a145b5f9..f33e687f5b3291 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -644,6 +644,20 @@ - Fix race condition between A11yManager and UIManager ([f39f34ed82](https://github.com/facebook/react-native/commit/f39f34ed82997d0595522a285c3cb8693594e718) by [@cipolleschi](https://github.com/cipolleschi)) - Fix symbol not found _jump_fcontext with use_frameworks ([a2771ce58a](https://github.com/facebook/react-native/commit/a2771ce58ac221d1ac0de265c1ce571212fbcf83) by [@cipolleschi](https://github.com/cipolleschi)) +## v0.72.12 + +### Changed + +- Rename BUILD_FROM_SOURCE to RCT_BUILD_HERMES_FROM_SOURCE ([a215805eb7](https://github.com/facebook/react-native/commit/a215805eb73f687116af4aa74461ff4e17b05f42) by [@cipolleschi](https://github.com/cipolleschi)) + +#### iOS specific + +- [0.72] Fix flipper for Xcode 15.3 ([a316e0154e](https://github.com/facebook/react-native/commit/a316e0154ee8d1dd809be47694abb62d245bff0b) by [@cipolleschi](https://github.com/cipolleschi)) + +### Fixed + +- Fix flags for new arch ([0724c2769a](https://github.com/facebook/react-native/commit/0724c2769a3dea8f7886c8c541ffb49ae5c045dc) by [@cipolleschi](https://github.com/cipolleschi)) + ## v0.72.11 ### Changed From 276fdc414b26fd390d472d61f1ea7c9413b228fe Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 12 Mar 2024 05:38:45 -0700 Subject: [PATCH 156/361] Reduce logspam of missing instanceHandle (#43432) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43432 Changelog: [Internal] Reviewed By: sammy-SC, fabriziocucci Differential Revision: D54798889 fbshipit-source-id: 19cbac6b6bbb19242227ad9357cd9e8b86cdd331 --- .../ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index 03633a8a48566f..b57ecc3d38f5dc 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -158,7 +158,9 @@ void UIManagerBinding::dispatchEventToJS( : jsi::Value::null(); if (instanceHandle.isNull()) { - LOG(WARNING) << "instanceHandle is null, event will be dropped"; + // Do not log all missing instanceHandles to avoid log spam + LOG_EVERY_N(INFO, 10) << "instanceHandle is null, event of type " << type + << " will be dropped"; } currentEventPriority_ = priority; From 7a00623947f559741a1448a7dde1deea43558fd2 Mon Sep 17 00:00:00 2001 From: szymonrybczak Date: Tue, 12 Mar 2024 06:18:30 -0700 Subject: [PATCH 157/361] Update `@react-native-community/cli` to 14.0.0-alpha.0 (#43415) Summary: Updates CLI to 14.0.0-alpha.0 ## Changelog: [GENERAL] [CHANGED] - Update `react-native-community/cli` to 14.0.0-alpha.0 Pull Request resolved: https://github.com/facebook/react-native/pull/43415 Test Plan: CI Reviewed By: cortinico Differential Revision: D54760054 Pulled By: huntie fbshipit-source-id: c4e29e2122c5de0ff60f9c52bd6f9a86ce0a5560 --- packages/community-cli-plugin/package.json | 4 +- packages/react-native/package.json | 6 +- yarn.lock | 154 +++++++++------------ 3 files changed, 70 insertions(+), 94 deletions(-) diff --git a/packages/community-cli-plugin/package.json b/packages/community-cli-plugin/package.json index c293aa220b5b03..8c11a3927ededf 100644 --- a/packages/community-cli-plugin/package.json +++ b/packages/community-cli-plugin/package.json @@ -22,8 +22,8 @@ "dist" ], "dependencies": { - "@react-native-community/cli-server-api": "13.6.1", - "@react-native-community/cli-tools": "13.6.1", + "@react-native-community/cli-server-api": "14.0.0-alpha.0", + "@react-native-community/cli-tools": "14.0.0-alpha.0", "@react-native/dev-middleware": "0.75.0-main", "@react-native/metro-babel-transformer": "0.75.0-main", "chalk": "^4.0.0", diff --git a/packages/react-native/package.json b/packages/react-native/package.json index 286bfb3d4d7662..6475253fc7cb79 100644 --- a/packages/react-native/package.json +++ b/packages/react-native/package.json @@ -98,9 +98,9 @@ }, "dependencies": { "@jest/create-cache-key-function": "^29.6.3", - "@react-native-community/cli": "13.6.1", - "@react-native-community/cli-platform-android": "13.6.1", - "@react-native-community/cli-platform-ios": "13.6.1", + "@react-native-community/cli": "14.0.0-alpha.0", + "@react-native-community/cli-platform-android": "14.0.0-alpha.0", + "@react-native-community/cli-platform-ios": "14.0.0-alpha.0", "@react-native/assets-registry": "0.75.0-main", "@react-native/codegen": "0.75.0-main", "@react-native/community-cli-plugin": "0.75.0-main", diff --git a/yarn.lock b/yarn.lock index fe7f8b6cd828e9..a1aa51b8663429 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2384,51 +2384,50 @@ optionalDependencies: npmlog "2 || ^3.1.0 || ^4.0.0" -"@react-native-community/cli-clean@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-13.6.1.tgz#e4dce2aa8ea5a2fbdbfe8074e0c285bf4796d7be" - integrity sha512-HV0kTegCMbq9INOLUVzPFl/FDjZ2uX6kOa7cFYezkRhgApJo0a/KYTvqwQVlmdHXAjDiWLARGTUPqYQGwIef0A== +"@react-native-community/cli-clean@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-14.0.0-alpha.0.tgz#fc7bfd187c897e5e6431f7122370886bf55dd5a7" + integrity sha512-sZPH2riywRcbV0wzfbZSGJOLxcsIt1jyB4tKmQUCcJMTd+UFUykqmYRiAw1rqAEIXzh80TVkt5GwNnLduLiyEQ== dependencies: - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-tools" "14.0.0-alpha.0" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" -"@react-native-community/cli-config@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-13.6.1.tgz#b1f83fc1572d2500fb9e8d5b1a38ba417acb6eec" - integrity sha512-ljqwH04RNkwv8Y67TjmJ60qgvAdS2aCCUszaD7ZPXmfqBBxkvLg5QFtja9y+1QuTGPmBuTtC55JqmCHg/UDAsg== +"@react-native-community/cli-config@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-config/-/cli-config-14.0.0-alpha.0.tgz#ad5a7e11b9d43aad7ceb0a2098c7acacd5cc6205" + integrity sha512-jq/mQkuOoCG+aFlQEnlPAvfWRPDOLNtBoKUQhr3db7Eex3hVlxIKqOkrcgUnDghwOdAhq+Kx2KE5brwI2ETMNw== dependencies: - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-tools" "14.0.0-alpha.0" chalk "^4.1.2" cosmiconfig "^5.1.0" deepmerge "^4.3.0" fast-glob "^3.3.2" joi "^17.2.1" -"@react-native-community/cli-debugger-ui@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-13.6.1.tgz#7bb56be33d3ee2289bfbab7efa59a16a7554cd1a" - integrity sha512-3z1io3AsT1NqlJZOlqNFcrzlavBb7R+Vy5Orzruc3m/OIjc4TrGNtyzQmOfCC3peF8J3So3d6dH1a11YYUDfFw== +"@react-native-community/cli-debugger-ui@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-14.0.0-alpha.0.tgz#eb8e59f4d7fc29759f0e4034e96d003cbdc8d03e" + integrity sha512-L4SOp2ktqpo4rbEK+cE49SpJgAhPj/g1nhSHami0g5kVbZjwEPugHdZlb8jxSeqCoy1kaDOt+nASInvMfg2q4Q== dependencies: serve-static "^1.13.1" -"@react-native-community/cli-doctor@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-13.6.1.tgz#64b6e64c13cf8d318fe631ebc84834fa5650adf1" - integrity sha512-jP5otBbvcItuIy8WJT8UAA0lLB+0kKtCmcfQFmcs0/NlBy04cpTtGp7w2N3F1r2Qy9sdQWGRa20IFZn8eenieQ== +"@react-native-community/cli-doctor@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-doctor/-/cli-doctor-14.0.0-alpha.0.tgz#da539b9dddfc55d5d4ba49631fc427f1a265edd9" + integrity sha512-J7VmjyJlT9N3WryFsqFXriP9Fn7BlHqdkLa8P6TqABXxp7ZD21WrYgCqsDTR3pfBiyAFpOpyrgjO6d0RNu1SSQ== dependencies: - "@react-native-community/cli-config" "13.6.1" - "@react-native-community/cli-platform-android" "13.6.1" - "@react-native-community/cli-platform-apple" "13.6.1" - "@react-native-community/cli-platform-ios" "13.6.1" - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-config" "14.0.0-alpha.0" + "@react-native-community/cli-platform-android" "14.0.0-alpha.0" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.0" + "@react-native-community/cli-platform-ios" "14.0.0-alpha.0" + "@react-native-community/cli-tools" "14.0.0-alpha.0" chalk "^4.1.2" command-exists "^1.2.8" deepmerge "^4.3.0" envinfo "^7.10.0" execa "^5.0.0" - hermes-profile-transformer "^0.0.6" node-stream-zip "^1.9.1" ora "^5.4.1" semver "^7.5.2" @@ -2436,54 +2435,44 @@ wcwidth "^1.0.1" yaml "^2.2.1" -"@react-native-community/cli-hermes@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-hermes/-/cli-hermes-13.6.1.tgz#2d4de930ffbe30e02150031d33108059d51e7e17" - integrity sha512-uGzmpg3DCqXiVLArTw6LMCGoGPkdMBKUllnlvgl1Yjne6LL7NPnQ971lMVGqTX9/p3CaW5TcqYYJjnI7sxlVcA== +"@react-native-community/cli-platform-android@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-14.0.0-alpha.0.tgz#ea3deec43f8cfb8f6fd7e00310e6c8aa255223ab" + integrity sha512-iin6jxiiFGFoO5yySFI1GPuFJVmPpoXI3+sgSHxpCA6sqSJ7iZilwa0jzDKV4XqWFstmijh2zZJgiJvv9srurw== dependencies: - "@react-native-community/cli-platform-android" "13.6.1" - "@react-native-community/cli-tools" "13.6.1" - chalk "^4.1.2" - hermes-profile-transformer "^0.0.6" - -"@react-native-community/cli-platform-android@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-android/-/cli-platform-android-13.6.1.tgz#7ddac2b257425de54ea62b6e215c06a9bfc77e53" - integrity sha512-HkrV8kCbHUdWH2LMEeSsuvl0ULI+JLmBZ2eQNEyyYOT8h+tM90OwaPLRpBFtD+yvp2/DpIKo97yCVJT5cLjBzA== - dependencies: - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-tools" "14.0.0-alpha.0" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" fast-xml-parser "^4.2.4" logkitty "^0.7.1" -"@react-native-community/cli-platform-apple@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-13.6.1.tgz#cd0d393e8328f439f453bf90fcfec48b350e2f3a" - integrity sha512-yv4iPewUwhy3uGg4uJwA03wSV/1bnEnAJNs7CQ0zl7DQZhqrhfJLhzPURtu34sMUN+Wt6S3KaBmny5kHRKTuwA== +"@react-native-community/cli-platform-apple@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-apple/-/cli-platform-apple-14.0.0-alpha.0.tgz#a96d7bdd3776d711ea8c4027a38c1a7c3e554f48" + integrity sha512-8uTqmJu9wMRPStftzUUH7y5ZlYqzlkfaS1VDkz40V/ECnDQK24NzgHdm6UHckcydF4PomO4esEJUlBlMUZeK/w== dependencies: - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-tools" "14.0.0-alpha.0" chalk "^4.1.2" execa "^5.0.0" fast-glob "^3.3.2" fast-xml-parser "^4.0.12" ora "^5.4.1" -"@react-native-community/cli-platform-ios@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-13.6.1.tgz#fa3e3a6494a09538f369709a376f7d6d5c7f5ae5" - integrity sha512-JwXV9qMpqJWduoEcK3pbAjkOaTqg+o0IzZz/LP7EkFCfJyg5hnDRAUZhP5ffs5/zukZIGHHPY1ZEW8jl5T2j6Q== +"@react-native-community/cli-platform-ios@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-platform-ios/-/cli-platform-ios-14.0.0-alpha.0.tgz#a4ef1642ef11b5edde5124a547613d6ee10aa78a" + integrity sha512-m3Eouxh7MvMmiroFdl52dJp6uP5pRasoe1sEvZ0vDzqhENCb36N7lzLlHVAd05FT9/xsC3wQvRElGiJXGhOxwg== dependencies: - "@react-native-community/cli-platform-apple" "13.6.1" + "@react-native-community/cli-platform-apple" "14.0.0-alpha.0" -"@react-native-community/cli-server-api@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-13.6.1.tgz#6be357c07339856620b0881f000bfcf72f3af68c" - integrity sha512-64eC7NuCLenYr237LyJ1H6jf+6L4NA2eXuy+634q0CeIZsAqOe7B5VCJyy2CsWWaeeUbAsC0Oy9/2o2y8/muIw== +"@react-native-community/cli-server-api@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-server-api/-/cli-server-api-14.0.0-alpha.0.tgz#3a7faea110ed6ec137052e38991aeff7944a5c9a" + integrity sha512-LA212P8nfQtLe/EVjCDFeBdzPUSexescisdhHWHlAla/V6+MzhLr+RD2Umrahha0er/Z1Y7pzayy4j/Vhky6xQ== dependencies: - "@react-native-community/cli-debugger-ui" "13.6.1" - "@react-native-community/cli-tools" "13.6.1" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.0" + "@react-native-community/cli-tools" "14.0.0-alpha.0" compression "^1.7.1" connect "^3.6.5" errorhandler "^1.5.1" @@ -2492,10 +2481,10 @@ serve-static "^1.13.1" ws "^7.5.1" -"@react-native-community/cli-tools@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-13.6.1.tgz#f453a3e8ef13d114c05d77dafe411bc2a82f0279" - integrity sha512-mRJmI5c/Mfi/pESUPjqElv8+t81qfi0pUr1UrIX38nS1o5Ki1D8vC9vAMkPbLaIu2RuhUuzSCfs6zW8AwakUoA== +"@react-native-community/cli-tools@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-tools/-/cli-tools-14.0.0-alpha.0.tgz#39d223807859d922a991dafc4bedf36c0b21301d" + integrity sha512-+ypuOKGQnUVWbxZqfflwzSUWLv3tUZBGmrpdSZoNMOtPiR+JyxgtHA9IODwTDYmuFWG+nyRZDBE+eHSk0zutww== dependencies: appdirsjs "^1.2.4" chalk "^4.1.2" @@ -2509,31 +2498,30 @@ shell-quote "^1.7.3" sudo-prompt "^9.0.0" -"@react-native-community/cli-types@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-13.6.1.tgz#565e3dec401c86e5abb436f70b3f491d0e8cb919" - integrity sha512-+ue0eaEnGTKsTpX7F/DVspGDVZz7OgN7uaanaGKJuG9+pJiIgVIXnVu546Ycq8XbWAbZuWR1PL4+SNbf6Ebqqw== +"@react-native-community/cli-types@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli-types/-/cli-types-14.0.0-alpha.0.tgz#8877b21e271938750c061bbd7c9447ab961fc52d" + integrity sha512-1iQ6AgOxGz7oLlLSDOeGPD9ewPAW23OyYjVpv8+rcirZisHzqMT8zwuCtLo4vmAfKad2HB0yL2EjEDN2VFyNCQ== dependencies: joi "^17.2.1" -"@react-native-community/cli@13.6.1": - version "13.6.1" - resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-13.6.1.tgz#38a250422f172559bdbaa8f6f70a75a1cb9a14d2" - integrity sha512-Q3eA7xw42o8NAkztJvjVZT9WWxtRDnYYoRkv8IEIi9m2ya3p/4ZJBNlsQO6kDjasQTERkAoGQc1CveEHEv2QsA== - dependencies: - "@react-native-community/cli-clean" "13.6.1" - "@react-native-community/cli-config" "13.6.1" - "@react-native-community/cli-debugger-ui" "13.6.1" - "@react-native-community/cli-doctor" "13.6.1" - "@react-native-community/cli-hermes" "13.6.1" - "@react-native-community/cli-server-api" "13.6.1" - "@react-native-community/cli-tools" "13.6.1" - "@react-native-community/cli-types" "13.6.1" +"@react-native-community/cli@14.0.0-alpha.0": + version "14.0.0-alpha.0" + resolved "https://registry.yarnpkg.com/@react-native-community/cli/-/cli-14.0.0-alpha.0.tgz#f7b93f38043e07cd98ea73ae716425bc192fe4d3" + integrity sha512-gl0HvvchqgDtjybHrdzkwJP/gcxmO6pTjaCXfMKu1BrGv763ZPtTyWC1hJyZD8e8srMGspuBqed870Rv+rfgbA== + dependencies: + "@react-native-community/cli-clean" "14.0.0-alpha.0" + "@react-native-community/cli-config" "14.0.0-alpha.0" + "@react-native-community/cli-debugger-ui" "14.0.0-alpha.0" + "@react-native-community/cli-doctor" "14.0.0-alpha.0" + "@react-native-community/cli-server-api" "14.0.0-alpha.0" + "@react-native-community/cli-tools" "14.0.0-alpha.0" + "@react-native-community/cli-types" "14.0.0-alpha.0" chalk "^4.1.2" commander "^9.4.1" deepmerge "^4.3.0" execa "^5.0.0" - find-up "^4.1.0" + find-up "^5.0.0" fs-extra "^8.1.0" graceful-fs "^4.1.3" prompts "^2.4.2" @@ -5582,13 +5570,6 @@ hermes-parser@0.20.1: dependencies: hermes-estree "0.20.1" -hermes-profile-transformer@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz#bd0f5ecceda80dd0ddaae443469ab26fb38fc27b" - integrity sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ== - dependencies: - source-map "^0.7.3" - hermes-transform@0.20.1: version "0.20.1" resolved "https://registry.yarnpkg.com/hermes-transform/-/hermes-transform-0.20.1.tgz#910bd0ea7cc58eca4c0acadb413d779b70dd3803" @@ -8709,11 +8690,6 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@^0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" From e2c5a36ec78744617ba506cd1045f69cad87cf37 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Tue, 12 Mar 2024 08:19:49 -0700 Subject: [PATCH 158/361] Add enableHermesCDPAgent case to ReactInstanceIntegrationTest (#43436) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43436 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Expands test coverage for the Hermes `CDPAgent` implementation by enabling in `ReactInstanceIntegrationTest`. Changelog: [Internal] bypass-github-export-checks Reviewed By: motiz88 Differential Revision: D54801168 fbshipit-source-id: 9b71f8e697c7ab24c1383100938b3f648774a106 --- .../tests/ReactInstanceIntegrationTest.cpp | 21 ++++++++++++++----- .../utils/InspectorFlagOverridesGuard.cpp | 10 ++++++--- .../tests/utils/InspectorFlagOverridesGuard.h | 8 ++++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp index a945d692b9f8ee..2e0f5c209b1242 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp @@ -17,9 +17,11 @@ #include #include +using namespace ::testing; + namespace facebook::react::jsinspector_modern { -using namespace ::testing; +#pragma region ReactInstanceIntegrationTest ReactInstanceIntegrationTest::ReactInstanceIntegrationTest() : runtime(nullptr), @@ -179,6 +181,8 @@ bool ReactInstanceIntegrationTest::verbose(bool isVerbose) { return previous; } +#pragma endregion + TEST_F(ReactInstanceIntegrationTest, RuntimeEvalTest) { auto val = run("1 + 2"); EXPECT_EQ(val.asNumber(), 3); @@ -217,14 +221,21 @@ INSTANTIATE_TEST_SUITE_P( ReactInstanceVaryingInspectorFlags, ReactInstanceIntegrationTestWithFlags, ::testing::Values( - InspectorFlagOverrides{ - .enableCxxInspectorPackagerConnection = true, - .enableModernCDPRegistry = true}, InspectorFlagOverrides{ .enableCxxInspectorPackagerConnection = false, + .enableHermesCDPAgent = false, .enableModernCDPRegistry = false}, InspectorFlagOverrides{ .enableCxxInspectorPackagerConnection = true, - .enableModernCDPRegistry = false})); + .enableHermesCDPAgent = false, + .enableModernCDPRegistry = false}, + InspectorFlagOverrides{ + .enableCxxInspectorPackagerConnection = true, + .enableHermesCDPAgent = false, + .enableModernCDPRegistry = true}, + InspectorFlagOverrides{ + .enableCxxInspectorPackagerConnection = false, + .enableHermesCDPAgent = true, + .enableModernCDPRegistry = true})); } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp index ea6e640a59da10..816ec4a1b9818d 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.cpp @@ -27,15 +27,19 @@ class ReactNativeFeatureFlagsOverrides : overrides_(overrides) {} bool inspectorEnableCxxInspectorPackagerConnection() override { - return overrides_.enableCxxInspectorPackagerConnection; + return overrides_.enableCxxInspectorPackagerConnection.value_or( + ReactNativeFeatureFlagsDefaults:: + inspectorEnableCxxInspectorPackagerConnection()); } bool inspectorEnableHermesCDPAgent() override { - return overrides_.enableHermesCDPAgent; + return overrides_.enableHermesCDPAgent.value_or( + ReactNativeFeatureFlagsDefaults::inspectorEnableHermesCDPAgent()); } bool inspectorEnableModernCDPRegistry() override { - return overrides_.enableModernCDPRegistry; + return overrides_.enableModernCDPRegistry.value_or( + ReactNativeFeatureFlagsDefaults::inspectorEnableModernCDPRegistry()); } private: diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h index 5e91bb4cb8abf3..c998cbb2391ae7 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/utils/InspectorFlagOverridesGuard.h @@ -9,6 +9,8 @@ #include +#include + namespace facebook::react::jsinspector_modern { /** @@ -17,9 +19,9 @@ namespace facebook::react::jsinspector_modern { struct InspectorFlagOverrides { // NOTE: Keep these entries in sync with ReactNativeFeatureFlagsOverrides in // the implementation file. - bool enableCxxInspectorPackagerConnection = false; - bool enableHermesCDPAgent = false; - bool enableModernCDPRegistry = false; + std::optional enableCxxInspectorPackagerConnection; + std::optional enableHermesCDPAgent; + std::optional enableModernCDPRegistry; }; /** From d456e50bb0984374c6909b2872dde4ae2a6ae727 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 12 Mar 2024 08:59:30 -0700 Subject: [PATCH 159/361] Add new systrace sections in MountingCoordinator (#43408) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43408 Changelog: [internal] I think mount operations are taking longer than expected because of a debugging block (that we might remove). This adds some systrace sections to distinguish that from the overall time and confirm this only happens in debug builds. Reviewed By: sammy-SC Differential Revision: D54746491 fbshipit-source-id: 317b22b6dcd1ae117ed4a013180df8842bf712f0 --- .../react/renderer/mounting/MountingCoordinator.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp b/packages/react-native/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp index 9a8a36e7a7a3ae..6a0db7ab4263b7 100644 --- a/packages/react-native/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp +++ b/packages/react-native/ReactCommon/react/renderer/mounting/MountingCoordinator.cpp @@ -106,6 +106,8 @@ std::optional MountingCoordinator::pullTransaction() mountingOverrideDelegate->shouldOverridePullTransaction(); if (shouldOverridePullTransaction) { + SystraceSection section2("MountingCoordinator::overridePullTransaction"); + auto mutations = ShadowViewMutation::List{}; auto telemetry = TransactionTelemetry{}; @@ -128,6 +130,9 @@ std::optional MountingCoordinator::pullTransaction() #ifdef RN_SHADOW_TREE_INTROSPECTION if (transaction.has_value()) { + SystraceSection section2( + "MountingCoordinator::verifyMutationsForDebugging"); + // We have something to validate. auto mutations = transaction->getMutations(); From 032873a84c0f73f83a3020f3d43cefb0b82488aa Mon Sep 17 00:00:00 2001 From: Alfonso Curbelo Date: Tue, 12 Mar 2024 09:18:08 -0700 Subject: [PATCH 160/361] Add missing commit to 0.72.12 changelog (#43434) Summary: ## Changelog: [INTERNAL] - Add missing commit to 0.72.12 changelog Pull Request resolved: https://github.com/facebook/react-native/pull/43434 Reviewed By: huntie Differential Revision: D54805620 Pulled By: tdn120 fbshipit-source-id: c3bc31842b57c85fa584894132015f9856086876 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f33e687f5b3291..f56b93c3d918d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -656,6 +656,8 @@ ### Fixed +- Fix component stacks for tsx, ts, and jsx files ([dd311c9782](https://github.com/facebook/react-native/commit/dd311c9782c9f4d0f9d98423de2ae71227a24a7d) by [@rickhanlonii](https://github.com/rickhanlonii)) + - Fix flags for new arch ([0724c2769a](https://github.com/facebook/react-native/commit/0724c2769a3dea8f7886c8c541ffb49ae5c045dc) by [@cipolleschi](https://github.com/cipolleschi)) ## v0.72.11 From c62be78d99939e33b5b2bc3cee5be2a030f0640b Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Tue, 12 Mar 2024 09:39:00 -0700 Subject: [PATCH 161/361] feature(dev-middleware): use `userAgent` query parameter as fallback when header is unset (#43364) Summary: At Expo, we use [Expo Tools](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts) to connect the [built-in vscode-js-debug](https://github.com/microsoft/vscode-js-debug) to Hermes. Since there are a few differences in vscode vs chrome devtools, we need to enable a couple of modifications through the [`customMessageHandler` API](https://github.com/facebook/react-native/pull/43291). Unfortunately, vscode itself doesn't set the `user-agent` header when connecting to the inspector proxy. Becuase of that, we'd need a fallback to "manually" mark the debugger as being vscode ([we use this query parameter here](https://github.com/expo/vscode-expo/blob/main/src/expoDebuggers.ts#L208)). This PR supports setting the `user-agent` through `?userAgent=` when the header is not set. ## Changelog: [GENERAL] [ADDED] - Fallback to query parameter based `user-agent` when header is unset Pull Request resolved: https://github.com/facebook/react-native/pull/43364 Test Plan: - Install [Expo Tools](https://marketplace.visualstudio.com/items?itemName=expo.vscode-expo-tools) - Start Metro with this change. - Connect a device. - Run the vscode command `"Expo: Debug Expo app ..."` - Debugger should connect, and have it's user-agent marked as: `vscode/1.87.0 vscode-expo-tools/1.3.0` Reviewed By: huntie Differential Revision: D54804556 Pulled By: motiz88 fbshipit-source-id: 1ff558ba5350811ad042d08a713438e046759feb --- packages/dev-middleware/src/inspector-proxy/InspectorProxy.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index 0f4146d5e01884..532bf06c0b457c 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -258,7 +258,7 @@ export default class InspectorProxy implements InspectorProxyQueries { } device.handleDebuggerConnection(socket, pageId, { - userAgent: req.headers['user-agent'] ?? null, + userAgent: req.headers['user-agent'] ?? query.userAgent ?? null, }); } catch (e) { console.error(e); From 2830066b7cbe8a6857a7cc06a62148371c6b1404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 12 Mar 2024 09:54:11 -0700 Subject: [PATCH 162/361] Update feature flag generator to create directories for generated files before writing (#43393) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43393 Changelog: [internal] The generator doesn't create intermediate directories, which is causing issues now that we're moving the generated native module spec to a new directory. This fixes that. Reviewed By: rshest Differential Revision: D54690126 fbshipit-source-id: 1ba0d821872da7bbe1f6120ef6d0c1f800326778 --- packages/react-native/scripts/featureflags/generateFiles.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/react-native/scripts/featureflags/generateFiles.js b/packages/react-native/scripts/featureflags/generateFiles.js index f03df2163e6496..8f155b1350aeb5 100644 --- a/packages/react-native/scripts/featureflags/generateFiles.js +++ b/packages/react-native/scripts/featureflags/generateFiles.js @@ -14,6 +14,7 @@ import generateAndroidModules from './generateAndroidModules'; import generateCommonCxxModules from './generateCommonCxxModules'; import generateJavaScriptModules from './generateJavaScriptModules'; import fs from 'fs'; +import path from 'path'; export default function generateFiles( generatorConfig: GeneratorConfig, @@ -65,6 +66,7 @@ export default function generateFiles( } for (const [modulePath, moduleContents] of Object.entries(generatedFiles)) { - fs.writeFileSync(modulePath, moduleContents, 'utf8'); + fs.mkdirSync(path.dirname(modulePath), {recursive: true}); + fs.writeFileSync(modulePath, moduleContents, {encoding: 'utf8'}); } } From 9c9c7edeb3b20056147fec72f32d9ed1af32fd13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 12 Mar 2024 09:54:11 -0700 Subject: [PATCH 163/361] Allow accessing common feature flags before setting overrides for JS-only overrides (#43394) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43394 Changelog: [internal] When we built the new feature flag system we added a constraint in the JS API to prevent calling `override` if any of the flags was already accessed from JS. This is very restrictive because it doesn't allow us to access common flags (like `enableMicrotasks`) set up from native during the initialization of the framework because then applications wouldn't be able to set JS-only overrides. This relaxes the constraint to disallow accessing JS-only flags before setting JS-only overrides, but accessing common (native) flags before that is ok. Reviewed By: rshest Differential Revision: D54687055 fbshipit-source-id: b0716f24baf7d12a5e4a61fba79e6b50ef0ad10a --- .../ReactNativeFeatureFlagsBase.js | 6 ++++-- .../__tests__/ReactNativeFeatureFlags-test.js | 20 ++++++++++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js index 3223800bed4add..d7398c5358cafa 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js @@ -29,7 +29,6 @@ function createGetter( return () => { if (cachedValue == null) { - accessedFeatureFlags.add(configName); cachedValue = customValueGetter() ?? defaultValue; } return cachedValue; @@ -44,7 +43,10 @@ export function createJavaScriptFlagGetter< ): Getter> { return createGetter( configName, - () => overrides?.[configName]?.(), + () => { + accessedFeatureFlags.add(configName); + return overrides?.[configName]?.(); + }, defaultValue, ); } diff --git a/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js b/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js index 02d61696e10fbf..0b3ea72ec38b1e 100644 --- a/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js +++ b/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js @@ -84,20 +84,34 @@ describe('ReactNativeFeatureFlags', () => { expect(jsOnlyTestFlagFn).toHaveBeenCalledTimes(1); }); - it('should throw an error if any of the flags has been accessed before overridding', () => { + it('should throw an error if any of the JS flags has been accessed before overridding', () => { const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags'); - ReactNativeFeatureFlags.commonTestFlag(); + ReactNativeFeatureFlags.jsOnlyTestFlag(); expect(() => ReactNativeFeatureFlags.override({ jsOnlyTestFlag: () => true, }), ).toThrow( - 'Feature flags were accessed before being overridden: commonTestFlag', + 'Feature flags were accessed before being overridden: jsOnlyTestFlag', ); }); + it('should NOT throw an error if any of the common flags has been accessed before overridding', () => { + const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags'); + + ReactNativeFeatureFlags.commonTestFlag(); + + expect(() => { + ReactNativeFeatureFlags.override({ + jsOnlyTestFlag: () => true, + }); + }).not.toThrow(); + + expect(ReactNativeFeatureFlags.jsOnlyTestFlag()).toBe(true); + }); + it('should throw an error when trying to set overrides twice', () => { const ReactNativeFeatureFlags = require('../ReactNativeFeatureFlags'); From 4799d0cc5c0adee238222dd89a9aaa81ee9298ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 12 Mar 2024 09:54:11 -0700 Subject: [PATCH 164/361] Move spec files to specs directories in react-native/src/private (#43395) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43395 Changelog: [internal] This moves native module specs to `specs` directory to align with the general convention. Reviewed By: cortinico Differential Revision: D54680056 fbshipit-source-id: 8b6ae6187e2ffa9120159b7d1fa25957677e0f4f --- .../Libraries/Core/setUpPerformance.js | 2 +- .../featureflags/generateJavaScriptModules.js | 2 +- ...tiveReactNativeFeatureFlags.js-template.js | 4 +- .../ReactNativeFeatureFlagsBase.js | 2 +- .../__tests__/ReactNativeFeatureFlags-test.js | 4 +- .../specs/NativeReactNativeFeatureFlags.js | 45 +++++++++++++++++++ .../webapis/performance/EventCounts.js | 2 +- .../webapis/performance/Performance.js | 4 +- .../performance/PerformanceObserver.js | 2 +- .../performance/RawPerformanceEntry.js | 4 +- .../performance/__tests__/EventCounts-test.js | 6 +-- .../performance/__tests__/Performance-test.js | 8 ++-- .../__tests__/PerformanceObserver-test.js | 6 +-- .../{ => specs}/BoundedConsumableBuffer.h | 0 .../{ => specs}/NativePerformance.cpp | 0 .../{ => specs}/NativePerformance.h | 0 .../{ => specs}/NativePerformance.js | 4 +- .../{ => specs}/NativePerformanceObserver.cpp | 0 .../{ => specs}/NativePerformanceObserver.h | 0 .../{ => specs}/NativePerformanceObserver.js | 4 +- .../{ => specs}/PerformanceEntryReporter.cpp | 0 .../{ => specs}/PerformanceEntryReporter.h | 0 .../__mocks__/NativePerformance.js | 2 +- .../__mocks__/NativePerformanceObserver.js | 2 +- .../__tests__/BoundedConsumableBufferTest.cpp | 0 .../__tests__/NativePerformanceMock-test.js | 2 +- .../NativePerformanceObserverMock-test.js | 2 +- .../PerformanceEntryReporterTest.cpp | 0 28 files changed, 76 insertions(+), 31 deletions(-) create mode 100644 packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js rename packages/react-native/src/private/webapis/performance/{ => specs}/BoundedConsumableBuffer.h (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformance.cpp (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformance.h (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformance.js (81%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformanceObserver.cpp (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformanceObserver.h (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/NativePerformanceObserver.js (90%) rename packages/react-native/src/private/webapis/performance/{ => specs}/PerformanceEntryReporter.cpp (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/PerformanceEntryReporter.h (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__mocks__/NativePerformance.js (95%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__mocks__/NativePerformanceObserver.js (97%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__tests__/BoundedConsumableBufferTest.cpp (100%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__tests__/NativePerformanceMock-test.js (96%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__tests__/NativePerformanceObserverMock-test.js (97%) rename packages/react-native/src/private/webapis/performance/{ => specs}/__tests__/PerformanceEntryReporterTest.cpp (100%) diff --git a/packages/react-native/Libraries/Core/setUpPerformance.js b/packages/react-native/Libraries/Core/setUpPerformance.js index a33afb30cae53d..acd41a7398c4e7 100644 --- a/packages/react-native/Libraries/Core/setUpPerformance.js +++ b/packages/react-native/Libraries/Core/setUpPerformance.js @@ -8,8 +8,8 @@ * @format */ -import NativePerformance from '../../src/private/webapis/performance/NativePerformance'; import Performance from '../../src/private/webapis/performance/Performance'; +import NativePerformance from '../../src/private/webapis/performance/specs/NativePerformance'; // In case if the native implementation of the Performance API is available, use it, // otherwise fall back to the legacy/default one, which only defines 'Performance.now()' diff --git a/packages/react-native/scripts/featureflags/generateJavaScriptModules.js b/packages/react-native/scripts/featureflags/generateJavaScriptModules.js index 4fc7d30e15530a..f005295478297a 100644 --- a/packages/react-native/scripts/featureflags/generateJavaScriptModules.js +++ b/packages/react-native/scripts/featureflags/generateJavaScriptModules.js @@ -25,7 +25,7 @@ export default function generateCommonCxxModules( return { [path.join(jsPath, 'ReactNativeFeatureFlags.js')]: ReactNativeFeatureFlagsJS(featureFlagDefinitions), - [path.join(jsPath, 'NativeReactNativeFeatureFlags.js')]: + [path.join(jsPath, 'specs', 'NativeReactNativeFeatureFlags.js')]: NativeReactNativeFeatureFlagsJS(featureFlagDefinitions), [path.join(commonNativeModuleCxxPath, 'NativeReactNativeFeatureFlags.h')]: NativeReactNativeFeatureFlagsH(featureFlagDefinitions), diff --git a/packages/react-native/scripts/featureflags/templates/js/NativeReactNativeFeatureFlags.js-template.js b/packages/react-native/scripts/featureflags/templates/js/NativeReactNativeFeatureFlags.js-template.js index 9c9e557879dbe1..0d6a1ca64515a9 100644 --- a/packages/react-native/scripts/featureflags/templates/js/NativeReactNativeFeatureFlags.js-template.js +++ b/packages/react-native/scripts/featureflags/templates/js/NativeReactNativeFeatureFlags.js-template.js @@ -26,9 +26,9 @@ export default function (definitions: FeatureFlagDefinitions): string { ${DO_NOT_MODIFY_COMMENT} -import type {TurboModule} from '../../../Libraries/TurboModule/RCTExport'; +import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; -import * as TurboModuleRegistry from '../../../Libraries/TurboModule/TurboModuleRegistry'; +import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; export interface Spec extends TurboModule { ${Object.entries(definitions.common) diff --git a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js index d7398c5358cafa..61d8266b9551a8 100644 --- a/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js +++ b/packages/react-native/src/private/featureflags/ReactNativeFeatureFlagsBase.js @@ -13,7 +13,7 @@ import type { ReactNativeFeatureFlagsJsOnlyOverrides, } from './ReactNativeFeatureFlags'; -import NativeReactNativeFeatureFlags from './NativeReactNativeFeatureFlags'; +import NativeReactNativeFeatureFlags from './specs/NativeReactNativeFeatureFlags'; const accessedFeatureFlags: Set = new Set(); let overrides: ?ReactNativeFeatureFlagsJsOnlyOverrides; diff --git a/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js b/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js index 0b3ea72ec38b1e..0d69a1afc3a9ba 100644 --- a/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js +++ b/packages/react-native/src/private/featureflags/__tests__/ReactNativeFeatureFlags-test.js @@ -27,7 +27,7 @@ describe('ReactNativeFeatureFlags', () => { }); it('should provide default values for common flags and log an error if the method in the native module is NOT available', () => { - jest.doMock('../NativeReactNativeFeatureFlags', () => ({ + jest.doMock('../specs/NativeReactNativeFeatureFlags', () => ({ __esModule: true, default: {}, })); @@ -44,7 +44,7 @@ describe('ReactNativeFeatureFlags', () => { it('should access and cache common flags from the native module if it is available', () => { const commonTestFlagFn = jest.fn(() => true); - jest.doMock('../NativeReactNativeFeatureFlags', () => ({ + jest.doMock('../specs/NativeReactNativeFeatureFlags', () => ({ __esModule: true, default: { commonTestFlag: commonTestFlagFn, diff --git a/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js new file mode 100644 index 00000000000000..156b73aad3d120 --- /dev/null +++ b/packages/react-native/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js @@ -0,0 +1,45 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<> + * @flow strict-local + */ + +/** + * IMPORTANT: Do NOT modify this file directly. + * + * To change the definition of the flags, edit + * packages/react-native/scripts/featureflags/ReactNativeFeatureFlags.config.js. + * + * To regenerate this code, run the following script from the repo root: + * yarn featureflags-update + */ + +import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; + +import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +commonTestFlag?: () => boolean; + +batchRenderingUpdatesInEventLoop?: () => boolean; + +enableBackgroundExecutor?: () => boolean; + +enableCustomDrawOrderFabric?: () => boolean; + +enableFixForClippedSubviewsCrash?: () => boolean; + +enableMicrotasks?: () => boolean; + +enableMountHooksAndroid?: () => boolean; + +enableSpannableBuildingUnification?: () => boolean; + +inspectorEnableCxxInspectorPackagerConnection?: () => boolean; + +inspectorEnableHermesCDPAgent?: () => boolean; + +inspectorEnableModernCDPRegistry?: () => boolean; + +skipMountHookNotifications?: () => boolean; + +useModernRuntimeScheduler?: () => boolean; +} + +const NativeReactNativeFeatureFlags: ?Spec = TurboModuleRegistry.get( + 'NativeReactNativeFeatureFlagsCxx', +); + +export default NativeReactNativeFeatureFlags; diff --git a/packages/react-native/src/private/webapis/performance/EventCounts.js b/packages/react-native/src/private/webapis/performance/EventCounts.js index 27ece857093b23..682ef5557072b5 100644 --- a/packages/react-native/src/private/webapis/performance/EventCounts.js +++ b/packages/react-native/src/private/webapis/performance/EventCounts.js @@ -8,8 +8,8 @@ * @format */ -import NativePerformanceObserver from './NativePerformanceObserver'; import {warnNoNativePerformanceObserver} from './PerformanceObserver'; +import NativePerformanceObserver from './specs/NativePerformanceObserver'; type EventCountsForEachCallbackType = | (() => void) diff --git a/packages/react-native/src/private/webapis/performance/Performance.js b/packages/react-native/src/private/webapis/performance/Performance.js index 92befaae912372..e17230cc893a5d 100644 --- a/packages/react-native/src/private/webapis/performance/Performance.js +++ b/packages/react-native/src/private/webapis/performance/Performance.js @@ -16,8 +16,6 @@ import type {PerformanceEntryList} from './PerformanceObserver'; import warnOnce from '../../../../Libraries/Utilities/warnOnce'; import EventCounts from './EventCounts'; import MemoryInfo from './MemoryInfo'; -import NativePerformance from './NativePerformance'; -import NativePerformanceObserver from './NativePerformanceObserver'; import {ALWAYS_LOGGED_ENTRY_TYPES, PerformanceEntry} from './PerformanceEntry'; import {warnNoNativePerformanceObserver} from './PerformanceObserver'; import { @@ -26,6 +24,8 @@ import { } from './RawPerformanceEntry'; import {RawPerformanceEntryTypeValues} from './RawPerformanceEntry'; import ReactNativeStartupTiming from './ReactNativeStartupTiming'; +import NativePerformance from './specs/NativePerformance'; +import NativePerformanceObserver from './specs/NativePerformanceObserver'; type DetailType = mixed; diff --git a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js index c8caee14662fbd..4a37d3e4f159c5 100644 --- a/packages/react-native/src/private/webapis/performance/PerformanceObserver.js +++ b/packages/react-native/src/private/webapis/performance/PerformanceObserver.js @@ -11,7 +11,6 @@ import type {HighResTimeStamp, PerformanceEntryType} from './PerformanceEntry'; import warnOnce from '../../../../Libraries/Utilities/warnOnce'; -import NativePerformanceObserver from './NativePerformanceObserver'; import {PerformanceEntry} from './PerformanceEntry'; import PerformanceEventTiming from './PerformanceEventTiming'; import { @@ -19,6 +18,7 @@ import { rawToPerformanceEntry, rawToPerformanceEntryType, } from './RawPerformanceEntry'; +import NativePerformanceObserver from './specs/NativePerformanceObserver'; export type PerformanceEntryList = $ReadOnlyArray; diff --git a/packages/react-native/src/private/webapis/performance/RawPerformanceEntry.js b/packages/react-native/src/private/webapis/performance/RawPerformanceEntry.js index 767a8bdd61795f..e1ef5a5c2b8a41 100644 --- a/packages/react-native/src/private/webapis/performance/RawPerformanceEntry.js +++ b/packages/react-native/src/private/webapis/performance/RawPerformanceEntry.js @@ -8,11 +8,11 @@ * @flow strict */ +import type {PerformanceEntryType} from './PerformanceEntry'; import type { RawPerformanceEntry, RawPerformanceEntryType, -} from './NativePerformanceObserver'; -import type {PerformanceEntryType} from './PerformanceEntry'; +} from './specs/NativePerformanceObserver'; import {PerformanceEntry} from './PerformanceEntry'; import PerformanceEventTiming from './PerformanceEventTiming'; diff --git a/packages/react-native/src/private/webapis/performance/__tests__/EventCounts-test.js b/packages/react-native/src/private/webapis/performance/__tests__/EventCounts-test.js index 7be1b9c1fd8c45..953349f9fe7c43 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/EventCounts-test.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/EventCounts-test.js @@ -12,12 +12,12 @@ import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; // NOTE: Jest mocks of transitive dependencies don't appear to work with // ES6 module imports, therefore forced to use commonjs style imports here. -const NativePerformanceObserver = require('../NativePerformanceObserver'); const Performance = require('../Performance').default; +const NativePerformanceObserver = require('../specs/NativePerformanceObserver'); jest.mock( - '../NativePerformanceObserver', - () => require('../__mocks__/NativePerformanceObserver').default, + '../specs/NativePerformanceObserver', + () => require('../specs/__mocks__/NativePerformanceObserver').default, ); describe('EventCounts', () => { diff --git a/packages/react-native/src/private/webapis/performance/__tests__/Performance-test.js b/packages/react-native/src/private/webapis/performance/__tests__/Performance-test.js index a5e85831ae3a5f..bb637df30d9075 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/Performance-test.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/Performance-test.js @@ -11,13 +11,13 @@ const Performance = require('../Performance').default; jest.mock( - '../NativePerformance', - () => require('../__mocks__/NativePerformance').default, + '../specs/NativePerformance', + () => require('../specs/__mocks__/NativePerformance').default, ); jest.mock( - '../NativePerformanceObserver', - () => require('../__mocks__/NativePerformanceObserver').default, + '../specs/NativePerformanceObserver', + () => require('../specs/__mocks__/NativePerformanceObserver').default, ); describe('Performance', () => { diff --git a/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-test.js b/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-test.js index a6e6a37be9ff62..cf46dcbfd0e2d8 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-test.js +++ b/packages/react-native/src/private/webapis/performance/__tests__/PerformanceObserver-test.js @@ -12,12 +12,12 @@ import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; // NOTE: Jest mocks of transitive dependencies don't appear to work with // ES6 module imports, therefore forced to use commonjs style imports here. -const NativePerformanceObserver = require('../NativePerformanceObserver'); const PerformanceObserver = require('../PerformanceObserver').default; +const NativePerformanceObserver = require('../specs/NativePerformanceObserver'); jest.mock( - '../NativePerformanceObserver', - () => require('../__mocks__/NativePerformanceObserver').default, + '../specs/NativePerformanceObserver', + () => require('../specs/__mocks__/NativePerformanceObserver').default, ); describe('PerformanceObserver', () => { diff --git a/packages/react-native/src/private/webapis/performance/BoundedConsumableBuffer.h b/packages/react-native/src/private/webapis/performance/specs/BoundedConsumableBuffer.h similarity index 100% rename from packages/react-native/src/private/webapis/performance/BoundedConsumableBuffer.h rename to packages/react-native/src/private/webapis/performance/specs/BoundedConsumableBuffer.h diff --git a/packages/react-native/src/private/webapis/performance/NativePerformance.cpp b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.cpp similarity index 100% rename from packages/react-native/src/private/webapis/performance/NativePerformance.cpp rename to packages/react-native/src/private/webapis/performance/specs/NativePerformance.cpp diff --git a/packages/react-native/src/private/webapis/performance/NativePerformance.h b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.h similarity index 100% rename from packages/react-native/src/private/webapis/performance/NativePerformance.h rename to packages/react-native/src/private/webapis/performance/specs/NativePerformance.h diff --git a/packages/react-native/src/private/webapis/performance/NativePerformance.js b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js similarity index 81% rename from packages/react-native/src/private/webapis/performance/NativePerformance.js rename to packages/react-native/src/private/webapis/performance/specs/NativePerformance.js index ac8d410af92dfe..beebbcc6558d97 100644 --- a/packages/react-native/src/private/webapis/performance/NativePerformance.js +++ b/packages/react-native/src/private/webapis/performance/specs/NativePerformance.js @@ -8,9 +8,9 @@ * @format */ -import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; +import type {TurboModule} from '../../../../../Libraries/TurboModule/RCTExport'; -import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; +import * as TurboModuleRegistry from '../../../../../Libraries/TurboModule/TurboModuleRegistry'; export type NativeMemoryInfo = {[key: string]: ?number}; diff --git a/packages/react-native/src/private/webapis/performance/NativePerformanceObserver.cpp b/packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.cpp similarity index 100% rename from packages/react-native/src/private/webapis/performance/NativePerformanceObserver.cpp rename to packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.cpp diff --git a/packages/react-native/src/private/webapis/performance/NativePerformanceObserver.h b/packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.h similarity index 100% rename from packages/react-native/src/private/webapis/performance/NativePerformanceObserver.h rename to packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.h diff --git a/packages/react-native/src/private/webapis/performance/NativePerformanceObserver.js b/packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.js similarity index 90% rename from packages/react-native/src/private/webapis/performance/NativePerformanceObserver.js rename to packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.js index 3881872fcca468..af2e2c3a68ce6b 100644 --- a/packages/react-native/src/private/webapis/performance/NativePerformanceObserver.js +++ b/packages/react-native/src/private/webapis/performance/specs/NativePerformanceObserver.js @@ -8,9 +8,9 @@ * @format */ -import type {TurboModule} from '../../../../Libraries/TurboModule/RCTExport'; +import type {TurboModule} from '../../../../../Libraries/TurboModule/RCTExport'; -import * as TurboModuleRegistry from '../../../../Libraries/TurboModule/TurboModuleRegistry'; +import * as TurboModuleRegistry from '../../../../../Libraries/TurboModule/TurboModuleRegistry'; export type RawPerformanceEntryType = number; diff --git a/packages/react-native/src/private/webapis/performance/PerformanceEntryReporter.cpp b/packages/react-native/src/private/webapis/performance/specs/PerformanceEntryReporter.cpp similarity index 100% rename from packages/react-native/src/private/webapis/performance/PerformanceEntryReporter.cpp rename to packages/react-native/src/private/webapis/performance/specs/PerformanceEntryReporter.cpp diff --git a/packages/react-native/src/private/webapis/performance/PerformanceEntryReporter.h b/packages/react-native/src/private/webapis/performance/specs/PerformanceEntryReporter.h similarity index 100% rename from packages/react-native/src/private/webapis/performance/PerformanceEntryReporter.h rename to packages/react-native/src/private/webapis/performance/specs/PerformanceEntryReporter.h diff --git a/packages/react-native/src/private/webapis/performance/__mocks__/NativePerformance.js b/packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformance.js similarity index 95% rename from packages/react-native/src/private/webapis/performance/__mocks__/NativePerformance.js rename to packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformance.js index ee5eed6e6b0157..b1e7072584fbf8 100644 --- a/packages/react-native/src/private/webapis/performance/__mocks__/NativePerformance.js +++ b/packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformance.js @@ -14,8 +14,8 @@ import type { Spec as NativePerformance, } from '../NativePerformance'; +import {RawPerformanceEntryTypeValues} from '../../RawPerformanceEntry'; import NativePerformanceObserver from '../NativePerformanceObserver'; -import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; const marks: Map = new Map(); diff --git a/packages/react-native/src/private/webapis/performance/__mocks__/NativePerformanceObserver.js b/packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js similarity index 97% rename from packages/react-native/src/private/webapis/performance/__mocks__/NativePerformanceObserver.js rename to packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js index dd0fd1acb7f537..9e71ab98692922 100644 --- a/packages/react-native/src/private/webapis/performance/__mocks__/NativePerformanceObserver.js +++ b/packages/react-native/src/private/webapis/performance/specs/__mocks__/NativePerformanceObserver.js @@ -15,7 +15,7 @@ import type { Spec as NativePerformanceObserver, } from '../NativePerformanceObserver'; -import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; +import {RawPerformanceEntryTypeValues} from '../../RawPerformanceEntry'; const reportingType: Set = new Set(); const isAlwaysLogged: Set = new Set(); diff --git a/packages/react-native/src/private/webapis/performance/__tests__/BoundedConsumableBufferTest.cpp b/packages/react-native/src/private/webapis/performance/specs/__tests__/BoundedConsumableBufferTest.cpp similarity index 100% rename from packages/react-native/src/private/webapis/performance/__tests__/BoundedConsumableBufferTest.cpp rename to packages/react-native/src/private/webapis/performance/specs/__tests__/BoundedConsumableBufferTest.cpp diff --git a/packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceMock-test.js b/packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceMock-test.js similarity index 96% rename from packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceMock-test.js rename to packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceMock-test.js index 679dad39dfc5e5..1d700ce9e5fd7e 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceMock-test.js +++ b/packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceMock-test.js @@ -9,7 +9,7 @@ */ const NativePerformanceMock = require('../__mocks__/NativePerformance').default; -const PerformanceObserver = require('../PerformanceObserver').default; +const PerformanceObserver = require('../../PerformanceObserver').default; describe('NativePerformanceMock', () => { jest.mock( diff --git a/packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceObserverMock-test.js b/packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceObserverMock-test.js similarity index 97% rename from packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceObserverMock-test.js rename to packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceObserverMock-test.js index a4d8a575d74e3f..7b5c62a362a8da 100644 --- a/packages/react-native/src/private/webapis/performance/__tests__/NativePerformanceObserverMock-test.js +++ b/packages/react-native/src/private/webapis/performance/specs/__tests__/NativePerformanceObserverMock-test.js @@ -9,7 +9,7 @@ */ import NativePerformanceObserverMock from '../__mocks__/NativePerformanceObserver'; -import {RawPerformanceEntryTypeValues} from '../RawPerformanceEntry'; +import {RawPerformanceEntryTypeValues} from '../../RawPerformanceEntry'; describe('NativePerformanceObserver', () => { it('correctly starts and stops listening to entries in a nominal scenario', async () => { diff --git a/packages/react-native/src/private/webapis/performance/__tests__/PerformanceEntryReporterTest.cpp b/packages/react-native/src/private/webapis/performance/specs/__tests__/PerformanceEntryReporterTest.cpp similarity index 100% rename from packages/react-native/src/private/webapis/performance/__tests__/PerformanceEntryReporterTest.cpp rename to packages/react-native/src/private/webapis/performance/specs/__tests__/PerformanceEntryReporterTest.cpp From 5833eb59e3087728a2098f0c55ea54d96af06c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Tue, 12 Mar 2024 09:54:11 -0700 Subject: [PATCH 165/361] Implement microtasks using new JSI method (#43397) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43397 Changelog: [internal] This migrates the Hermes-specific use of microtasks to an engine agnostic implementation based on the new JSI method to queue microtasks. Reviewed By: sammy-SC Differential Revision: D54687056 fbshipit-source-id: b077ba47b80f7b31c77b7e449def8a56061b0b69 --- .../Libraries/AppDelegate/RCTAppDelegate.mm | 5 ++ .../AppDelegate/React-RCTAppDelegate.podspec | 1 + .../Libraries/Core/setUpTimers.js | 67 ++++++++++--------- .../ReactAndroid/src/main/jni/CMakeLists.txt | 1 + .../jni/react/newarchdefaults/CMakeLists.txt | 1 + .../DefaultTurboModuleManagerDelegate.cpp | 5 ++ .../nativemodule/microtasks/CMakeLists.txt | 24 +++++++ .../microtasks/NativeMicrotasks.cpp | 31 +++++++++ .../microtasks/NativeMicrotasks.h | 28 ++++++++ .../React-microtasksnativemodule.podspec | 48 +++++++++++++ .../react-native/scripts/react_native_pods.rb | 1 + .../microtasks/specs/NativeMicrotasks.js | 19 ++++++ 12 files changed, 200 insertions(+), 31 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/nativemodule/microtasks/CMakeLists.txt create mode 100644 packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.cpp create mode 100644 packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.h create mode 100644 packages/react-native/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec create mode 100644 packages/react-native/src/private/webapis/microtasks/specs/NativeMicrotasks.js diff --git a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm index 64b9ccceca897a..b58482512a87ad 100644 --- a/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm +++ b/packages/react-native/Libraries/AppDelegate/RCTAppDelegate.mm @@ -29,6 +29,7 @@ #import #endif #import +#import @interface RCTAppDelegate () @end @@ -210,6 +211,10 @@ - (Class)getModuleClassFromName:(const char *)name return std::make_shared(jsInvoker); } + if (name == facebook::react::NativeMicrotasks::kModuleName) { + return std::make_shared(jsInvoker); + } + return nullptr; } diff --git a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec index 4ddc800c2d7d21..24b7368cb7159c 100644 --- a/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec +++ b/packages/react-native/Libraries/AppDelegate/React-RCTAppDelegate.podspec @@ -78,6 +78,7 @@ Pod::Spec.new do |s| s.dependency "React-nativeconfig" s.dependency "ReactCodegen" s.dependency "React-featureflagsnativemodule" + s.dependency "React-microtasksnativemodule" add_dependency(s, "ReactCommon", :subspec => "turbomodule/core", :additional_framework_paths => ["react/nativemodule/core"]) add_dependency(s, "React-NativeModulesApple") diff --git a/packages/react-native/Libraries/Core/setUpTimers.js b/packages/react-native/Libraries/Core/setUpTimers.js index 86d73869f5ef9c..db0ac5dc1e7cf3 100644 --- a/packages/react-native/Libraries/Core/setUpTimers.js +++ b/packages/react-native/Libraries/Core/setUpTimers.js @@ -10,7 +10,9 @@ 'use strict'; -const {isNativeFunction} = require('../Utilities/FeatureDetection'); +const ReactNativeFeatureFlags = require('../../src/private/featureflags/ReactNativeFeatureFlags'); +const NativeReactNativeFeatureFlags = + require('../../src/private/featureflags/specs/NativeReactNativeFeatureFlags').default; const {polyfillGlobal} = require('../Utilities/PolyfillFunctions'); if (__DEV__) { @@ -19,14 +21,6 @@ if (__DEV__) { } } -// Currently, Hermes `Promise` is implemented via Internal Bytecode. -const hasHermesPromiseQueuedToJSVM = - global.HermesInternal?.hasPromise?.() === true && - global.HermesInternal?.useEngineQueue?.() === true; - -const hasNativePromise = isNativeFunction(Promise); -const hasPromiseQueuedToJSVM = hasNativePromise || hasHermesPromiseQueuedToJSVM; - // In bridgeless mode, timers are host functions installed from cpp. if (global.RN$Bridgeless !== true) { /** @@ -56,13 +50,33 @@ if (global.RN$Bridgeless !== true) { defineLazyTimer('cancelIdleCallback'); } -/** - * Set up immediate APIs, which is required to use the same microtask queue - * as the Promise. - */ -if (hasPromiseQueuedToJSVM) { - // When promise queues to the JSVM microtasks queue, we shim the immediate - // APIs via `queueMicrotask` to maintain the backward compatibility. +// We need to check if the native module is available before accessing the +// feature flag, because otherwise the API would throw an error in the legacy +// architecture in OSS, where the native module isn't available. +if ( + NativeReactNativeFeatureFlags != null && + ReactNativeFeatureFlags.enableMicrotasks() +) { + // This is the flag that tells React to use `queueMicrotask` to batch state + // updates, instead of using the scheduler to schedule a regular task. + // We use a global variable because we don't currently have any other + // mechanism to pass feature flags from RN to React in OSS. + global.RN$enableMicrotasksInReact = true; + + polyfillGlobal('queueMicrotask', () => { + const nativeQueueMicrotask = + require('../../src/private/webapis/microtasks/specs/NativeMicrotasks') + .default?.queueMicrotask; + if (nativeQueueMicrotask) { + return nativeQueueMicrotask; + } else { + // For backwards-compatibility + return global.HermesInternal?.enqueueJob; + } + }); + + // We shim the immediate APIs via `queueMicrotask` to maintain the backward + // compatibility. polyfillGlobal( 'setImmediate', () => require('./Timers/immediateShim').setImmediate, @@ -72,6 +86,12 @@ if (hasPromiseQueuedToJSVM) { () => require('./Timers/immediateShim').clearImmediate, ); } else { + // Polyfill it with promise (regardless it's polyfilled or native) otherwise. + polyfillGlobal( + 'queueMicrotask', + () => require('./Timers/queueMicrotask.js').default, + ); + // When promise was polyfilled hence is queued to the RN microtask queue, // we polyfill the immediate APIs as aliases to the ReactNativeMicrotask APIs. // Note that in bridgeless mode, immediate APIs are installed from cpp. @@ -86,18 +106,3 @@ if (hasPromiseQueuedToJSVM) { ); } } - -/** - * Set up the microtask queueing API, which is required to use the same - * microtask queue as the Promise. - */ -if (hasHermesPromiseQueuedToJSVM) { - // Fast path for Hermes. - polyfillGlobal('queueMicrotask', () => global.HermesInternal?.enqueueJob); -} else { - // Polyfill it with promise (regardless it's polyfilled or native) otherwise. - polyfillGlobal( - 'queueMicrotask', - () => require('./Timers/queueMicrotask.js').default, - ); -} diff --git a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt index 8e30da2cda6e73..af48dbd60eee8d 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/CMakeLists.txt @@ -102,6 +102,7 @@ add_react_common_subdir(react/bridging) add_react_common_subdir(react/renderer/mapbuffer) add_react_common_subdir(react/nativemodule/core) add_react_common_subdir(react/nativemodule/featureflags) +add_react_common_subdir(react/nativemodule/microtasks) add_react_common_subdir(jserrorhandler) add_react_common_subdir(react/runtime) add_react_common_subdir(react/runtime/hermes) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt index 8ecdfadb9b4253..d541aa2305c868 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/CMakeLists.txt @@ -22,4 +22,5 @@ target_link_libraries(react_newarchdefaults react_codegen_rncore react_cxxreactpackage react_nativemodule_featureflags + react_nativemodule_microtasks jsi) diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp index ce5c07bf97deca..7a291d71821556 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/newarchdefaults/DefaultTurboModuleManagerDelegate.cpp @@ -10,6 +10,7 @@ #include #include +#include #include namespace facebook::react { @@ -78,6 +79,10 @@ std::shared_ptr DefaultTurboModuleManagerDelegate::getTurboModule( return std::make_shared(jsInvoker); } + if (name == NativeMicrotasks::kModuleName) { + return std::make_shared(jsInvoker); + } + return nullptr; } diff --git a/packages/react-native/ReactCommon/react/nativemodule/microtasks/CMakeLists.txt b/packages/react-native/ReactCommon/react/nativemodule/microtasks/CMakeLists.txt new file mode 100644 index 00000000000000..80fe7fdc29ef2e --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/microtasks/CMakeLists.txt @@ -0,0 +1,24 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13) +set(CMAKE_VERBOSE_MAKEFILE on) + +add_compile_options( + -fexceptions + -frtti + -std=c++20 + -Wall + -Wpedantic + -DLOG_TAG=\"ReactNative\") + +file(GLOB react_nativemodule_microtasks_SRC CONFIGURE_DEPENDS *.cpp) +add_library(react_nativemodule_microtasks SHARED ${react_nativemodule_microtasks_SRC}) + +target_include_directories(react_nativemodule_microtasks PUBLIC ${REACT_COMMON_DIR}) + +target_link_libraries(react_nativemodule_microtasks + react_codegen_rncore + reactnative) diff --git a/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.cpp b/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.cpp new file mode 100644 index 00000000000000..25d5f2c41a5253 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "NativeMicrotasks.h" + +#ifdef RN_DISABLE_OSS_PLUGIN_HEADER +#include "Plugins.h" +#endif + +std::shared_ptr NativeMicrotasksModuleProvider( + std::shared_ptr jsInvoker) { + return std::make_shared( + std::move(jsInvoker)); +} + +namespace facebook::react { + +NativeMicrotasks::NativeMicrotasks(std::shared_ptr jsInvoker) + : NativeMicrotasksCxxSpec(std::move(jsInvoker)) {} + +void NativeMicrotasks::queueMicrotask( + jsi::Runtime& runtime, + jsi::Function callback) { + runtime.queueMicrotask(callback); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.h b/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.h new file mode 100644 index 00000000000000..2d631bb2f475b0 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/microtasks/NativeMicrotasks.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#if __has_include("rncoreJSI.h") // Cmake headers on Android +#include "rncoreJSI.h" +#elif __has_include("FBReactNativeSpecJSI.h") // CocoaPod headers on Apple +#include "FBReactNativeSpecJSI.h" +#else +#include +#endif + +namespace facebook::react { + +class NativeMicrotasks : public NativeMicrotasksCxxSpec, + std::enable_shared_from_this { + public: + NativeMicrotasks(std::shared_ptr jsInvoker); + + void queueMicrotask(jsi::Runtime& runtime, jsi::Function callback); +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec b/packages/react-native/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec new file mode 100644 index 00000000000000..20ff70d9e43624 --- /dev/null +++ b/packages/react-native/ReactCommon/react/nativemodule/microtasks/React-microtasksnativemodule.podspec @@ -0,0 +1,48 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +require "json" + +package = JSON.parse(File.read(File.join(__dir__, "..", "..", "..", "..", "package.json"))) +version = package['version'] + +source = { :git => 'https://github.com/facebook/react-native.git' } +if version == '1000.0.0' + # This is an unpublished version, use the latest commit hash of the react-native repo, which we’re presumably in. + source[:commit] = `git rev-parse HEAD`.strip if system("git rev-parse --git-dir > /dev/null 2>&1") +else + source[:tag] = "v#{version}" +end + +header_search_paths = [] + +if ENV['USE_FRAMEWORKS'] + header_search_paths << "\"$(PODS_TARGET_SRCROOT)/../../..\"" # this is needed to allow the microtasks module access its own files +end + +Pod::Spec.new do |s| + s.name = "React-microtasksnativemodule" + s.version = version + s.summary = "React Native microtasks native module" + s.homepage = "https://reactnative.dev/" + s.license = package["license"] + s.author = "Meta Platforms, Inc. and its affiliates" + s.platforms = min_supported_versions + s.source = source + s.source_files = "*.{cpp,h}" + s.header_dir = "react/nativemodule/microtasks" + s.pod_target_xcconfig = { "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", + "HEADER_SEARCH_PATHS" => header_search_paths.join(' '), + "DEFINES_MODULE" => "YES" } + + if ENV['USE_FRAMEWORKS'] + s.module_name = "React_microtasksnativemodule" + s.header_mappings_dir = "../.." + end + + install_modules_dependencies(s) + + s.dependency "ReactCommon/turbomodule/core" +end diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index 6c13f048bfeec5..e60920404de575 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -126,6 +126,7 @@ def use_react_native! ( pod 'React-utils', :path => "#{prefix}/ReactCommon/react/utils" pod 'React-featureflags', :path => "#{prefix}/ReactCommon/react/featureflags" pod 'React-featureflagsnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/featureflags" + pod 'React-microtasksnativemodule', :path => "#{prefix}/ReactCommon/react/nativemodule/microtasks" pod 'React-Mapbuffer', :path => "#{prefix}/ReactCommon" pod 'React-jserrorhandler', :path => "#{prefix}/ReactCommon/jserrorhandler" pod 'React-nativeconfig', :path => "#{prefix}/ReactCommon" diff --git a/packages/react-native/src/private/webapis/microtasks/specs/NativeMicrotasks.js b/packages/react-native/src/private/webapis/microtasks/specs/NativeMicrotasks.js new file mode 100644 index 00000000000000..5fa44e54803d0d --- /dev/null +++ b/packages/react-native/src/private/webapis/microtasks/specs/NativeMicrotasks.js @@ -0,0 +1,19 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +import type {TurboModule} from '../../../../../Libraries/TurboModule/RCTExport'; + +import * as TurboModuleRegistry from '../../../../../Libraries/TurboModule/TurboModuleRegistry'; + +export interface Spec extends TurboModule { + +queueMicrotask: (callback: () => mixed) => void; +} + +export default (TurboModuleRegistry.get('NativeMicrotasksCxx'): ?Spec); From 3f41fb5d5b5dfd6d69b00e104f9eb05b98671fa6 Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Tue, 12 Mar 2024 09:58:51 -0700 Subject: [PATCH 166/361] feature(dev-middleware): add custom message handlers to extend CDP capabilities (#43291) Summary: This is a proposal for the `react-native/dev-middleware` package, to allow implementers to extend the CDP capabilities of the `InspectorProxy`. It's unfortunately needed until we can move to the native Hermes CDP layer. At Expo, we extend the CDP capabilities of this `InspectorProxy` by injecting functionality on the device level. This proposed API does the same, but without having to overwrite internal functions of both the `InspectorProxy` and `InspectorDevice`. A good example of this is the network inspector's capabilities. This currently works through the inspection proxy, and roughly like: - Handle any incoming `Expo(Network.receivedResponseBody)` from the _**device**_, store it, and stop event from propagating - Handle the incoming `Network.getResponseBody` from the _**debugger**_, return the data, and stop event from propagating. This API brings back that capability in a more structured way. ## API: ```ts import { createDevMiddleware } from 'react-native/dev-middleware'; const { middleware, websocketEndpoints } = createDevMiddleware({ unstable_customInspectorMessageHandler: ({ page, deviceInfo, debuggerInfo }) => { // Do not enable handler for page other than "SOMETHING", or for vscode debugging // Can also include `page.capabilities` to determine if handler is required if (page.title !== 'SOMETHING' || debuggerInfo.userAgent?.includes('vscode')) { return null; } return { handleDeviceMessage(message) { if (message.type === 'CDP_MESSAGE') { // Do something and stop message from propagating with return `true` return true; } }, handleDebuggerMessage(message) { if (message.type === 'CDP_MESSAGE') { // Do something and stop message from propagating with return `true` return true; } }, }; }, }); ``` ## Changelog: [GENERAL] [ADDED] - Add inspector proxy device message middleware API Pull Request resolved: https://github.com/facebook/react-native/pull/43291 Test Plan: See added tests and code above Reviewed By: huntie Differential Revision: D54804503 Pulled By: motiz88 fbshipit-source-id: ae918dcd5b7e76d3fb31db4c84717567ae60fa96 --- ...InspectorProxyCustomMessageHandler-test.js | 310 ++++++++++++++++++ .../dev-middleware/src/createDevMiddleware.js | 12 +- packages/dev-middleware/src/index.flow.js | 8 +- .../inspector-proxy/CustomMessageHandler.js | 54 +++ .../src/inspector-proxy/Device.js | 89 ++++- .../src/inspector-proxy/InspectorProxy.js | 7 + 6 files changed, 466 insertions(+), 14 deletions(-) create mode 100644 packages/dev-middleware/src/__tests__/InspectorProxyCustomMessageHandler-test.js create mode 100644 packages/dev-middleware/src/inspector-proxy/CustomMessageHandler.js diff --git a/packages/dev-middleware/src/__tests__/InspectorProxyCustomMessageHandler-test.js b/packages/dev-middleware/src/__tests__/InspectorProxyCustomMessageHandler-test.js new file mode 100644 index 00000000000000..5f3f8b7798d875 --- /dev/null +++ b/packages/dev-middleware/src/__tests__/InspectorProxyCustomMessageHandler-test.js @@ -0,0 +1,310 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import {createAndConnectTarget} from './InspectorProtocolUtils'; +import {withAbortSignalForEachTest} from './ResourceUtils'; +import {baseUrlForServer, createServer} from './ServerUtils'; +import until from 'wait-for-expect'; + +// WebSocket is unreliable when using fake timers. +jest.useRealTimers(); + +jest.setTimeout(10000); + +describe('inspector proxy device message middleware', () => { + const autoCleanup = withAbortSignalForEachTest(); + const page = { + id: 'page1', + app: 'bar-app', + title: 'bar-title', + vm: 'bar-vm', + }; + + afterEach(() => { + jest.clearAllMocks(); + }); + + test('middleware is created with device, debugger, and page information', async () => { + const createCustomMessageHandler = jest.fn().mockImplementation(() => null); + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: createCustomMessageHandler, + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Ensure the middleware was created with the device information + await until(() => + expect(createCustomMessageHandler).toBeCalledWith( + expect.objectContaining({ + page: expect.objectContaining({ + ...page, + capabilities: expect.any(Object), + }), + device: expect.objectContaining({ + appId: expect.any(String), + id: expect.any(String), + name: expect.any(String), + sendMessage: expect.any(Function), + }), + debugger: expect.objectContaining({ + userAgent: null, + sendMessage: expect.any(Function), + }), + }), + ), + ); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); + + test('send message functions are passing messages to sockets', async () => { + const handleDebuggerMessage = jest.fn(); + const handleDeviceMessage = jest.fn(); + const createCustomMessageHandler = jest.fn().mockImplementation(() => ({ + handleDebuggerMessage, + handleDeviceMessage, + })); + + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: createCustomMessageHandler, + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Ensure the middleware was created with the send message methods + await until(() => + expect(createCustomMessageHandler).toBeCalledWith( + expect.objectContaining({ + device: expect.objectContaining({ + sendMessage: expect.any(Function), + }), + debugger: expect.objectContaining({ + sendMessage: expect.any(Function), + }), + }), + ), + ); + + // Send a message to the device + createCustomMessageHandler.mock.calls[0][0].device.sendMessage({ + id: 1, + }); + // Ensure the device received the message + await until(() => + expect(device.wrappedEvent).toBeCalledWith({ + event: 'wrappedEvent', + payload: { + pageId: page.id, + wrappedEvent: JSON.stringify({id: 1}), + }, + }), + ); + + // Send a message to the debugger + createCustomMessageHandler.mock.calls[0][0].debugger.sendMessage({ + id: 2, + }); + // Ensure the debugger received the message + await until(() => + expect(debugger_.handle).toBeCalledWith({ + id: 2, + }), + ); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); + + test('device message is passed to message middleware', async () => { + const handleDeviceMessage = jest.fn(); + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: () => ({ + handleDeviceMessage, + handleDebuggerMessage() {}, + }), + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Send a message from the device, and ensure the middleware received it + device.sendWrappedEvent(page.id, {id: 1337}); + + // Ensure the debugger received the message + await until(() => expect(debugger_.handle).toBeCalledWith({id: 1337})); + // Ensure the middleware received the message + await until(() => expect(handleDeviceMessage).toBeCalled()); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); + + test('device message stops propagating when handled by middleware', async () => { + const handleDeviceMessage = jest.fn(); + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: () => ({ + handleDeviceMessage, + handleDebuggerMessage() {}, + }), + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Stop the first message from propagating by returning true (once) from middleware + handleDeviceMessage.mockReturnValueOnce(true); + + // Send the first message which should NOT be received by the debugger + device.sendWrappedEvent(page.id, {id: -1}); + await until(() => expect(handleDeviceMessage).toBeCalled()); + + // Send the second message which should be received by the debugger + device.sendWrappedEvent(page.id, {id: 1337}); + + // Ensure only the last message was received by the debugger + await until(() => expect(debugger_.handle).toBeCalledWith({id: 1337})); + // Ensure the first message was not received by the debugger + expect(debugger_.handle).not.toBeCalledWith({id: -1}); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); + + test('debugger message is passed to message middleware', async () => { + const handleDebuggerMessage = jest.fn(); + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: () => ({ + handleDeviceMessage() {}, + handleDebuggerMessage, + }), + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Send a message from the debugger + const message = { + method: 'Runtime.enable', + id: 1337, + }; + debugger_.send(message); + + // Ensure the device received the message + await until(() => expect(device.wrappedEvent).toBeCalled()); + // Ensure the middleware received the message + await until(() => expect(handleDebuggerMessage).toBeCalledWith(message)); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); + + test('debugger message stops propagating when handled by middleware', async () => { + const handleDebuggerMessage = jest.fn(); + const {server} = await createServer({ + logger: undefined, + projectRoot: '', + unstable_customInspectorMessageHandler: () => ({ + handleDeviceMessage() {}, + handleDebuggerMessage, + }), + }); + + let device, debugger_; + try { + ({device, debugger_} = await createAndConnectTarget( + serverRefUrls(server), + autoCleanup.signal, + page, + )); + + // Stop the first message from propagating by returning true (once) from middleware + handleDebuggerMessage.mockReturnValueOnce(true); + + // Send the first emssage which should not be received by the device + debugger_.send({id: -1}); + // Send the second message which should be received by the device + debugger_.send({id: 1337}); + + // Ensure only the last message was received by the device + await until(() => + expect(device.wrappedEvent).toBeCalledWith({ + event: 'wrappedEvent', + payload: {pageId: page.id, wrappedEvent: JSON.stringify({id: 1337})}, + }), + ); + // Ensure the first message was not received by the device + expect(device.wrappedEvent).not.toBeCalledWith({id: -1}); + } finally { + device?.close(); + debugger_?.close(); + await closeServer(server); + } + }); +}); + +function serverRefUrls(server: http$Server | https$Server) { + return { + serverBaseUrl: baseUrlForServer(server, 'http'), + serverBaseWsUrl: baseUrlForServer(server, 'ws'), + }; +} + +async function closeServer(server: http$Server | https$Server): Promise { + return new Promise(resolve => server.close(() => resolve())); +} diff --git a/packages/dev-middleware/src/createDevMiddleware.js b/packages/dev-middleware/src/createDevMiddleware.js index e6c9dc1f7d93e2..8766811b8885ba 100644 --- a/packages/dev-middleware/src/createDevMiddleware.js +++ b/packages/dev-middleware/src/createDevMiddleware.js @@ -9,6 +9,7 @@ * @oncall react_native */ +import type {CreateCustomMessageHandlerFn} from './inspector-proxy/CustomMessageHandler'; import type {BrowserLauncher} from './types/BrowserLauncher'; import type {EventReporter} from './types/EventReporter'; import type {Experiments, ExperimentsConfig} from './types/Experiments'; @@ -61,11 +62,12 @@ type Options = $ReadOnly<{ unstable_experiments?: ExperimentsConfig, /** - * An interface for using a modified inspector proxy implementation. + * Create custom handler to add support for unsupported CDP events, or debuggers. + * This handler is instantiated per logical device and debugger pair. * * This is an unstable API with no semver guarantees. */ - unstable_InspectorProxy?: Class, + unstable_customInspectorMessageHandler?: CreateCustomMessageHandlerFn, }>; type DevMiddlewareAPI = $ReadOnly<{ @@ -80,16 +82,16 @@ export default function createDevMiddleware({ unstable_browserLauncher = DefaultBrowserLauncher, unstable_eventReporter, unstable_experiments: experimentConfig = {}, - unstable_InspectorProxy, + unstable_customInspectorMessageHandler, }: Options): DevMiddlewareAPI { const experiments = getExperiments(experimentConfig); - const InspectorProxyClass = unstable_InspectorProxy ?? InspectorProxy; - const inspectorProxy = new InspectorProxyClass( + const inspectorProxy = new InspectorProxy( projectRoot, serverBaseUrl, unstable_eventReporter, experiments, + unstable_customInspectorMessageHandler, ); const middleware = connect() diff --git a/packages/dev-middleware/src/index.flow.js b/packages/dev-middleware/src/index.flow.js index c662838fea10ce..7afbbdbd8894b3 100644 --- a/packages/dev-middleware/src/index.flow.js +++ b/packages/dev-middleware/src/index.flow.js @@ -13,6 +13,8 @@ export {default as createDevMiddleware} from './createDevMiddleware'; export type {BrowserLauncher, LaunchedBrowser} from './types/BrowserLauncher'; export type {EventReporter, ReportableEvent} from './types/EventReporter'; - -export {default as unstable_InspectorProxy} from './inspector-proxy/InspectorProxy'; -export {default as unstable_Device} from './inspector-proxy/Device'; +export type { + CustomMessageHandler, + CustomMessageHandlerConnection, + CreateCustomMessageHandlerFn, +} from './inspector-proxy/CustomMessageHandler'; diff --git a/packages/dev-middleware/src/inspector-proxy/CustomMessageHandler.js b/packages/dev-middleware/src/inspector-proxy/CustomMessageHandler.js new file mode 100644 index 00000000000000..1c3dd473b7c118 --- /dev/null +++ b/packages/dev-middleware/src/inspector-proxy/CustomMessageHandler.js @@ -0,0 +1,54 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + */ + +import type {JSONSerializable, Page} from './types'; + +type ExposedDevice = $ReadOnly<{ + appId: string, + id: string, + name: string, + sendMessage: (message: JSONSerializable) => void, +}>; + +type ExposedDebugger = $ReadOnly<{ + userAgent: string | null, + sendMessage: (message: JSONSerializable) => void, +}>; + +export type CustomMessageHandlerConnection = $ReadOnly<{ + page: Page, + device: ExposedDevice, + debugger: ExposedDebugger, +}>; + +export type CreateCustomMessageHandlerFn = ( + connection: CustomMessageHandlerConnection, +) => ?CustomMessageHandler; + +/** + * The device message middleware allows implementers to handle unsupported CDP messages. + * It is instantiated per device and may contain state that is specific to that device. + * The middleware can also mark messages from the device or debugger as handled, which stops propagating. + */ +export interface CustomMessageHandler { + /** + * Handle a CDP message coming from the device. + * This is invoked before the message is sent to the debugger. + * When returning true, the message is considered handled and will not be sent to the debugger. + */ + handleDeviceMessage(message: JSONSerializable): true | void; + + /** + * Handle a CDP message coming from the debugger. + * This is invoked before the message is sent to the device. + * When returning true, the message is considered handled and will not be sent to the device. + */ + handleDebuggerMessage(message: JSONSerializable): true | void; +} diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 455a89fd09f051..a7c4450c593da3 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -16,6 +16,10 @@ import type { CDPResponse, CDPServerMessage, } from './cdp-types/messages'; +import type { + CreateCustomMessageHandlerFn, + CustomMessageHandler, +} from './CustomMessageHandler'; import type { MessageFromDevice, MessageToDevice, @@ -51,6 +55,11 @@ type DebuggerInfo = { userAgent: string | null, }; +type DebuggerConnection = { + ...DebuggerInfo, + customHandler: ?CustomMessageHandler, +}; + const REACT_NATIVE_RELOADABLE_PAGE_ID = '-1'; /** @@ -74,7 +83,7 @@ export default class Device { #pages: $ReadOnlyMap; // Stores information about currently connected debugger (if any). - #debuggerConnection: ?DebuggerInfo = null; + #debuggerConnection: ?DebuggerConnection = null; // Last known Page ID of the React Native page. // This is used by debugger connections that don't have PageID specified @@ -97,6 +106,9 @@ export default class Device { #pagesPollingIntervalId: ReturnType; + // The device message middleware factory function allowing implementers to handle unsupported CDP messages. + #createCustomMessageHandler: ?CreateCustomMessageHandlerFn; + constructor( id: string, name: string, @@ -104,6 +116,7 @@ export default class Device { socket: WS, projectRoot: string, eventReporter: ?EventReporter, + createMessageMiddleware: ?CreateCustomMessageHandlerFn, ) { this.#id = id; this.#name = name; @@ -118,6 +131,7 @@ export default class Device { appId: app, }) : null; + this.#createCustomMessageHandler = createMessageMiddleware; // $FlowFixMe[incompatible-call] this.#deviceSocket.on('message', (message: string) => { @@ -205,6 +219,7 @@ export default class Device { prependedFilePrefix: false, pageId, userAgent: metadata.userAgent, + customHandler: null, }; // TODO(moti): Handle null case explicitly, e.g. refuse to connect to @@ -215,6 +230,50 @@ export default class Device { debug(`Got new debugger connection for page ${pageId} of ${this.#name}`); + if (page && this.#debuggerConnection && this.#createCustomMessageHandler) { + this.#debuggerConnection.customHandler = this.#createCustomMessageHandler( + { + page, + debugger: { + userAgent: debuggerInfo.userAgent, + sendMessage: message => { + try { + const payload = JSON.stringify(message); + debug('(Debugger) <- (Proxy) (Device): ' + payload); + socket.send(payload); + } catch {} + }, + }, + device: { + appId: this.#app, + id: this.#id, + name: this.#name, + sendMessage: message => { + try { + const payload = JSON.stringify({ + event: 'wrappedEvent', + payload: { + pageId: this.#mapToDevicePageId(pageId), + wrappedEvent: JSON.stringify(message), + }, + }); + debug('(Debugger) -> (Proxy) (Device): ' + payload); + this.#deviceSocket.send(payload); + } catch {} + }, + }, + }, + ); + + if (this.#debuggerConnection.customHandler) { + debug('Created new custom message handler for debugger connection'); + } else { + debug( + 'Skipping new custom message handler for debugger connection, factory function returned null', + ); + } + } + this.#sendMessageToDevice({ event: 'connect', payload: { @@ -231,6 +290,15 @@ export default class Device { frontendUserAgent: metadata.userAgent, }); let processedReq = debuggerRequest; + + if ( + this.#debuggerConnection?.customHandler?.handleDebuggerMessage( + debuggerRequest, + ) === true + ) { + return; + } + if (!page || !this.#pageHasCapability(page, 'nativeSourceCodeFetching')) { processedReq = this.#interceptClientMessageForSourceFetching( debuggerRequest, @@ -411,12 +479,21 @@ export default class Device { }); } - if (this.#debuggerConnection != null) { + const debuggerConnection = this.#debuggerConnection; + if (debuggerConnection != null) { + if ( + debuggerConnection.customHandler?.handleDeviceMessage( + parsedPayload, + ) === true + ) { + return; + } + // Wrapping just to make flow happy :) // $FlowFixMe[unused-promise] this.#processMessageFromDeviceLegacy( parsedPayload, - this.#debuggerConnection, + debuggerConnection, pageId, ).then(() => { const messageToSend = JSON.stringify(parsedPayload); @@ -499,7 +576,7 @@ export default class Device { // Allows to make changes in incoming message from device. async #processMessageFromDeviceLegacy( payload: CDPServerMessage, - debuggerInfo: DebuggerInfo, + debuggerInfo: DebuggerConnection, pageId: ?string, ) { // TODO(moti): Handle null case explicitly, or ideally associate a copy @@ -616,7 +693,7 @@ export default class Device { */ #interceptClientMessageForSourceFetching( req: CDPClientMessage, - debuggerInfo: DebuggerInfo, + debuggerInfo: DebuggerConnection, socket: WS, ): CDPClientMessage | null { switch (req.method) { @@ -633,7 +710,7 @@ export default class Device { #processDebuggerSetBreakpointByUrl( req: CDPRequest<'Debugger.setBreakpointByUrl'>, - debuggerInfo: DebuggerInfo, + debuggerInfo: DebuggerConnection, ): CDPRequest<'Debugger.setBreakpointByUrl'> { // If we replaced Android emulator's address to localhost we need to change it back. if (debuggerInfo.originalSourceURLAddress != null) { diff --git a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js index 532bf06c0b457c..9b9916dc220d98 100644 --- a/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js +++ b/packages/dev-middleware/src/inspector-proxy/InspectorProxy.js @@ -11,6 +11,7 @@ import type {EventReporter} from '../types/EventReporter'; import type {Experiments} from '../types/Experiments'; +import type {CreateCustomMessageHandlerFn} from './CustomMessageHandler'; import type { JsonPagesListResponse, JsonVersionResponse, @@ -58,17 +59,22 @@ export default class InspectorProxy implements InspectorProxyQueries { #experiments: Experiments; + // custom message handler factory allowing implementers to handle unsupported CDP messages. + #customMessageHandler: ?CreateCustomMessageHandlerFn; + constructor( projectRoot: string, serverBaseUrl: string, eventReporter: ?EventReporter, experiments: Experiments, + customMessageHandler: ?CreateCustomMessageHandlerFn, ) { this.#projectRoot = projectRoot; this.#serverBaseUrl = serverBaseUrl; this.#devices = new Map(); this.#eventReporter = eventReporter; this.#experiments = experiments; + this.#customMessageHandler = customMessageHandler; } getPageDescriptions(): Array { @@ -204,6 +210,7 @@ export default class InspectorProxy implements InspectorProxyQueries { socket, this.#projectRoot, this.#eventReporter, + this.#customMessageHandler, ); if (oldDevice) { From 00d8f497ea637a50a410aafe40c3d28f16f2f634 Mon Sep 17 00:00:00 2001 From: Rob Hogan Date: Tue, 12 Mar 2024 10:04:40 -0700 Subject: [PATCH 167/361] Re-enable stale execution context test under new Hermes CDP Agent (#43444) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43444 Re-enable a test now that D54649943 added correct handling of stale execution context IDs. NOTE: There's a minor difference in returned error code. The test now allows either, though note that the old implementation is more consistent with Chrome itself which returns -32000 (server error). Semantically -32600 (invalid request) seems more appropriate. Changelog: [Internal] Reviewed By: huntie Differential Revision: D54805777 fbshipit-source-id: eb2baadf6b35319f5331462425eaa38b4edfab28 --- .../tests/JsiIntegrationTest.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index ce89fed224565c..4501770b9ac95f 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -494,11 +494,7 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpression) { })"); } -// TODO(T181299386): Restore stale execution context validation under -// HermesRuntimeAgentDelegateNew -TYPED_TEST( - JsiIntegrationHermesLegacyTest, - EvaluateExpressionInExecutionContext) { +TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { this->connect(); InSequence s; @@ -546,8 +542,14 @@ TYPED_TEST( this->reload(); // Now the old execution context is stale. - this->expectMessageFromPage( - JsonParsed(AllOf(AtJsonPtr("/id", 3), AtJsonPtr("/error/code", -32000)))); + this->expectMessageFromPage(JsonParsed(AllOf( + AtJsonPtr("/id", 3), + AtJsonPtr( + "/error/code", + // HermesRuntimeAgentDelegateNew responds more correctly with -32600 + // (invalid request), old responds -32000 (server error). Accept + // either. + AnyOf(-32600, -32000))))); this->toPage_->sendMessage(sformat( R"({{ "id": 3, From 92540a618d336c747c0ebdfffdd1a2a0a82e636d Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 12 Mar 2024 10:19:56 -0700 Subject: [PATCH 168/361] do not synchronise native animated in paper Summary: ## Changelog: [General][Fixed] - Fix broken native animation in Paper In Native Animated Paper, `scheduleUpdate` must not be called. In Fabric, the synchronisation between Fiber and Shadow trees is a must but in Paper it sets undesired state. Reviewed By: javache Differential Revision: D54799237 fbshipit-source-id: f6b07dc377111ed2f8253ea0c7c7e312168166e8 --- .../Libraries/Animated/useAnimatedProps.js | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/packages/react-native/Libraries/Animated/useAnimatedProps.js b/packages/react-native/Libraries/Animated/useAnimatedProps.js index 51196426ec2234..7350b0951e7bb8 100644 --- a/packages/react-native/Libraries/Animated/useAnimatedProps.js +++ b/packages/react-native/Libraries/Animated/useAnimatedProps.js @@ -74,34 +74,45 @@ export default function useAnimatedProps( // every animation frame. When using the native driver, this callback is // called when the animation completes. onUpdateRef.current = () => { - if (node.__isNative || process.env.NODE_ENV === 'test') { - // Check 1: either tests are running or this is a native driven animation. - // In native driven animations, this callback is only called once the animation completes. - // Call `scheduleUpdate` to synchronise Fiber and Shadow tree. + if (process.env.NODE_ENV === 'test') { + // Check 1: this is a test. + // call `scheduleUpdate` to bypass use of setNativeProps. return scheduleUpdate(); } + const isFabricNode = isFabricInstance(instance); + if (node.__isNative) { + // Check 2: this is an animation driven by native. + // In native driven animations, this callback is only called once the animation completes. + if (isFabricNode) { + // Call `scheduleUpdate` to synchronise Fiber and Shadow tree. + // Must not be called in Paper. + scheduleUpdate(); + } + return; + } + if ( typeof instance !== 'object' || typeof instance?.setNativeProps !== 'function' ) { - // Check 2: the instance does not support setNativeProps. Call `scheduleUpdate`. + // Check 3: the instance does not support setNativeProps. Call `scheduleUpdate`. return scheduleUpdate(); } - if (!isFabricInstance(instance)) { - // Check 3: this is a paper instance, call setNativeProps. + if (!isFabricNode) { + // Check 4: this is a paper instance, call setNativeProps. // $FlowIgnore[not-a-function] - Assume it's still a function. // $FlowFixMe[incompatible-use] return instance.setNativeProps(node.__getAnimatedValue()); } if (!useNativePropsInFabric) { - // Check 4: setNativeProps are disabled. + // Check 5: setNativeProps are disabled. return scheduleUpdate(); } - // This is a Fabric instance and setNativeProps are supported. + // This is a Fabric instance and setNativeProps is supported. // $FlowIgnore[not-a-function] - Assume it's still a function. // $FlowFixMe[incompatible-use] From 3341ab7cc0ba7a8460069cd39ff3060154d96e1a Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Tue, 12 Mar 2024 11:08:43 -0700 Subject: [PATCH 169/361] Fix bug where absolute nodes were not insetted correctly in certain cases (#43417) Summary: X-link: https://github.com/facebook/yoga/pull/1593 Pull Request resolved: https://github.com/facebook/react-native/pull/43417 There was a bug where we did not position absolute nodes correctly if the static node had a different main/cross axis from the containing node. This fixes that. The change is somewhat complicated unfortunately but I tried to add sufficient comments to explain what is happening Reviewed By: NickGerleman Differential Revision: D54703955 fbshipit-source-id: 096c643f61d4f9bb3ee6278d675ebd69b57350d7 --- .../yoga/yoga/algorithm/AbsoluteLayout.cpp | 104 +++++++++++------- .../yoga/yoga/algorithm/CalculateLayout.cpp | 39 ++++--- 2 files changed, 83 insertions(+), 60 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp index ccec8f187623ea..32a13c9d430664 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/AbsoluteLayout.cpp @@ -480,14 +480,10 @@ void layoutAbsoluteDescendants( LayoutData& layoutMarkerData, uint32_t currentDepth, uint32_t generationCount, - float currentNodeMainOffsetFromContainingBlock, - float currentNodeCrossOffsetFromContainingBlock, + float currentNodeLeftOffsetFromContainingBlock, + float currentNodeTopOffsetFromContainingBlock, float containingNodeAvailableInnerWidth, float containingNodeAvailableInnerHeight) { - const FlexDirection mainAxis = resolveDirection( - currentNode->style().flexDirection(), currentNodeDirection); - const FlexDirection crossAxis = - resolveCrossDirection(mainAxis, currentNodeDirection); for (auto child : currentNode->getChildren()) { if (child->style().display() == Display::None) { continue; @@ -516,45 +512,73 @@ void layoutAbsoluteDescendants( currentDepth, generationCount); - const bool isMainAxisRow = isRow(mainAxis); - const bool mainInsetsDefined = isMainAxisRow - ? child->style().horizontalInsetsDefined() - : child->style().verticalInsetsDefined(); - const bool crossInsetsDefined = isMainAxisRow - ? child->style().verticalInsetsDefined() - : child->style().horizontalInsetsDefined(); - - const float childMainOffsetFromParent = mainInsetsDefined - ? (child->getLayout().position(flexStartEdge(mainAxis)) - - currentNodeMainOffsetFromContainingBlock) - : child->getLayout().position(flexStartEdge(mainAxis)); - const float childCrossOffsetFromParent = crossInsetsDefined - ? (child->getLayout().position(flexStartEdge(crossAxis)) - - currentNodeCrossOffsetFromContainingBlock) - : child->getLayout().position(flexStartEdge(crossAxis)); - - child->setLayoutPosition( - childMainOffsetFromParent, flexStartEdge(mainAxis)); - child->setLayoutPosition( - childCrossOffsetFromParent, flexStartEdge(crossAxis)); - - if (needsTrailingPosition(mainAxis)) { - setChildTrailingPosition(currentNode, child, mainAxis); + /* + * At this point the child has its position set but only on its the + * parent's flexStart edge. Additionally, this position should be + * interpreted relative to the containing block of the child if it had + * insets defined. So we need to adjust the position by subtracting the + * the parents offset from the containing block. However, getting that + * offset is complicated since the two nodes can have different main/cross + * axes. + */ + const FlexDirection parentMainAxis = resolveDirection( + currentNode->style().flexDirection(), currentNodeDirection); + const FlexDirection parentCrossAxis = + resolveCrossDirection(parentMainAxis, currentNodeDirection); + + if (needsTrailingPosition(parentMainAxis)) { + const bool mainInsetsDefined = isRow(parentMainAxis) + ? child->style().horizontalInsetsDefined() + : child->style().verticalInsetsDefined(); + setChildTrailingPosition( + mainInsetsDefined ? containingNode : currentNode, + child, + parentMainAxis); } - if (needsTrailingPosition(crossAxis)) { - setChildTrailingPosition(currentNode, child, crossAxis); + if (needsTrailingPosition(parentCrossAxis)) { + const bool crossInsetsDefined = isRow(parentCrossAxis) + ? child->style().horizontalInsetsDefined() + : child->style().verticalInsetsDefined(); + setChildTrailingPosition( + crossInsetsDefined ? containingNode : currentNode, + child, + parentCrossAxis); } + + /* + * At this point we know the left and top physical edges of the child are + * set with positions that are relative to the containing block if insets + * are defined + */ + const float childLeftPosition = + child->getLayout().position(PhysicalEdge::Left); + const float childTopPosition = + child->getLayout().position(PhysicalEdge::Top); + + const float childLeftOffsetFromParent = + child->style().horizontalInsetsDefined() + ? (childLeftPosition - currentNodeLeftOffsetFromContainingBlock) + : childLeftPosition; + const float childTopOffsetFromParent = + child->style().verticalInsetsDefined() + ? (childTopPosition - currentNodeTopOffsetFromContainingBlock) + : childTopPosition; + + child->setLayoutPosition(childLeftOffsetFromParent, PhysicalEdge::Left); + child->setLayoutPosition(childTopOffsetFromParent, PhysicalEdge::Top); } else if ( child->style().positionType() == PositionType::Static && !child->alwaysFormsContainingBlock()) { const Direction childDirection = child->resolveDirection(currentNodeDirection); - const float childMainOffsetFromContainingBlock = - currentNodeMainOffsetFromContainingBlock + - child->getLayout().position(flexStartEdge(mainAxis)); - const float childCrossOffsetFromContainingBlock = - currentNodeCrossOffsetFromContainingBlock + - child->getLayout().position(flexStartEdge(crossAxis)); + // By now all descendants of the containing block that are not absolute + // will have their positions set for left and top. + const float childLeftOffsetFromContainingBlock = + currentNodeLeftOffsetFromContainingBlock + + child->getLayout().position(PhysicalEdge::Left); + const float childTopOffsetFromContainingBlock = + currentNodeTopOffsetFromContainingBlock + + child->getLayout().position(PhysicalEdge::Top); layoutAbsoluteDescendants( containingNode, @@ -564,8 +588,8 @@ void layoutAbsoluteDescendants( layoutMarkerData, currentDepth + 1, generationCount, - childMainOffsetFromContainingBlock, - childCrossOffsetFromContainingBlock, + childLeftOffsetFromContainingBlock, + childTopOffsetFromContainingBlock, containingNodeAvailableInnerWidth, containingNodeAvailableInnerHeight); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index c6fb81e703450c..abec51f58181a6 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -2040,26 +2040,7 @@ static void calculateLayoutImpl( } if (performLayout) { - // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN - // Let the containing block layout its absolute descendants. By definition - // the containing block will not be static unless we are at the root. - if (node->style().positionType() != PositionType::Static || - node->alwaysFormsContainingBlock() || depth == 1) { - layoutAbsoluteDescendants( - node, - node, - isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, - direction, - layoutMarkerData, - depth, - generationCount, - 0.0f, - 0.0f, - availableInnerWidth, - availableInnerHeight); - } - - // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN + // STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN const bool needsMainTrailingPos = needsTrailingPosition(mainAxis); const bool needsCrossTrailingPos = needsTrailingPosition(crossAxis); @@ -2082,6 +2063,24 @@ static void calculateLayoutImpl( } } } + + // STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN + // Let the containing block layout its absolute descendants. + if (node->style().positionType() != PositionType::Static || + node->alwaysFormsContainingBlock() || depth == 1) { + layoutAbsoluteDescendants( + node, + node, + isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, + direction, + layoutMarkerData, + depth, + generationCount, + 0.0f, + 0.0f, + availableInnerWidth, + availableInnerHeight); + } } } From 9af98ccd71e7329e3188f1c8fb2a48eed19afaeb Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Tue, 12 Mar 2024 11:17:40 -0700 Subject: [PATCH 170/361] Prevent OSS build breakage due to unused-local-typedef (#43449) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43449 Error: ``` react-native/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp:162:5: error: unused typedef 'INVALID_REQUESTED_LOG_SEVERITY' [-Werror,-Wunused-local-typedef] LOG_EVERY_N(INFO, 10) << "instanceHandle is null, event of type " << type ^ react-native/packages/react-native/ReactAndroid/build/third-party-ndk/glog/exported/glog/logging.h:943:30: note: expanded from macro 'LOG_EVERY_N' INVALID_REQUESTED_LOG_SEVERITY); \ ^ 1 error generated. ninja: build stopped: subcommand failed. ``` This has been fixed upstream (https://github.com/google/glog/commit/8b3023f7e4ca46e0ecf5f660dd7340c79139bc34) but we're on an older glog version, so ignore the error. Changelog: [Internal] Reviewed By: fabriziocucci Differential Revision: D54811655 fbshipit-source-id: a00c23528d457ae365b0a27e680bb46afabb152f --- .../ReactCommon/react/renderer/uimanager/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt index 8f0aafeb80288a..badeb64afcfdf0 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/CMakeLists.txt @@ -12,6 +12,7 @@ add_compile_options( -std=c++20 -Wall -Wpedantic + -Wno-unused-local-typedef -DLOG_TAG=\"Fabric\") file(GLOB react_render_uimanager_SRC CONFIGURE_DEPENDS *.cpp) From 7b40c8ee5fc4073cdf83060cf81e16fa282899ee Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Tue, 12 Mar 2024 11:52:52 -0700 Subject: [PATCH 171/361] Support onWindowFocusChange in Bridgeless (#43398) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43398 Implement onWindowFocusChange in Bridgeless by adding it to the ReactHostImpl Changelog: [Android][Breaking] Implement onWindowFocusChange in Bridgeless Reviewed By: javache Differential Revision: D54670119 fbshipit-source-id: 71f560e5a3bf0e853ac06955e67b8035f1ec0468 --- .../ReactAndroid/api/ReactAndroid.api | 3 +++ .../facebook/react/ReactActivityDelegate.java | 8 +------- .../java/com/facebook/react/ReactDelegate.java | 10 ++++++++++ .../main/java/com/facebook/react/ReactHost.kt | 3 +++ .../facebook/react/runtime/ReactHostImpl.java | 17 +++++++++++++++++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 9bb3145b68f208..774ca78dc3c2ed 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -153,6 +153,7 @@ public class com/facebook/react/ReactDelegate { public fun onHostDestroy ()V public fun onHostPause ()V public fun onHostResume ()V + public fun onWindowFocusChanged (Z)V public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z } @@ -203,6 +204,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun onHostPause (Landroid/app/Activity;)V public abstract fun onHostResume (Landroid/app/Activity;)V public abstract fun onHostResume (Landroid/app/Activity;Lcom/facebook/react/modules/core/DefaultHardwareBackBtnHandler;)V + public abstract fun onWindowFocusChange (Z)V public abstract fun reload (Ljava/lang/String;)Lcom/facebook/react/interfaces/TaskInterface; public abstract fun removeBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V public abstract fun setJsEngineResolutionAlgorithm (Lcom/facebook/react/JSEngineResolutionAlgorithm;)V @@ -3641,6 +3643,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React public fun onHostPause (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;Lcom/facebook/react/modules/core/DefaultHardwareBackBtnHandler;)V + public fun onWindowFocusChange (Z)V public fun reload (Ljava/lang/String;)Lcom/facebook/react/interfaces/TaskInterface; public fun removeBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V public fun removeReactInstanceEventListener (Lcom/facebook/react/ReactInstanceEventListener;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 229f2d9f630d4c..ca95a2615060f3 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -195,13 +195,7 @@ public boolean onNewIntent(Intent intent) { } public void onWindowFocusChanged(boolean hasFocus) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: support onWindowFocusChanged - } else { - if (getReactNativeHost().hasInstance()) { - getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus); - } - } + mReactDelegate.onWindowFocusChanged(hasFocus); } public void onConfigurationChanged(Configuration newConfig) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 7b83e71d5d8c64..bb0cb136e30994 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -148,6 +148,16 @@ public void onActivityResult( } } + public void onWindowFocusChanged(boolean hasFocus) { + if (ReactFeatureFlags.enableBridgelessArchitecture) { + mReactHost.onWindowFocusChange(hasFocus); + } else { + if (getReactNativeHost().hasInstance()) { + getReactNativeHost().getReactInstanceManager().onWindowFocusChange(hasFocus); + } + } + } + public void loadApp() { loadApp(mMainComponentName); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index 69c9821b004a27..1183e792138518 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -120,6 +120,9 @@ public interface ReactHost { data: Intent?, ) + /* To be called when focus has changed for the hosting window. */ + public fun onWindowFocusChange(hasFocus: Boolean) + public fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit) public fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index c7d852d38507d5..4ca0483914dc49 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -650,6 +650,23 @@ public void onActivityResult( "Tried to access onActivityResult while context is not ready")); } + /* To be called when focus has changed for the hosting window. */ + @ThreadConfined(UI) + @Override + public void onWindowFocusChange(boolean hasFocus) { + final String method = "onWindowFocusChange(hasFocus = \"" + hasFocus + "\")"; + log(method); + + ReactContext currentContext = getCurrentReactContext(); + if (currentContext != null) { + currentContext.onWindowFocusChange(hasFocus); + } + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException( + "Tried to access onWindowFocusChange while context is not ready")); + } + @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); From 55ed1c26ab7eda2a6ed1a7c41f3018b63fdd6a99 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 12 Mar 2024 12:08:00 -0700 Subject: [PATCH 172/361] delete EventPriority and its uses (#43437) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43437 ## Changelog: [iOS][Removed] - remove EventPriority class and always use the default EventPriority::AsynchronousBatched. This is potentially a breaking change if something in OSS sets a different priority. If a build fails because of this, simply remove the use of EventPriority. EventPriority::AsynchronousBatched is the default and none of the other priorities are used anymore. This is the first step of removing this concept from the codebase. Reviewed By: NickGerleman Differential Revision: D54684311 fbshipit-source-id: 18240e5ee84f489f43b15fd9aab43f3b1b1b4963 --- .../jni/react/fabric/EventEmitterWrapper.cpp | 1 - .../scrollview/ScrollViewEventEmitter.cpp | 12 +-- .../scrollview/ScrollViewEventEmitter.h | 3 +- .../iostextinput/TextInputEventEmitter.cpp | 33 +++----- .../iostextinput/TextInputEventEmitter.h | 6 +- .../components/view/TouchEventEmitter.cpp | 78 ++++--------------- .../components/view/TouchEventEmitter.h | 2 - .../react/renderer/core/ConcreteState.h | 17 ++-- .../react/renderer/core/EventDispatcher.cpp | 35 ++------- .../react/renderer/core/EventDispatcher.h | 11 +-- .../react/renderer/core/EventEmitter.cpp | 17 ++-- .../react/renderer/core/EventEmitter.h | 4 - .../react/renderer/core/EventPriority.h | 24 ------ .../react/renderer/core/ShadowNodeFamily.cpp | 6 +- .../react/renderer/core/ShadowNodeFamily.h | 3 +- 15 files changed, 52 insertions(+), 200 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/renderer/core/EventPriority.h diff --git a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/EventEmitterWrapper.cpp b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/EventEmitterWrapper.cpp index 9d37fa1f08cc1a..e3908c880dff71 100644 --- a/packages/react-native/ReactAndroid/src/main/jni/react/fabric/EventEmitterWrapper.cpp +++ b/packages/react-native/ReactAndroid/src/main/jni/react/fabric/EventEmitterWrapper.cpp @@ -23,7 +23,6 @@ void EventEmitterWrapper::dispatchEvent( eventEmitter->dispatchEvent( eventName, payload ? payload->consume() : folly::dynamic::object(), - EventPriority::AsynchronousBatched, static_cast(category)); } } diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.cpp index 9ea8c939900431..016c3316bb418e 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.cpp @@ -94,14 +94,10 @@ void ScrollViewEventEmitter::onMomentumScrollEnd( void ScrollViewEventEmitter::dispatchScrollViewEvent( std::string name, - const ScrollViewMetrics& scrollViewMetrics, - EventPriority priority) const { - dispatchEvent( - std::move(name), - [scrollViewMetrics](jsi::Runtime& runtime) { - return scrollViewMetricsPayload(runtime, scrollViewMetrics); - }, - priority); + const ScrollViewMetrics& scrollViewMetrics) const { + dispatchEvent(std::move(name), [scrollViewMetrics](jsi::Runtime& runtime) { + return scrollViewMetricsPayload(runtime, scrollViewMetrics); + }); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.h index 8a849db8a50935..12e271149149c0 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewEventEmitter.h @@ -38,8 +38,7 @@ class ScrollViewEventEmitter : public ViewEventEmitter { private: void dispatchScrollViewEvent( std::string name, - const ScrollViewMetrics& scrollViewMetrics, - EventPriority priority = EventPriority::AsynchronousBatched) const; + const ScrollViewMetrics& scrollViewMetrics) const; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp index 8f1bf5734add40..4b39a211fba349 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp @@ -114,12 +114,9 @@ void TextInputEventEmitter::onSubmitEditing( void TextInputEventEmitter::onKeyPress( const KeyPressMetrics& keyPressMetrics) const { - dispatchEvent( - "keyPress", - [keyPressMetrics](jsi::Runtime& runtime) { - return keyPressMetricsPayload(runtime, keyPressMetrics); - }, - EventPriority::AsynchronousBatched); + dispatchEvent("keyPress", [keyPressMetrics](jsi::Runtime& runtime) { + return keyPressMetricsPayload(runtime, keyPressMetrics); + }); } void TextInputEventEmitter::onScroll( @@ -129,26 +126,18 @@ void TextInputEventEmitter::onScroll( void TextInputEventEmitter::dispatchTextInputEvent( const std::string& name, - const TextInputMetrics& textInputMetrics, - EventPriority priority) const { - dispatchEvent( - name, - [textInputMetrics](jsi::Runtime& runtime) { - return textInputMetricsPayload(runtime, textInputMetrics); - }, - priority); + const TextInputMetrics& textInputMetrics) const { + dispatchEvent(name, [textInputMetrics](jsi::Runtime& runtime) { + return textInputMetricsPayload(runtime, textInputMetrics); + }); } void TextInputEventEmitter::dispatchTextInputContentSizeChangeEvent( const std::string& name, - const TextInputMetrics& textInputMetrics, - EventPriority priority) const { - dispatchEvent( - name, - [textInputMetrics](jsi::Runtime& runtime) { - return textInputMetricsContentSizePayload(runtime, textInputMetrics); - }, - priority); + const TextInputMetrics& textInputMetrics) const { + dispatchEvent(name, [textInputMetrics](jsi::Runtime& runtime) { + return textInputMetricsContentSizePayload(runtime, textInputMetrics); + }); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h index a4c68483c235b5..ba3e20e10584e2 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.h @@ -49,13 +49,11 @@ class TextInputEventEmitter : public ViewEventEmitter { private: void dispatchTextInputEvent( const std::string& name, - const TextInputMetrics& textInputMetrics, - EventPriority priority = EventPriority::AsynchronousBatched) const; + const TextInputMetrics& textInputMetrics) const; void dispatchTextInputContentSizeChangeEvent( const std::string& name, - const TextInputMetrics& textInputMetrics, - EventPriority priority = EventPriority::AsynchronousBatched) const; + const TextInputMetrics& textInputMetrics) const; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp index 154273a830dfa3..d147e5db54112c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp @@ -45,35 +45,25 @@ static jsi::Value touchEventPayload( void TouchEventEmitter::dispatchTouchEvent( std::string type, const TouchEvent& event, - EventPriority priority, RawEvent::Category category) const { dispatchEvent( std::move(type), [event](jsi::Runtime& runtime) { return touchEventPayload(runtime, event); }, - priority, category); } void TouchEventEmitter::dispatchPointerEvent( std::string type, const PointerEvent& event, - EventPriority priority, RawEvent::Category category) const { dispatchEvent( - std::move(type), - std::make_shared(event), - priority, - category); + std::move(type), std::make_shared(event), category); } void TouchEventEmitter::onTouchStart(const TouchEvent& event) const { - dispatchTouchEvent( - "touchStart", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + dispatchTouchEvent("touchStart", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onTouchMove(const TouchEvent& event) const { @@ -83,43 +73,25 @@ void TouchEventEmitter::onTouchMove(const TouchEvent& event) const { } void TouchEventEmitter::onTouchEnd(const TouchEvent& event) const { - dispatchTouchEvent( - "touchEnd", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + dispatchTouchEvent("touchEnd", event, RawEvent::Category::ContinuousEnd); } void TouchEventEmitter::onTouchCancel(const TouchEvent& event) const { - dispatchTouchEvent( - "touchCancel", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + dispatchTouchEvent("touchCancel", event, RawEvent::Category::ContinuousEnd); } void TouchEventEmitter::onClick(const PointerEvent& event) const { - dispatchPointerEvent( - "click", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::Discrete); + dispatchPointerEvent("click", event, RawEvent::Category::Discrete); } void TouchEventEmitter::onPointerCancel(const PointerEvent& event) const { dispatchPointerEvent( - "pointerCancel", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + "pointerCancel", event, RawEvent::Category::ContinuousEnd); } void TouchEventEmitter::onPointerDown(const PointerEvent& event) const { dispatchPointerEvent( - "pointerDown", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + "pointerDown", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onPointerMove(const PointerEvent& event) const { @@ -127,59 +99,37 @@ void TouchEventEmitter::onPointerMove(const PointerEvent& event) const { } void TouchEventEmitter::onPointerUp(const PointerEvent& event) const { - dispatchPointerEvent( - "pointerUp", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + dispatchPointerEvent("pointerUp", event, RawEvent::Category::ContinuousEnd); } void TouchEventEmitter::onPointerEnter(const PointerEvent& event) const { dispatchPointerEvent( - "pointerEnter", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + "pointerEnter", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onPointerLeave(const PointerEvent& event) const { dispatchPointerEvent( - "pointerLeave", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + "pointerLeave", event, RawEvent::Category::ContinuousEnd); } void TouchEventEmitter::onPointerOver(const PointerEvent& event) const { dispatchPointerEvent( - "pointerOver", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + "pointerOver", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onPointerOut(const PointerEvent& event) const { dispatchPointerEvent( - "pointerOut", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + "pointerOut", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onGotPointerCapture(const PointerEvent& event) const { dispatchPointerEvent( - "gotPointerCapture", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousStart); + "gotPointerCapture", event, RawEvent::Category::ContinuousStart); } void TouchEventEmitter::onLostPointerCapture(const PointerEvent& event) const { dispatchPointerEvent( - "lostPointerCapture", - event, - EventPriority::AsynchronousBatched, - RawEvent::Category::ContinuousEnd); + "lostPointerCapture", event, RawEvent::Category::ContinuousEnd); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h index 08b368c0eb552d..869e3ac34054ba 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/TouchEventEmitter.h @@ -45,12 +45,10 @@ class TouchEventEmitter : public EventEmitter { void dispatchTouchEvent( std::string type, const TouchEvent& event, - EventPriority priority, RawEvent::Category category) const; void dispatchPointerEvent( std::string type, const PointerEvent& event, - EventPriority priority, RawEvent::Category category) const; }; diff --git a/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h b/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h index 6a0ab8daf2f0b2..4755dc875c7c02 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ConcreteState.h @@ -58,16 +58,10 @@ class ConcreteState : public State { * function for cases where a new value of data does not depend on an old * value. */ - void updateState(Data&& newData, EventPriority priority) const { - updateState( - [data{std::move(newData)}](const Data& oldData) -> SharedData { - return std::make_shared(data); - }, - priority); - } - void updateState(Data&& newData) const { - updateState(std::move(newData), EventPriority::AsynchronousBatched); + updateState([data{std::move(newData)}](const Data& oldData) -> SharedData { + return std::make_shared(data); + }); } /* @@ -79,8 +73,7 @@ class ConcreteState : public State { * return `nullptr`. */ void updateState( - std::function callback, - EventPriority priority = EventPriority::AsynchronousBatched) const { + std::function callback) const { auto family = family_.lock(); if (!family) { @@ -95,7 +88,7 @@ class ConcreteState : public State { return callback(*static_cast(oldData.get())); }}; - family->dispatchRawState(std::move(stateUpdate), priority); + family->dispatchRawState(std::move(stateUpdate)); } #ifdef ANDROID diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp index e6385ae6d41403..14e675e9dc0a50 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp @@ -21,21 +21,11 @@ EventDispatcher::EventDispatcher( const EventBeat::Factory& synchonousEventBeatFactory, const EventBeat::Factory& asynchronousEventBeatFactory, const EventBeat::SharedOwnerBox& ownerBox) - : synchronousUnbatchedQueue_(std::make_unique( - eventProcessor, - synchonousEventBeatFactory(ownerBox))), - synchronousBatchedQueue_(std::make_unique( - eventProcessor, - synchonousEventBeatFactory(ownerBox))), - asynchronousUnbatchedQueue_(std::make_unique( - eventProcessor, - asynchronousEventBeatFactory(ownerBox))), - asynchronousBatchedQueue_(std::make_unique( + : asynchronousBatchedQueue_(std::make_unique( eventProcessor, asynchronousEventBeatFactory(ownerBox))) {} -void EventDispatcher::dispatchEvent(RawEvent&& rawEvent, EventPriority priority) - const { +void EventDispatcher::dispatchEvent(RawEvent&& rawEvent) const { // Allows the event listener to interrupt default event dispatch if (eventListeners_.willDispatchEvent(rawEvent)) { return; @@ -45,13 +35,11 @@ void EventDispatcher::dispatchEvent(RawEvent&& rawEvent, EventPriority priority) if (eventLogger != nullptr) { rawEvent.loggingTag = eventLogger->onEventStart(rawEvent.type); } - getEventQueue(priority).enqueueEvent(std::move(rawEvent)); + asynchronousBatchedQueue_->enqueueEvent(std::move(rawEvent)); } -void EventDispatcher::dispatchStateUpdate( - StateUpdate&& stateUpdate, - EventPriority priority) const { - getEventQueue(priority).enqueueStateUpdate(std::move(stateUpdate)); +void EventDispatcher::dispatchStateUpdate(StateUpdate&& stateUpdate) const { + asynchronousBatchedQueue_->enqueueStateUpdate(std::move(stateUpdate)); } void EventDispatcher::dispatchUniqueEvent(RawEvent&& rawEvent) const { @@ -62,19 +50,6 @@ void EventDispatcher::dispatchUniqueEvent(RawEvent&& rawEvent) const { asynchronousBatchedQueue_->enqueueUniqueEvent(std::move(rawEvent)); } -const EventQueue& EventDispatcher::getEventQueue(EventPriority priority) const { - switch (priority) { - case EventPriority::SynchronousUnbatched: - return *synchronousUnbatchedQueue_; - case EventPriority::SynchronousBatched: - return *synchronousBatchedQueue_; - case EventPriority::AsynchronousUnbatched: - return *asynchronousUnbatchedQueue_; - case EventPriority::AsynchronousBatched: - return *asynchronousBatchedQueue_; - } -} - void EventDispatcher::addListener( const std::shared_ptr& listener) const { eventListeners_.addListener(listener); diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h index 77594bfb877606..0fff56155d829f 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ class EventDispatcher { /* * Dispatches a raw event with given priority using event-delivery pipe. */ - void dispatchEvent(RawEvent&& rawEvent, EventPriority priority) const; + void dispatchEvent(RawEvent&& rawEvent) const; /* * Dispatches a raw event with asynchronous batched priority. Before the @@ -49,8 +48,7 @@ class EventDispatcher { /* * Dispatches a state update with given priority. */ - void dispatchStateUpdate(StateUpdate&& stateUpdate, EventPriority priority) - const; + void dispatchStateUpdate(StateUpdate&& stateUpdate) const; #pragma mark - Event listeners /* @@ -65,11 +63,6 @@ class EventDispatcher { const std::shared_ptr& listener) const; private: - const EventQueue& getEventQueue(EventPriority priority) const; - - std::unique_ptr synchronousUnbatchedQueue_; - std::unique_ptr synchronousBatchedQueue_; - std::unique_ptr asynchronousUnbatchedQueue_; std::unique_ptr asynchronousBatchedQueue_; mutable EventListenerContainer eventListeners_; diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp index bd9a7c0e39a21b..1b37492583777a 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.cpp @@ -58,14 +58,12 @@ EventEmitter::EventEmitter( void EventEmitter::dispatchEvent( std::string type, const folly::dynamic& payload, - EventPriority priority, RawEvent::Category category) const { dispatchEvent( std::move(type), [payload](jsi::Runtime& runtime) { return valueFromDynamic(runtime, payload); }, - priority, category); } @@ -80,19 +78,16 @@ void EventEmitter::dispatchUniqueEvent( void EventEmitter::dispatchEvent( std::string type, const ValueFactory& payloadFactory, - EventPriority priority, RawEvent::Category category) const { dispatchEvent( std::move(type), std::make_shared(payloadFactory), - priority, category); } void EventEmitter::dispatchEvent( std::string type, SharedEventPayload payload, - EventPriority priority, RawEvent::Category category) const { SystraceSection s("EventEmitter::dispatchEvent", "type", type); @@ -101,13 +96,11 @@ void EventEmitter::dispatchEvent( return; } - eventDispatcher->dispatchEvent( - RawEvent( - normalizeEventType(std::move(type)), - std::move(payload), - eventTarget_, - category), - priority); + eventDispatcher->dispatchEvent(RawEvent( + normalizeEventType(std::move(type)), + std::move(payload), + eventTarget_, + category)); } void EventEmitter::dispatchUniqueEvent( diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h index d31e30585ff101..04bb9ebe42c0d7 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventEmitter.h @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -66,19 +65,16 @@ class EventEmitter { std::string type, const ValueFactory& payloadFactory = EventEmitter::defaultPayloadFactory(), - EventPriority priority = EventPriority::AsynchronousBatched, RawEvent::Category category = RawEvent::Category::Unspecified) const; void dispatchEvent( std::string type, const folly::dynamic& payload, - EventPriority priority = EventPriority::AsynchronousBatched, RawEvent::Category category = RawEvent::Category::Unspecified) const; void dispatchEvent( std::string type, SharedEventPayload payload, - EventPriority priority = EventPriority::AsynchronousBatched, RawEvent::Category category = RawEvent::Category::Unspecified) const; void dispatchUniqueEvent(std::string type, const folly::dynamic& payload) diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventPriority.h b/packages/react-native/ReactCommon/react/renderer/core/EventPriority.h deleted file mode 100644 index bc1e9aa9b49ebc..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/core/EventPriority.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -namespace facebook::react { - -enum class EventPriority { - SynchronousUnbatched, - SynchronousBatched, - AsynchronousUnbatched, - AsynchronousBatched, - - Sync = SynchronousUnbatched, - Work = SynchronousBatched, - Interactive = AsynchronousUnbatched, - Deferred = AsynchronousBatched -}; - -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp index 0e73b0a5cf3687..0e7fbdc2ca47ab 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.cpp @@ -136,15 +136,13 @@ std::shared_ptr ShadowNodeFamily::getMostRecentStateIfObsolete( return mostRecentState_; } -void ShadowNodeFamily::dispatchRawState( - StateUpdate&& stateUpdate, - EventPriority priority) const { +void ShadowNodeFamily::dispatchRawState(StateUpdate&& stateUpdate) const { auto eventDispatcher = eventDispatcher_.lock(); if (!eventDispatcher) { return; } - eventDispatcher->dispatchStateUpdate(std::move(stateUpdate), priority); + eventDispatcher->dispatchStateUpdate(std::move(stateUpdate)); } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h index dc5dbc815317f0..92f79cfb532e2b 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h +++ b/packages/react-native/ReactCommon/react/renderer/core/ShadowNodeFamily.h @@ -96,8 +96,7 @@ class ShadowNodeFamily final { /* * Dispatches a state update with given priority. */ - void dispatchRawState(StateUpdate&& stateUpdate, EventPriority priority) - const; + void dispatchRawState(StateUpdate&& stateUpdate) const; /* * Holds currently applied native props. `nullptr` if setNativeProps API is From eef87ca59e2c14b3c18ce645b76c17ddd24593e8 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Tue, 12 Mar 2024 13:03:13 -0700 Subject: [PATCH 173/361] Implement previouslyExportedState on HermesRuntimeAgentDelegateNew (#43392) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43392 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Wires up `previouslyExportedState` with `CDPAgent`, and re-enables the `ResolveBreakpointAfterReload` integration test. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54369985 fbshipit-source-id: 5dcb4fe59b8b36b2db9f0385e8487097822e5704 --- .circleci/configurations/top_level.yml | 2 +- .github/workflows/ios-tests.yml | 2 +- .../chrome/HermesRuntimeAgentDelegateNew.cpp | 47 +++++++++++++------ .../chrome/HermesRuntimeAgentDelegateNew.h | 3 ++ .../tests/JsiIntegrationTest.cpp | 19 +++++--- 5 files changed, 51 insertions(+), 22 deletions(-) diff --git a/.circleci/configurations/top_level.yml b/.circleci/configurations/top_level.yml index 5d3281d36400a6..165b2be7969ee1 100644 --- a/.circleci/configurations/top_level.yml +++ b/.circleci/configurations/top_level.yml @@ -92,7 +92,7 @@ references: # Cocoapods - RNTester pods_cache_key: &pods_cache_key v11-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} cocoapods_cache_key: &cocoapods_cache_key v11-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock" }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/hermes/hermesversion" }} - rntester_podfile_lock_cache_key: &rntester_podfile_lock_cache_key v9-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/week_year" }}-{{ checksum "/tmp/hermes/hermesversion" }} + rntester_podfile_lock_cache_key: &rntester_podfile_lock_cache_key v10-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/week_year" }}-{{ checksum "/tmp/hermes/hermesversion" }} # Cocoapods - Template template_cocoapods_cache_key: &template_cocoapods_cache_key v6-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile.lock" }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }}-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "packages/rn-tester/Podfile.lock" }} diff --git a/.github/workflows/ios-tests.yml b/.github/workflows/ios-tests.yml index cdfe1189593db7..a8ccb3cbf49282 100644 --- a/.github/workflows/ios-tests.yml +++ b/.github/workflows/ios-tests.yml @@ -36,7 +36,7 @@ jobs: uses: actions/cache@v3 with: path: packages/rn-tester/Pods - key: v2-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }} + key: v3-${{ runner.os }}-RNTesterPods-${{ hashFiles('packages/rn-tester/Podfile.lock') }}-${{ hashFiles('packages/rn-tester/Podfile') }}-${{ hashFiles('tmp/hermes/hermesversion') }} - name: Pod Install run: | cd packages/rn-tester diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp index 2f628aef9d1540..18f3104c53accf 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp @@ -24,6 +24,25 @@ using namespace facebook::hermes; namespace facebook::react::jsinspector_modern { class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { + using HermesState = hermes::cdp::State; + + struct HermesStateWrapper : public ExportedState { + explicit HermesStateWrapper(HermesState state) : state_(std::move(state)) {} + + static HermesState unwrapDestructively(ExportedState* wrapper) { + if (!wrapper) { + return {}; + } + if (auto* typedWrapper = dynamic_cast(wrapper)) { + return std::move(typedWrapper->state_); + } + return {}; + } + + private: + HermesState state_; + }; + public: Impl( FrontendChannel frontendChannel, @@ -44,24 +63,15 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { runtimeExecutor( [&runtime, fn = std::move(fn)](auto&) { fn(runtime); }); }, - std::move(frontendChannel))) { - // TODO(T178858701): Pass previouslyExportedState to CDPAgent - (void)previouslyExportedState; - } + std::move(frontendChannel), + HermesStateWrapper::unwrapDestructively( + previouslyExportedState.get()))) {} - /** - * Handle a CDP request. The response will be sent over the provided - * \c FrontendChannel synchronously or asynchronously. - * \param req The parsed request. - * \returns true if this agent has responded, or will respond asynchronously, - * to the request (with either a success or error message). False if the - * agent expects another agent to respond to the request instead. - */ bool handleRequest(const cdp::PreparsedRequest& req) override { // TODO: Change to string::starts_with when we're on C++20. if (req.method.rfind("Log.", 0) == 0) { - // Since we know Hermes doesn't do anything useful with Log messages, but - // our containing PageAgent will, just bail out early. + // Since we know Hermes doesn't do anything useful with Log messages, + // but our containing HostAgent will, bail out early. // TODO: We need a way to negotiate this more dynamically with Hermes // through the API. return false; @@ -73,6 +83,10 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { return true; } + std::unique_ptr getExportedState() override { + return std::make_unique(hermes_->getState()); + } + private: std::unique_ptr hermes_; }; @@ -100,6 +114,11 @@ bool HermesRuntimeAgentDelegateNew::handleRequest( return impl_->handleRequest(req); } +std::unique_ptr +HermesRuntimeAgentDelegateNew::getExportedState() { + return impl_->getExportedState(); +} + } // namespace facebook::react::jsinspector_modern #endif // HERMES_ENABLE_DEBUGGER diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h index 3a8e959b23fc39..674bc8d049cbe3 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.h @@ -66,6 +66,9 @@ class HermesRuntimeAgentDelegateNew : public RuntimeAgentDelegate { */ bool handleRequest(const cdp::PreparsedRequest& req) override; + std::unique_ptr getExportedState() + override; + private: class Impl; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index 4501770b9ac95f..6aea1c35a0b5c3 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -559,16 +559,23 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { std::to_string(executionContextId))); } -// TODO(T178858701): Restore breakpoint reload persistence under -// HermesRuntimeAgentDelegateNew -TYPED_TEST(JsiIntegrationHermesLegacyTest, ResolveBreakpointAfterReload) { +TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { this->connect(); InSequence s; - this->expectMessageFromPage(JsonParsed(AtJsonPtr("/id", 1))); + this->expectMessageFromPage(JsonEq(R"({ + "id": 1, + "result": {} + })")); this->toPage_->sendMessage(R"({ "id": 1, + "method": "Debugger.enable" + })"); + + this->expectMessageFromPage(JsonParsed(AtJsonPtr("/id", 2))); + this->toPage_->sendMessage(R"({ + "id": 2, "method": "Debugger.setBreakpointByUrl", "params": {"lineNumber": 2, "url": "breakpointTest.js"} })"); @@ -576,11 +583,11 @@ TYPED_TEST(JsiIntegrationHermesLegacyTest, ResolveBreakpointAfterReload) { this->reload(); this->expectMessageFromPage(JsonEq(R"({ - "id": 2, + "id": 3, "result": {} })")); this->toPage_->sendMessage(R"({ - "id": 2, + "id": 3, "method": "Debugger.enable" })"); From 41b63719409f373a4b4f0cfc1de7d3ff95c74fd4 Mon Sep 17 00:00:00 2001 From: Fabrizio Cucci Date: Tue, 12 Mar 2024 13:18:25 -0700 Subject: [PATCH 174/361] Synchronize access to LongLivedObjectCollection instances (#43450) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43450 Changelog: [Internal] This is just to make sure that all instances of `LongLivedObjectCollection` map can be safely accessed by multiple threads. Reviewed By: RSNara Differential Revision: D54801015 fbshipit-source-id: e0b15bfbeac9ce3a1051f83a59c5513a90ba2a4b --- .../ReactCommon/react/bridging/LongLivedObject.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp index 64a93c1b7ec508..9c6d7c38d86fb2 100644 --- a/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp +++ b/packages/react-native/ReactCommon/react/bridging/LongLivedObject.cpp @@ -16,6 +16,9 @@ LongLivedObjectCollection& LongLivedObjectCollection::get( jsi::Runtime& runtime) { static std::unordered_map> instances; + static std::mutex instancesMutex; + + std::scoped_lock lock(instancesMutex); void* key = static_cast(&runtime); auto entry = instances.find(key); if (entry == instances.end()) { From 255d1cebf2a3a7270b30510d8da3907c079e0d93 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 12 Mar 2024 15:05:51 -0700 Subject: [PATCH 175/361] delete passthroughAnimatedPropExplicitValues from animated component (#43407) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43407 changelog: [internal] `passthroughAnimatedPropExplicitValues` is not used. Let's remove it. Reviewed By: yungsters Differential Revision: D54583470 fbshipit-source-id: 9e480e4bf3216d4d6c9d7eac99a6b4d5a2e9583f --- .../Animated/createAnimatedComponent.js | 23 +++---------------- .../__snapshots__/public-api-test.js.snap | 8 +------ 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/packages/react-native/Libraries/Animated/createAnimatedComponent.js b/packages/react-native/Libraries/Animated/createAnimatedComponent.js index 78b66e094812d2..90878ca81bd6db 100644 --- a/packages/react-native/Libraries/Animated/createAnimatedComponent.js +++ b/packages/react-native/Libraries/Animated/createAnimatedComponent.js @@ -8,19 +8,12 @@ * @format */ -import View from '../Components/View/View'; import useMergeRefs from '../Utilities/useMergeRefs'; import useAnimatedProps from './useAnimatedProps'; import * as React from 'react'; // $FlowFixMe[deprecated-type] -export type AnimatedProps = $ObjMap< - Props & - $ReadOnly<{ - passthroughAnimatedPropExplicitValues?: React.ElementConfig, - }>, - () => any, ->; +export type AnimatedProps = $ObjMap any>; export type AnimatedComponentType< Props: {...}, @@ -43,19 +36,9 @@ export default function createAnimatedComponent( // transformed and Pressable, onPress will not work after transform // without these passthrough values. // $FlowFixMe[prop-missing] - const {passthroughAnimatedPropExplicitValues, style} = reducedProps; - const {style: passthroughStyle, ...passthroughProps} = - passthroughAnimatedPropExplicitValues ?? {}; - const mergedStyle = {...style, ...passthroughStyle}; + const {style} = reducedProps; - return ( - - ); + return ; }, ); diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index ab7be2f1001e90..290704597d70e4 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -810,13 +810,7 @@ exports[`public API should not change unintentionally Libraries/Animated/compone `; exports[`public API should not change unintentionally Libraries/Animated/createAnimatedComponent.js 1`] = ` -"export type AnimatedProps = $ObjMap< - Props & - $ReadOnly<{ - passthroughAnimatedPropExplicitValues?: React.ElementConfig, - }>, - () => any, ->; +"export type AnimatedProps = $ObjMap any>; export type AnimatedComponentType< Props: { ... }, +Instance = mixed, From 3bbe193ab1aff73f26c0a7b449b0813fb5011c1d Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Tue, 12 Mar 2024 15:24:50 -0700 Subject: [PATCH 176/361] Add missing dependency from AndroidTextInput (#43448) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43448 ## Changelog: [Internal] - This adds a stub for `TextLayoutManager.measureCachedSpannableById`, as well as a missing explicit dependency to `jni/react/jni` from the `TextInput` implementation on the Android platform. This is required in order for certain build configurations to compile. Reviewed By: andrewdacenko Differential Revision: D54807518 fbshipit-source-id: 206f0edb03a4ed328a962e57d1e791614eb7f851 --- .../textlayoutmanager/platform/cxx/TextLayoutManager.cpp | 7 +++++++ .../textlayoutmanager/platform/cxx/TextLayoutManager.h | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp index 6d99a35008fca5..b3e49dfed3a8aa 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp @@ -29,6 +29,13 @@ TextMeasurement TextLayoutManager::measure( return TextMeasurement{{0, 0}, attachments}; } +TextMeasurement TextLayoutManager::measureCachedSpannableById( + int64_t /*cacheId*/, + const ParagraphAttributes& /*paragraphAttributes*/, + LayoutConstraints /*layoutConstraints*/) const { + return {}; +} + LinesMeasurements TextLayoutManager::measureLines( AttributedString attributedString, ParagraphAttributes paragraphAttributes, diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h index 63903786a91b3d..0d323241190fc6 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h @@ -42,6 +42,15 @@ class TextLayoutManager { LayoutConstraints layoutConstraints, std::shared_ptr) const; + /** + * Measures an AttributedString on the platform, as identified by some + * opaque cache ID. + */ + virtual TextMeasurement measureCachedSpannableById( + int64_t cacheId, + const ParagraphAttributes& paragraphAttributes, + LayoutConstraints layoutConstraints) const; + /* * Measures lines of `attributedString` using native text rendering * infrastructure. From d2c5db59cd988aa258dc3f9a2b535da18484926d Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 12 Mar 2024 16:45:36 -0700 Subject: [PATCH 177/361] Identify Hermes CDPAgent/CDPHandler via log message (#43442) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43442 Changelog: [Internal] TSIA Reviewed By: huntie Differential Revision: D54630591 fbshipit-source-id: ef3c9f871a5c7150b1b890b6afb0f07bb77968fd --- .../chrome/HermesRuntimeAgentDelegate.cpp | 49 ++++++++++++++++- .../chrome/HermesRuntimeAgentDelegateNew.cpp | 52 +++++++++++++++++-- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp index 2641d55c009830..f3ba43500dd58f 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegate.cpp @@ -13,9 +13,13 @@ #include #include +#include #include +#include + using namespace facebook::hermes; +using namespace std::chrono; namespace facebook::react::jsinspector_modern { @@ -124,11 +128,15 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate { .origin = executionContextDescription.origin, .name = executionContextDescription.name, .auxData = std::nullopt, - .shouldSendNotifications = false})) { + .shouldSendNotifications = false})), + frontendChannel_(std::move(frontendChannel)) { + if (sessionState.isLogDomainEnabled) { + sendHermesIntegrationDescription(); + } hermes_->registerCallbacks( /* msgCallback */ [frontendChannel = - std::move(frontendChannel)](const std::string& messageFromHermes) { + frontendChannel_](const std::string& messageFromHermes) { frontendChannel(messageFromHermes); ; }, @@ -145,6 +153,13 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate { * agent expects another agent to respond to the request instead. */ bool handleRequest(const cdp::PreparsedRequest& req) override { + if (req.method == "Log.enable") { + sendHermesIntegrationDescription(); + + // The parent Agent should send a response. + return false; + } + // TODO: Change to string::starts_with when we're on C++20. if (req.method.rfind("Log.", 0) == 0) { // Since we know Hermes doesn't do anything useful with Log messages, but @@ -165,7 +180,37 @@ class HermesRuntimeAgentDelegate::Impl final : public RuntimeAgentDelegate { } private: + /** + * Send a user-facing message describing the current Hermes integration. You + * must ensure that the frontend has enabled Log notifications (using + * Log.enable) prior to calling this function. + */ + void sendHermesIntegrationDescription() { + sendInfoLogEntry("Hermes integration: CDPHandler"); + } + + /** + * Send a simple Log.entryAdded notification with the given + * \param text. You must ensure that the frontend has enabled Log + * notifications (using Log.enable) prior to calling this function. In Chrome + * DevTools, the message will appear in the Console tab along with regular + * console messages. + */ + void sendInfoLogEntry(std::string_view text) { + frontendChannel_(cdp::jsonNotification( + "Log.entryAdded", + folly::dynamic::object( + "entry", + folly::dynamic::object( + "timestamp", + duration_cast( + system_clock::now().time_since_epoch()) + .count())("source", "other")( + "level", "info")("text", text)))); + } + std::shared_ptr hermes_; + FrontendChannel frontendChannel_; }; HermesRuntimeAgentDelegate::HermesRuntimeAgentDelegate( diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp index 18f3104c53accf..1ca7fdd2001499 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp @@ -17,9 +17,13 @@ #include #include +#include #include +#include + using namespace facebook::hermes; +using namespace std::chrono; namespace facebook::react::jsinspector_modern { @@ -46,7 +50,7 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { public: Impl( FrontendChannel frontendChannel, - SessionState& /*unused*/, + SessionState& sessionState, std::unique_ptr previouslyExportedState, const ExecutionContextDescription& executionContextDescription, @@ -63,11 +67,23 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { runtimeExecutor( [&runtime, fn = std::move(fn)](auto&) { fn(runtime); }); }, - std::move(frontendChannel), + frontendChannel, HermesStateWrapper::unwrapDestructively( - previouslyExportedState.get()))) {} + previouslyExportedState.get()))), + frontendChannel_(frontendChannel) { + if (sessionState.isLogDomainEnabled) { + sendHermesIntegrationDescription(); + } + } bool handleRequest(const cdp::PreparsedRequest& req) override { + if (req.method == "Log.enable") { + sendHermesIntegrationDescription(); + + // The parent Agent should send a response. + return false; + } + // TODO: Change to string::starts_with when we're on C++20. if (req.method.rfind("Log.", 0) == 0) { // Since we know Hermes doesn't do anything useful with Log messages, @@ -88,7 +104,37 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { } private: + /** + * Send a user-facing message describing the current Hermes integration. You + * must ensure that the frontend has enabled Log notifications (using + * Log.enable) prior to calling this function. + */ + void sendHermesIntegrationDescription() { + sendInfoLogEntry("Hermes integration: CDPAgent"); + } + + /** + * Send a simple Log.entryAdded notification with the given + * \param text. You must ensure that the frontend has enabled Log + * notifications (using Log.enable) prior to calling this function. In Chrome + * DevTools, the message will appear in the Console tab along with regular + * console messages. + */ + void sendInfoLogEntry(std::string_view text) { + frontendChannel_(cdp::jsonNotification( + "Log.entryAdded", + folly::dynamic::object( + "entry", + folly::dynamic::object( + "timestamp", + duration_cast( + system_clock::now().time_since_epoch()) + .count())("source", "other")( + "level", "info")("text", text)))); + } + std::unique_ptr hermes_; + FrontendChannel frontendChannel_; }; HermesRuntimeAgentDelegateNew::HermesRuntimeAgentDelegateNew( From 1150f21404fa2e580af2a7ed27bc5d69f8b4979c Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Tue, 12 Mar 2024 16:45:36 -0700 Subject: [PATCH 178/361] Persist Debugger and Runtime domain state for Hermes CDPAgent (#43443) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43443 TSIA Changelog: [Internal] Reviewed By: huntie Differential Revision: D54712525 fbshipit-source-id: 34b1804088f15a2524607ebce81bceb82170feab --- .../chrome/HermesRuntimeAgentDelegateNew.cpp | 6 ++++++ .../ReactCommon/jsinspector-modern/HostAgent.cpp | 10 ++++++++++ .../ReactCommon/jsinspector-modern/SessionState.h | 1 + 3 files changed, 17 insertions(+) diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp index 1ca7fdd2001499..79139846bc1d87 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeAgentDelegateNew.cpp @@ -74,6 +74,12 @@ class HermesRuntimeAgentDelegateNew::Impl final : public RuntimeAgentDelegate { if (sessionState.isLogDomainEnabled) { sendHermesIntegrationDescription(); } + if (sessionState.isRuntimeDomainEnabled) { + hermes_->enableRuntimeDomain(); + } + if (sessionState.isDebuggerDomainEnabled) { + hermes_->enableDebuggerDomain(); + } } bool handleRequest(const cdp::PreparsedRequest& req) override { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp index 2415586f099a07..e8171ec625e52a 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/HostAgent.cpp @@ -74,6 +74,16 @@ void HostAgent::handleRequest(const cdp::PreparsedRequest& req) { } else if (req.method == "Runtime.disable") { sessionState_.isRuntimeDomainEnabled = false; + shouldSendOKResponse = true; + isFinishedHandlingRequest = false; + } else if (req.method == "Debugger.enable") { + sessionState_.isDebuggerDomainEnabled = true; + + shouldSendOKResponse = true; + isFinishedHandlingRequest = false; + } else if (req.method == "Debugger.disable") { + sessionState_.isDebuggerDomainEnabled = false; + shouldSendOKResponse = true; isFinishedHandlingRequest = false; } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/SessionState.h b/packages/react-native/ReactCommon/jsinspector-modern/SessionState.h index a0329cc2db7b41..6a61ff5468524e 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/SessionState.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/SessionState.h @@ -20,6 +20,7 @@ namespace facebook::react::jsinspector_modern { struct SessionState { public: // TODO: Generalise this to arbitrary domains + bool isDebuggerDomainEnabled{false}; bool isLogDomainEnabled{false}; bool isRuntimeDomainEnabled{false}; From 5d711f83b5f1e8053b5b19d0a864a1d8fc27a235 Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Tue, 12 Mar 2024 19:00:35 -0700 Subject: [PATCH 179/361] Support onNewIntent in Bridgeless (#43401) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43401 Implement `onNewIntent` in Bridgeless by adding it to ReactHostImpl Changelog: [Android][Breaking] Implement `onNewIntent` in Bridgeless Reviewed By: fkgozali, RSNara Differential Revision: D54703159 fbshipit-source-id: fd8589d8131f4fa57188d493331dc68fb38c4520 --- .../ReactAndroid/api/ReactAndroid.api | 3 ++ .../facebook/react/ReactActivityDelegate.java | 10 +----- .../com/facebook/react/ReactDelegate.java | 13 ++++++++ .../main/java/com/facebook/react/ReactHost.kt | 3 ++ .../facebook/react/runtime/ReactHostImpl.java | 32 +++++++++++++++++++ 5 files changed, 52 insertions(+), 9 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 774ca78dc3c2ed..dd22a0e67474bf 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -153,6 +153,7 @@ public class com/facebook/react/ReactDelegate { public fun onHostDestroy ()V public fun onHostPause ()V public fun onHostResume ()V + public fun onNewIntent (Landroid/content/Intent;)Z public fun onWindowFocusChanged (Z)V public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z } @@ -204,6 +205,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun onHostPause (Landroid/app/Activity;)V public abstract fun onHostResume (Landroid/app/Activity;)V public abstract fun onHostResume (Landroid/app/Activity;Lcom/facebook/react/modules/core/DefaultHardwareBackBtnHandler;)V + public abstract fun onNewIntent (Landroid/content/Intent;)V public abstract fun onWindowFocusChange (Z)V public abstract fun reload (Ljava/lang/String;)Lcom/facebook/react/interfaces/TaskInterface; public abstract fun removeBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V @@ -3643,6 +3645,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React public fun onHostPause (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;)V public fun onHostResume (Landroid/app/Activity;Lcom/facebook/react/modules/core/DefaultHardwareBackBtnHandler;)V + public fun onNewIntent (Landroid/content/Intent;)V public fun onWindowFocusChange (Z)V public fun reload (Ljava/lang/String;)Lcom/facebook/react/interfaces/TaskInterface; public fun removeBeforeDestroyListener (Lkotlin/jvm/functions/Function0;)V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index ca95a2615060f3..a54238c801447a 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -183,15 +183,7 @@ public boolean onBackPressed() { } public boolean onNewIntent(Intent intent) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: support onNewIntent - } else { - if (getReactNativeHost().hasInstance()) { - getReactNativeHost().getReactInstanceManager().onNewIntent(intent); - return true; - } - } - return false; + return mReactDelegate.onNewIntent(intent); } public void onWindowFocusChanged(boolean hasFocus) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index bb0cb136e30994..1880f66362679e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -135,6 +135,19 @@ public boolean onBackPressed() { return false; } + public boolean onNewIntent(Intent intent) { + if (ReactFeatureFlags.enableBridgelessArchitecture) { + mReactHost.onNewIntent(intent); + return true; + } else { + if (getReactNativeHost().hasInstance()) { + getReactNativeHost().getReactInstanceManager().onNewIntent(intent); + return true; + } + } + return false; + } + public void onActivityResult( int requestCode, int resultCode, Intent data, boolean shouldForwardToReactInstance) { if (ReactFeatureFlags.enableBridgelessArchitecture) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index 1183e792138518..11a7826437179f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -123,6 +123,9 @@ public interface ReactHost { /* To be called when focus has changed for the hosting window. */ public fun onWindowFocusChange(hasFocus: Boolean) + /* This method will give JS the opportunity to receive intents via Linking. */ + public fun onNewIntent(intent: Intent) + public fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit) public fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 4ca0483914dc49..bf28ed8a8fa2ea 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -16,6 +16,8 @@ import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.net.Uri; +import android.nfc.NfcAdapter; import android.os.Bundle; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -667,6 +669,36 @@ public void onWindowFocusChange(boolean hasFocus) { "Tried to access onWindowFocusChange while context is not ready")); } + /* This method will give JS the opportunity to receive intents via Linking. + * + * @param intent The incoming intent + */ + @ThreadConfined(UI) + @Override + public void onNewIntent(Intent intent) { + log("onNewIntent()"); + + ReactContext currentContext = getCurrentReactContext(); + if (currentContext != null) { + String action = intent.getAction(); + Uri uri = intent.getData(); + + if (uri != null + && (Intent.ACTION_VIEW.equals(action) + || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))) { + DeviceEventManagerModule deviceEventManagerModule = + currentContext.getNativeModule(DeviceEventManagerModule.class); + if (deviceEventManagerModule != null) { + deviceEventManagerModule.emitNewIntentReceived(uri); + } + } + currentContext.onNewIntent(getCurrentActivity(), intent); + } + ReactSoftExceptionLogger.logSoftException( + TAG, + new ReactNoCrashSoftException("Tried to access onNewIntent while context is not ready")); + } + @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); From 4f10f3069fff9090d700d9bcfbf49da1aa85f272 Mon Sep 17 00:00:00 2001 From: Alex Hunt Date: Wed, 13 Mar 2024 01:06:50 -0700 Subject: [PATCH 180/361] Update test to validate Debugger domain persistence (#43446) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43446 ## Context We are migrating to the new Hermes `CDPAgent` and `CDPDebugAPI` APIs in the modern CDP server (previously `HermesCDPHandler`). ## This diff Following D54712525, add a test case that validates `"Debugger.enable"` is persisted between reloads. This has been actioned by creating a further test group, `ModernHermesVariants`, and scoping the existing `ResolveBreakpointAfterReload` to this, with the removed second `"Debugger.enable"` message. Changelog: [Internal] Reviewed By: motiz88 Differential Revision: D54808212 fbshipit-source-id: 0775beb85a0907cca4dccbc77ec461d9515ab078 --- .../tests/JsiIntegrationTest.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index 6aea1c35a0b5c3..e9ccbe96c7c275 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -179,6 +179,8 @@ using AllHermesVariants = Types< JsiIntegrationTestHermesEngineAdapter, JsiIntegrationTestHermesWithCDPAgentEngineAdapter>; +using ModernHermesVariants = + Types; using LegacyHermesVariants = Types; TYPED_TEST_SUITE(JsiIntegrationPortableTest, AllEngines); @@ -192,7 +194,12 @@ using JsiIntegrationHermesLegacyTest = JsiIntegrationPortableTest; TYPED_TEST_SUITE(JsiIntegrationHermesLegacyTest, LegacyHermesVariants); -#pragma region JsiIntegrationPortableTest +template +using JsiIntegrationHermesModernTest = + JsiIntegrationPortableTest; +TYPED_TEST_SUITE(JsiIntegrationHermesModernTest, ModernHermesVariants); + +#pragma region AllEngines TYPED_TEST(JsiIntegrationPortableTest, ConnectWithoutCrashing) { this->connect(); @@ -472,8 +479,8 @@ TYPED_TEST(JsiIntegrationPortableTest, ExceptionDuringAddBindingIsIgnored) { EXPECT_TRUE(this->eval("globalThis.foo === 42").getBool()); } -#pragma endregion -#pragma region JsiIntegrationHermesTest +#pragma endregion // AllEngines +#pragma region AllHermesVariants TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpression) { this->connect(); @@ -559,7 +566,10 @@ TYPED_TEST(JsiIntegrationHermesTest, EvaluateExpressionInExecutionContext) { std::to_string(executionContextId))); } -TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { +#pragma endregion // AllHermesVariants +#pragma region ModernHermesVariants + +TYPED_TEST(JsiIntegrationHermesModernTest, ResolveBreakpointAfterReload) { this->connect(); InSequence s; @@ -610,6 +620,6 @@ TYPED_TEST(JsiIntegrationHermesTest, ResolveBreakpointAfterReload) { scriptInfo->value()["params"]["scriptId"]); } -#pragma endregion +#pragma endregion // ModernHermesVariants } // namespace facebook::react::jsinspector_modern From 38cbc082db92abdc00a73be0485999f406a05fe6 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Wed, 13 Mar 2024 04:43:12 -0700 Subject: [PATCH 181/361] Apply pointerEvents dispatch check in dispatchGenericMotionEvent (#43433) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43433 Changelog: [Android][Fixed] Views would still receive hover events when nested in a view with pointer-events: "none" `View` calls `dispatchGenericPointerEvent` from `dispatchGenericMotionEvent` (https://android.googlesource.com/platform/frameworks/base/+/android-4.3_r2.1/core/java/android/view/View.java#7439), so this is the better method to override. Reviewed By: markv Differential Revision: D54799820 fbshipit-source-id: 896572b86a0e9053b0138a18ced938a9dc3e60fc --- packages/react-native/ReactAndroid/api/ReactAndroid.api | 6 +++--- .../react/views/scroll/ReactHorizontalScrollView.java | 6 +++--- .../com/facebook/react/views/scroll/ReactScrollView.java | 6 +++--- .../java/com/facebook/react/views/view/ReactViewGroup.java | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index dd22a0e67474bf..3ac2275e0de738 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -6278,7 +6278,7 @@ public class com/facebook/react/views/scroll/ReactHorizontalScrollView : android public fun addFocusables (Ljava/util/ArrayList;II)V public fun arrowScroll (I)Z public fun canScrollHorizontally (I)Z - public fun dispatchGenericPointerEvent (Landroid/view/MotionEvent;)Z + public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z public fun draw (Landroid/graphics/Canvas;)V public fun executeKeyEvent (Landroid/view/KeyEvent;)Z public fun flashScrollIndicators ()V @@ -6404,7 +6404,7 @@ public class com/facebook/react/views/scroll/ReactScrollView : android/widget/Sc public fun (Landroid/content/Context;)V public fun (Landroid/content/Context;Lcom/facebook/react/views/scroll/FpsListener;)V public fun abortAnimation ()V - public fun dispatchGenericPointerEvent (Landroid/view/MotionEvent;)Z + public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z public fun draw (Landroid/graphics/Canvas;)V public fun executeKeyEvent (Landroid/view/KeyEvent;)Z public fun flashScrollIndicators ()V @@ -7567,7 +7567,7 @@ public class com/facebook/react/views/view/ReactViewGroup : android/view/ViewGro public fun addView (Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;)V protected fun addViewInLayout (Landroid/view/View;ILandroid/view/ViewGroup$LayoutParams;Z)Z protected fun dispatchDraw (Landroid/graphics/Canvas;)V - public fun dispatchGenericPointerEvent (Landroid/view/MotionEvent;)Z + public fun dispatchGenericMotionEvent (Landroid/view/MotionEvent;)Z public fun dispatchProvideStructure (Landroid/view/ViewStructure;)V protected fun dispatchSetPressed (Z)V protected fun drawChild (Landroid/graphics/Canvas;Landroid/view/View;J)Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 7dbcb788c3ac32..7e52edb5a2c7c9 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -640,13 +640,13 @@ public boolean onTouchEvent(MotionEvent ev) { } @Override - public boolean dispatchGenericPointerEvent(MotionEvent ev) { - // We do not dispatch the pointer event if its children are not supposed to receive it + public boolean dispatchGenericMotionEvent(MotionEvent ev) { + // We do not dispatch the motion event if its children are not supposed to receive it if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) { return false; } - return super.dispatchGenericPointerEvent(ev); + return super.dispatchGenericMotionEvent(ev); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 49f7326f0a2241..50fc9b0bc43c03 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -463,13 +463,13 @@ public boolean onTouchEvent(MotionEvent ev) { } @Override - public boolean dispatchGenericPointerEvent(MotionEvent ev) { - // We do not dispatch the pointer event if its children are not supposed to receive it + public boolean dispatchGenericMotionEvent(MotionEvent ev) { + // We do not dispatch the motion event if its children are not supposed to receive it if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) { return false; } - return super.dispatchGenericPointerEvent(ev); + return super.dispatchGenericMotionEvent(ev); } @Override diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index af5dea7170d488..bc5d22b34cc247 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -284,13 +284,13 @@ public boolean onTouchEvent(MotionEvent ev) { } @Override - public boolean dispatchGenericPointerEvent(MotionEvent ev) { - // We do not dispatch the pointer event if its children are not supposed to receive it + public boolean dispatchGenericMotionEvent(MotionEvent ev) { + // We do not dispatch the motion event if its children are not supposed to receive it if (!PointerEvents.canChildrenBeTouchTarget(mPointerEvents)) { return false; } - return super.dispatchGenericPointerEvent(ev); + return super.dispatchGenericMotionEvent(ev); } /** From 6c50418474603b2b7fe9478a3b79ae64333e9bd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 13 Mar 2024 08:07:32 -0700 Subject: [PATCH 182/361] Remove getIsSynchronous method from RuntimeScheduler (#43441) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43441 `RuntimeScheduler::getIsSynchronous` is currently used to check if the current task is being executed on the main thread, to avoid using the background executor. This was part of a test to dispatch events synchronously in an app using background executor. We're not running that test anymore and this method doesn't make a lot of sense in the first place (it's not checking if the current task is running on the main thread, only if the caller of the task scheduled it synchronously from whatever thread they called from), so we can remove the method. If this is necessary in the future we should create a method that actually does something useful (like `isCurrentTaskOnMainThread()`). Changelog: [internal] I consider this change not to be a breaking change because runtime scheduler wasn't an official public API, and what we want to make public doesn't include this method. Reviewed By: sammy-SC Differential Revision: D54804805 fbshipit-source-id: 54b3a6586e08bccc201df848b942fb1fcae29f30 --- .../runtimescheduler/RuntimeScheduler.cpp | 4 ---- .../runtimescheduler/RuntimeScheduler.h | 9 -------- .../RuntimeSchedulerBinding.cpp | 4 ---- .../RuntimeSchedulerBinding.h | 2 -- .../RuntimeScheduler_Legacy.cpp | 6 ----- .../RuntimeScheduler_Legacy.h | 8 ------- .../RuntimeScheduler_Modern.cpp | 8 ------- .../RuntimeScheduler_Modern.h | 10 --------- .../tests/RuntimeSchedulerTest.cpp | 4 +--- .../renderer/uimanager/UIManagerBinding.cpp | 22 +++++++++---------- 10 files changed, 11 insertions(+), 66 deletions(-) diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp index 79be477d2c240a..4f2cf5d8646d20 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.cpp @@ -58,10 +58,6 @@ bool RuntimeScheduler::getShouldYield() const noexcept { return runtimeSchedulerImpl_->getShouldYield(); } -bool RuntimeScheduler::getIsSynchronous() const noexcept { - return runtimeSchedulerImpl_->getIsSynchronous(); -} - void RuntimeScheduler::cancelTask(Task& task) noexcept { return runtimeSchedulerImpl_->cancelTask(task); } diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h index 26c2c336202df2..115bc3ec3d9930 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler.h @@ -30,7 +30,6 @@ class RuntimeSchedulerBase { RawCallback&& callback) noexcept = 0; virtual void cancelTask(Task& task) noexcept = 0; virtual bool getShouldYield() const noexcept = 0; - virtual bool getIsSynchronous() const noexcept = 0; virtual SchedulerPriority getCurrentPriorityLevel() const noexcept = 0; virtual RuntimeSchedulerTimePoint now() const noexcept = 0; virtual void callExpiredTasks(jsi::Runtime& runtime) = 0; @@ -100,14 +99,6 @@ class RuntimeScheduler final : RuntimeSchedulerBase { */ bool getShouldYield() const noexcept override; - /* - * Return value informs if the current task is executed inside synchronous - * block. - * - * Can be called from any thread. - */ - bool getIsSynchronous() const noexcept override; - /* * Returns value of currently executed task. Designed to be called from React. * diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp index 8bcb0420df9779..22312c98ca7f9a 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp @@ -61,10 +61,6 @@ RuntimeSchedulerBinding::RuntimeSchedulerBinding( std::shared_ptr runtimeScheduler) : runtimeScheduler_(std::move(runtimeScheduler)) {} -bool RuntimeSchedulerBinding::getIsSynchronous() const { - return runtimeScheduler_->getIsSynchronous(); -} - jsi::Value RuntimeSchedulerBinding::get( jsi::Runtime& runtime, const jsi::PropNameID& name) { diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h index 5058cb40252b60..ea892b043bc4b3 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.h @@ -42,8 +42,6 @@ class RuntimeSchedulerBinding : public jsi::HostObject { */ jsi::Value get(jsi::Runtime& runtime, const jsi::PropNameID& name) override; - bool getIsSynchronous() const; - private: std::shared_ptr runtimeScheduler_; }; diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp index 812eac2456d8c0..325de9f44c2700 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.cpp @@ -79,10 +79,6 @@ bool RuntimeScheduler_Legacy::getShouldYield() const noexcept { return runtimeAccessRequests_ > 0; } -bool RuntimeScheduler_Legacy::getIsSynchronous() const noexcept { - return isSynchronous_; -} - void RuntimeScheduler_Legacy::cancelTask(Task& task) noexcept { task.callback.reset(); } @@ -108,9 +104,7 @@ void RuntimeScheduler_Legacy::executeNowOnTheSameThread( "RuntimeScheduler::executeNowOnTheSameThread callback"); runtimeAccessRequests_ -= 1; - isSynchronous_ = true; callback(runtime); - isSynchronous_ = false; }); // Resume work loop if needed. In synchronous mode diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h index d4ad98d59a1f43..fc436b5d2283a6 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Legacy.h @@ -77,14 +77,6 @@ class RuntimeScheduler_Legacy final : public RuntimeSchedulerBase { */ bool getShouldYield() const noexcept override; - /* - * Return value informs if the current task is executed inside synchronous - * block. - * - * Can be called from any thread. - */ - bool getIsSynchronous() const noexcept override; - /* * Returns value of currently executed task. Designed to be called from React. * diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp index aa737c68310ed1..76011d0a272fb6 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.cpp @@ -74,10 +74,6 @@ bool RuntimeScheduler_Modern::getShouldYield() const noexcept { (!taskQueue_.empty() && taskQueue_.top() != currentTask_); } -bool RuntimeScheduler_Modern::getIsSynchronous() const noexcept { - return isSynchronous_; -} - void RuntimeScheduler_Modern::cancelTask(Task& task) noexcept { task.callback.reset(); } @@ -105,8 +101,6 @@ void RuntimeScheduler_Modern::executeNowOnTheSameThread( syncTaskRequests_--; - isSynchronous_ = true; - auto currentTime = now_(); auto priority = SchedulerPriority::ImmediatePriority; auto expirationTime = @@ -115,8 +109,6 @@ void RuntimeScheduler_Modern::executeNowOnTheSameThread( priority, std::move(callback), expirationTime); executeTask(runtime, task, currentTime); - - isSynchronous_ = false; }); bool shouldScheduleWorkLoop = false; diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h index 0759d8470bd54b..d31707f5217c96 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/RuntimeScheduler_Modern.h @@ -86,14 +86,6 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { */ bool getShouldYield() const noexcept override; - /* - * Return value informs if the current task is executed inside synchronous - * block. - * - * Can be called from any thread. - */ - bool getIsSynchronous() const noexcept override; - /* * Returns value of currently executed task. Designed to be called from React. * @@ -149,8 +141,6 @@ class RuntimeScheduler_Modern final : public RuntimeSchedulerBase { const RuntimeExecutor runtimeExecutor_; SchedulerPriority currentPriority_{SchedulerPriority::NormalPriority}; - std::atomic_bool isSynchronous_{false}; - void scheduleWorkLoop(); void startWorkLoop(jsi::Runtime& runtime, bool onlyExpired); diff --git a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp index ef98135ee47482..bff617dc5adc93 100644 --- a/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp +++ b/packages/react-native/ReactCommon/react/renderer/runtimescheduler/tests/RuntimeSchedulerTest.cpp @@ -777,11 +777,9 @@ TEST_P(RuntimeSchedulerTest, basicSameThreadExecution) { bool didRunSynchronousTask = false; std::thread t1([this, &didRunSynchronousTask]() { runtimeScheduler_->executeNowOnTheSameThread( - [this, &didRunSynchronousTask](jsi::Runtime& /*rt*/) { - EXPECT_TRUE(runtimeScheduler_->getIsSynchronous()); + [&didRunSynchronousTask](jsi::Runtime& /*rt*/) { didRunSynchronousTask = true; }); - EXPECT_FALSE(runtimeScheduler_->getIsSynchronous()); }); auto hasTask = stubQueue_->waitForTask(); diff --git a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp index b57ecc3d38f5dc..212184bc023f19 100644 --- a/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp +++ b/packages/react-native/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp @@ -500,18 +500,7 @@ jsi::Value UIManagerBinding::get( RuntimeSchedulerBinding::getBinding(runtime); auto surfaceId = surfaceIdFromValue(runtime, arguments[0]); - if (!uiManager->backgroundExecutor_ || - (runtimeSchedulerBinding && - runtimeSchedulerBinding->getIsSynchronous())) { - auto shadowNodeList = - shadowNodeListFromValue(runtime, arguments[1]); - uiManager->completeSurface( - surfaceId, - shadowNodeList, - {.enableStateReconciliation = true, - .mountSynchronously = false, - .shouldYield = nullptr}); - } else { + if (uiManager->backgroundExecutor_) { auto weakShadowNodeList = weakShadowNodeListFromValue(runtime, arguments[1]); static std::atomic_uint_fast8_t completeRootEventCounter{0}; @@ -542,6 +531,15 @@ jsi::Value UIManagerBinding::get( /* .shouldYield = */ shouldYield}); } }); + } else { + auto shadowNodeList = + shadowNodeListFromValue(runtime, arguments[1]); + uiManager->completeSurface( + surfaceId, + shadowNodeList, + {.enableStateReconciliation = true, + .mountSynchronously = false, + .shouldYield = nullptr}); } return jsi::Value::undefined(); From 71cf093aa3068a7786579962a10475ff0c3a2777 Mon Sep 17 00:00:00 2001 From: Ruslan Shestopalyuk Date: Wed, 13 Mar 2024 08:15:51 -0700 Subject: [PATCH 183/361] Factor out common parts of TextInputProps between Android/iOS (#43431) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43431 ## Changelog: [Internal] - This takes all the common props for TextInput between Android and iOS and factors them out into a single, platform independent props data structure, `BaseTextInputProps`. This way it's both easier to manage the corresponding props, but also making this easier to be used on other platforms. Reviewed By: sammy-SC Differential Revision: D54764898 fbshipit-source-id: 224b01c5a67ba5d5216cd5c482bf650a1c2453d5 --- .../ReactCommon/React-Fabric.podspec | 3 +- .../textinput/BaseTextInputProps.cpp | 179 ++++++++++++++++++ .../components/textinput/BaseTextInputProps.h | 66 +++++++ .../components/textinput/CMakeLists.txt | 5 +- .../AndroidTextInputProps.cpp | 107 +---------- .../androidtextinput/AndroidTextInputProps.h | 22 +-- .../iostextinput/TextInputProps.cpp | 78 +------- .../components/iostextinput/TextInputProps.h | 34 +--- 8 files changed, 255 insertions(+), 239 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.cpp create mode 100644 packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.h diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index 0423352e654c09..b67b999bf9c7da 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -201,7 +201,8 @@ Pod::Spec.new do |s| ss.subspec "textinput" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "react/renderer/components/textinput/platform/ios/**/*.{m,mm,cpp,h}" + sss.source_files = "react/renderer/components/textinput/**/*.{m,mm,cpp,h}" + sss.exclude_files = "react/renderer/components/textinput/platform/android" sss.header_dir = "react/renderer/components/iostextinput" end diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.cpp new file mode 100644 index 00000000000000..28dc7d87cbdad4 --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "BaseTextInputProps.h" + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace facebook::react { + +BaseTextInputProps::BaseTextInputProps( + const PropsParserContext& context, + const BaseTextInputProps& sourceProps, + const RawProps& rawProps) + : ViewProps(context, sourceProps, rawProps), + BaseTextProps(context, sourceProps, rawProps), + paragraphAttributes(convertRawProp( + context, + rawProps, + sourceProps.paragraphAttributes, + {})), + defaultValue(convertRawProp( + context, + rawProps, + "defaultValue", + sourceProps.defaultValue, + {})), + placeholder(convertRawProp( + context, + rawProps, + "placeholder", + sourceProps.placeholder, + {})), + placeholderTextColor(convertRawProp( + context, + rawProps, + "placeholderTextColor", + sourceProps.placeholderTextColor, + {})), + cursorColor(convertRawProp( + context, + rawProps, + "cursorColor", + sourceProps.cursorColor, + {})), + selectionColor(convertRawProp( + context, + rawProps, + "selectionColor", + sourceProps.selectionColor, + {})), + selectionHandleColor(convertRawProp( + context, + rawProps, + "selectionHandleColor", + sourceProps.selectionHandleColor, + {})), + underlineColorAndroid(convertRawProp( + context, + rawProps, + "underlineColorAndroid", + sourceProps.underlineColorAndroid, + {})), + maxLength(convertRawProp( + context, + rawProps, + "maxLength", + sourceProps.maxLength, + {})), + text(convertRawProp(context, rawProps, "text", sourceProps.text, {})), + mostRecentEventCount(convertRawProp( + context, + rawProps, + "mostRecentEventCount", + sourceProps.mostRecentEventCount, + {})), + autoFocus(convertRawProp( + context, + rawProps, + "autoFocus", + sourceProps.autoFocus, + {})){}; + +void BaseTextInputProps::setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value) { + ViewProps::setProp(context, hash, propName, value); + BaseTextProps::setProp(context, hash, propName, value); + + static auto defaults = BaseTextInputProps{}; + + // ParagraphAttributes has its own switch statement - to keep all + // of these fields together, and because there are some collisions between + // propnames parsed here and outside of ParagraphAttributes. For example, + // textBreakStrategy is duplicated. + // This code is also duplicated in ParagraphProps. + static auto paDefaults = ParagraphAttributes{}; + switch (hash) { + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + maximumNumberOfLines, + "numberOfLines"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + textBreakStrategy, + "textBreakStrategy"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + adjustsFontSizeToFit, + "adjustsFontSizeToFit"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + minimumFontSize, + "minimumFontSize"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + maximumFontSize, + "maximumFontSize"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + includeFontPadding, + "includeFontPadding"); + REBUILD_FIELD_SWITCH_CASE( + paDefaults, + value, + paragraphAttributes, + android_hyphenationFrequency, + "android_hyphenationFrequency"); + } + + switch (hash) { + RAW_SET_PROP_SWITCH_CASE_BASIC(underlineColorAndroid); + RAW_SET_PROP_SWITCH_CASE_BASIC(autoFocus); + RAW_SET_PROP_SWITCH_CASE_BASIC(maxLength); + RAW_SET_PROP_SWITCH_CASE_BASIC(placeholder); + RAW_SET_PROP_SWITCH_CASE_BASIC(placeholderTextColor); + RAW_SET_PROP_SWITCH_CASE_BASIC(selectionColor); + RAW_SET_PROP_SWITCH_CASE_BASIC(selectionHandleColor); + RAW_SET_PROP_SWITCH_CASE_BASIC(defaultValue); + RAW_SET_PROP_SWITCH_CASE_BASIC(cursorColor); + RAW_SET_PROP_SWITCH_CASE_BASIC(text); + RAW_SET_PROP_SWITCH_CASE_BASIC(mostRecentEventCount); + } +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.h new file mode 100644 index 00000000000000..c1a3ef1e202e5b --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/BaseTextInputProps.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace facebook::react { + +class BaseTextInputProps : public ViewProps, public BaseTextProps { + public: + BaseTextInputProps() = default; + BaseTextInputProps( + const PropsParserContext& context, + const BaseTextInputProps& sourceProps, + const RawProps& rawProps); + + void setProp( + const PropsParserContext& context, + RawPropsPropNameHash hash, + const char* propName, + const RawValue& value); + +#pragma mark - Props + + /* + * Contains all prop values that affect visual representation of the + * paragraph. + */ + ParagraphAttributes paragraphAttributes{}; + + std::string defaultValue{}; + + std::string placeholder{}; + SharedColor placeholderTextColor{}; + + /* + * Tint colors + */ + SharedColor cursorColor{}; + SharedColor selectionColor{}; + SharedColor selectionHandleColor{}; + // TODO: Rename to `tintColor` and make universal. + SharedColor underlineColorAndroid{}; + + int maxLength{}; + + /* + * "Private" (only used by TextInput.js) props + */ + std::string text{}; + int mostRecentEventCount{0}; + + bool autoFocus{false}; +}; + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt b/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt index e8d12d59df91fd..d245134fcc6572 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/CMakeLists.txt @@ -17,10 +17,7 @@ add_compile_options( file(GLOB rrc_textinput_SRC CONFIGURE_DEPENDS platform/android/react/renderer/components/androidtextinput/*.cpp) add_library(rrc_textinput STATIC ${rrc_textinput_SRC}) -target_include_directories(rrc_textinput - PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/ -) +target_include_directories(rrc_textinput PUBLIC . ${CMAKE_CURRENT_SOURCE_DIR}/platform/android/) target_link_libraries(rrc_textinput glog diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp index ea0fb6a1674e3d..38f3474ac350e1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.cpp @@ -36,8 +36,7 @@ AndroidTextInputProps::AndroidTextInputProps( const PropsParserContext &context, const AndroidTextInputProps &sourceProps, const RawProps &rawProps) - : ViewProps(context, sourceProps, rawProps), - BaseTextProps(context, sourceProps, rawProps), + : BaseTextInputProps(context, sourceProps, rawProps), autoComplete(CoreFeatures::enablePropIteratorSetter? sourceProps.autoComplete : convertRawProp( context, rawProps, @@ -60,10 +59,6 @@ AndroidTextInputProps::AndroidTextInputProps( "textBreakStrategy", sourceProps.textBreakStrategy, {})), - underlineColorAndroid(CoreFeatures::enablePropIteratorSetter? sourceProps.underlineColorAndroid : convertRawProp(context, rawProps, - "underlineColorAndroid", - sourceProps.underlineColorAndroid, - {})), inlineImageLeft(CoreFeatures::enablePropIteratorSetter? sourceProps.inlineImageLeft : convertRawProp(context, rawProps, "inlineImageLeft", sourceProps.inlineImageLeft, @@ -88,10 +83,6 @@ AndroidTextInputProps::AndroidTextInputProps( "autoCorrect", sourceProps.autoCorrect, {false})), - autoFocus(CoreFeatures::enablePropIteratorSetter? sourceProps.autoFocus : convertRawProp(context, rawProps, - "autoFocus", - sourceProps.autoFocus, - {false})), allowFontScaling(CoreFeatures::enablePropIteratorSetter? sourceProps.allowFontScaling : convertRawProp(context, rawProps, "allowFontScaling", sourceProps.allowFontScaling, @@ -110,35 +101,15 @@ AndroidTextInputProps::AndroidTextInputProps( "returnKeyType", sourceProps.returnKeyType, {})), - maxLength(CoreFeatures::enablePropIteratorSetter? sourceProps.maxLength : - convertRawProp(context, rawProps, "maxLength", sourceProps.maxLength, {0})), multiline(CoreFeatures::enablePropIteratorSetter? sourceProps.multiline : convertRawProp(context, rawProps, "multiline", sourceProps.multiline, {false})), - placeholder(CoreFeatures::enablePropIteratorSetter? sourceProps.placeholder : - convertRawProp(context, rawProps, "placeholder", sourceProps.placeholder, {})), - placeholderTextColor(CoreFeatures::enablePropIteratorSetter? sourceProps.placeholderTextColor : convertRawProp(context, rawProps, - "placeholderTextColor", - sourceProps.placeholderTextColor, - {})), secureTextEntry(CoreFeatures::enablePropIteratorSetter? sourceProps.secureTextEntry : convertRawProp(context, rawProps, "secureTextEntry", sourceProps.secureTextEntry, {false})), - selectionColor(CoreFeatures::enablePropIteratorSetter? sourceProps.selectionColor : convertRawProp(context, rawProps, - "selectionColor", - sourceProps.selectionColor, - {})), - selectionHandleColor(CoreFeatures::enablePropIteratorSetter? sourceProps.selectionHandleColor : convertRawProp(context, rawProps, - "selectionHandleColor", - sourceProps.selectionHandleColor, - {})), value(CoreFeatures::enablePropIteratorSetter? sourceProps.value : convertRawProp(context, rawProps, "value", sourceProps.value, {})), - defaultValue(CoreFeatures::enablePropIteratorSetter? sourceProps.defaultValue : convertRawProp(context, rawProps, - "defaultValue", - sourceProps.defaultValue, - {})), selectTextOnFocus(CoreFeatures::enablePropIteratorSetter? sourceProps.selectTextOnFocus : convertRawProp(context, rawProps, "selectTextOnFocus", sourceProps.selectTextOnFocus, @@ -202,15 +173,6 @@ AndroidTextInputProps::AndroidTextInputProps( "textAlignVertical", sourceProps.textAlignVertical, {})), - cursorColor(CoreFeatures::enablePropIteratorSetter? sourceProps.cursorColor : - convertRawProp(context, rawProps, "cursorColor", sourceProps.cursorColor, {})), - mostRecentEventCount(CoreFeatures::enablePropIteratorSetter? sourceProps.mostRecentEventCount : convertRawProp(context, rawProps, - "mostRecentEventCount", - sourceProps.mostRecentEventCount, - {0})), - text(CoreFeatures::enablePropIteratorSetter? sourceProps.text : convertRawProp(context, rawProps, "text", sourceProps.text, {})), - paragraphAttributes(CoreFeatures::enablePropIteratorSetter? sourceProps.paragraphAttributes : - convertRawProp(context, rawProps, sourceProps.paragraphAttributes, {})), // See AndroidTextInputComponentDescriptor for usage // TODO T63008435: can these, and this feature, be removed entirely? hasPadding(CoreFeatures::enablePropIteratorSetter? sourceProps.hasPadding : hasValue(rawProps, sourceProps.hasPadding, "padding")), @@ -252,91 +214,29 @@ void AndroidTextInputProps::setProp( // All Props structs setProp methods must always, unconditionally, // call all super::setProp methods, since multiple structs may // reuse the same values. - ViewProps::setProp(context, hash, propName, value); - BaseTextProps::setProp(context, hash, propName, value); + BaseTextInputProps::setProp(context, hash, propName, value); static auto defaults = AndroidTextInputProps{}; - // ParagraphAttributes has its own switch statement - to keep all - // of these fields together, and because there are some collisions between - // propnames parsed here and outside of ParagraphAttributes. For example, - // textBreakStrategy is duplicated. - // This code is also duplicated in ParagraphProps. - static auto paDefaults = ParagraphAttributes{}; - switch (hash) { - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - maximumNumberOfLines, - "numberOfLines"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - textBreakStrategy, - "textBreakStrategy"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - adjustsFontSizeToFit, - "adjustsFontSizeToFit"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - minimumFontSize, - "minimumFontSize"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - maximumFontSize, - "maximumFontSize"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - includeFontPadding, - "includeFontPadding"); - REBUILD_FIELD_SWITCH_CASE( - paDefaults, - value, - paragraphAttributes, - android_hyphenationFrequency, - "android_hyphenationFrequency"); - } - switch (hash) { RAW_SET_PROP_SWITCH_CASE_BASIC(autoComplete); RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyLabel); RAW_SET_PROP_SWITCH_CASE_BASIC(numberOfLines); RAW_SET_PROP_SWITCH_CASE_BASIC(disableFullscreenUI); RAW_SET_PROP_SWITCH_CASE_BASIC(textBreakStrategy); - RAW_SET_PROP_SWITCH_CASE_BASIC(underlineColorAndroid); RAW_SET_PROP_SWITCH_CASE_BASIC(inlineImageLeft); RAW_SET_PROP_SWITCH_CASE_BASIC(inlineImagePadding); RAW_SET_PROP_SWITCH_CASE_BASIC(importantForAutofill); RAW_SET_PROP_SWITCH_CASE_BASIC(showSoftInputOnFocus); RAW_SET_PROP_SWITCH_CASE_BASIC(autoCapitalize); RAW_SET_PROP_SWITCH_CASE_BASIC(autoCorrect); - RAW_SET_PROP_SWITCH_CASE_BASIC(autoFocus); RAW_SET_PROP_SWITCH_CASE_BASIC(allowFontScaling); RAW_SET_PROP_SWITCH_CASE_BASIC(maxFontSizeMultiplier); RAW_SET_PROP_SWITCH_CASE_BASIC(editable); RAW_SET_PROP_SWITCH_CASE_BASIC(keyboardType); RAW_SET_PROP_SWITCH_CASE_BASIC(returnKeyType); - RAW_SET_PROP_SWITCH_CASE_BASIC(maxLength); RAW_SET_PROP_SWITCH_CASE_BASIC(multiline); - RAW_SET_PROP_SWITCH_CASE_BASIC(placeholder); - RAW_SET_PROP_SWITCH_CASE_BASIC(placeholderTextColor); RAW_SET_PROP_SWITCH_CASE_BASIC(secureTextEntry); - RAW_SET_PROP_SWITCH_CASE_BASIC(selectionColor); - RAW_SET_PROP_SWITCH_CASE_BASIC(selectionHandleColor); - RAW_SET_PROP_SWITCH_CASE_BASIC(defaultValue); RAW_SET_PROP_SWITCH_CASE_BASIC(selectTextOnFocus); RAW_SET_PROP_SWITCH_CASE_BASIC(submitBehavior); RAW_SET_PROP_SWITCH_CASE_BASIC(caretHidden); @@ -356,9 +256,6 @@ void AndroidTextInputProps::setProp( RAW_SET_PROP_SWITCH_CASE_BASIC(fontWeight); RAW_SET_PROP_SWITCH_CASE_BASIC(fontFamily); RAW_SET_PROP_SWITCH_CASE_BASIC(textAlignVertical); - RAW_SET_PROP_SWITCH_CASE_BASIC(cursorColor); - RAW_SET_PROP_SWITCH_CASE_BASIC(mostRecentEventCount); - RAW_SET_PROP_SWITCH_CASE_BASIC(text); case CONSTEXPR_RAW_PROPS_KEY_HASH("value"): { fromRawValue(context, value, this->value, {}); diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h index 82fb75ea1028e4..28e5df5976be84 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/android/react/renderer/components/androidtextinput/AndroidTextInputProps.h @@ -12,8 +12,7 @@ #include #include -#include -#include +#include #include #include #include @@ -58,7 +57,7 @@ inline folly::dynamic toDynamic( return dynamicValue; } -class AndroidTextInputProps final : public ViewProps, public BaseTextProps { +class AndroidTextInputProps final : public BaseTextInputProps { public: AndroidTextInputProps() = default; AndroidTextInputProps( @@ -81,28 +80,20 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { int numberOfLines{0}; bool disableFullscreenUI{false}; std::string textBreakStrategy{}; - SharedColor underlineColorAndroid{}; std::string inlineImageLeft{}; int inlineImagePadding{0}; std::string importantForAutofill{}; bool showSoftInputOnFocus{false}; std::string autoCapitalize{}; bool autoCorrect{false}; - bool autoFocus{false}; bool allowFontScaling{false}; Float maxFontSizeMultiplier{0.0}; bool editable{false}; std::string keyboardType{}; std::string returnKeyType{}; - int maxLength{0}; bool multiline{false}; - std::string placeholder{}; - SharedColor placeholderTextColor{}; bool secureTextEntry{false}; - SharedColor selectionColor{}; - SharedColor selectionHandleColor{}; std::string value{}; - std::string defaultValue{}; bool selectTextOnFocus{false}; std::string submitBehavior{}; bool caretHidden{false}; @@ -122,15 +113,6 @@ class AndroidTextInputProps final : public ViewProps, public BaseTextProps { std::string fontWeight{}; std::string fontFamily{}; std::string textAlignVertical{}; - SharedColor cursorColor{}; - int mostRecentEventCount{0}; - std::string text{}; - - /* - * Contains all prop values that affect visual representation of the - * paragraph. - */ - ParagraphAttributes paragraphAttributes{}; /** * Auxiliary information to detect if these props are set or not. diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp index a825971ddbe8c8..43f5e9efa54c58 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.cpp @@ -18,75 +18,8 @@ TextInputProps::TextInputProps( const PropsParserContext& context, const TextInputProps& sourceProps, const RawProps& rawProps) - : ViewProps(context, sourceProps, rawProps), - BaseTextProps(context, sourceProps, rawProps), + : BaseTextInputProps(context, sourceProps, rawProps), traits(convertRawProp(context, rawProps, sourceProps.traits, {})), - paragraphAttributes(convertRawProp( - context, - rawProps, - sourceProps.paragraphAttributes, - {})), - defaultValue(convertRawProp( - context, - rawProps, - "defaultValue", - sourceProps.defaultValue, - {})), - placeholder(convertRawProp( - context, - rawProps, - "placeholder", - sourceProps.placeholder, - {})), - placeholderTextColor(convertRawProp( - context, - rawProps, - "placeholderTextColor", - sourceProps.placeholderTextColor, - {})), - maxLength(convertRawProp( - context, - rawProps, - "maxLength", - sourceProps.maxLength, - {})), - cursorColor(convertRawProp( - context, - rawProps, - "cursorColor", - sourceProps.cursorColor, - {})), - selectionColor(convertRawProp( - context, - rawProps, - "selectionColor", - sourceProps.selectionColor, - {})), - selectionHandleColor(convertRawProp( - context, - rawProps, - "selectionHandleColor", - sourceProps.selectionHandleColor, - {})), - underlineColorAndroid(convertRawProp( - context, - rawProps, - "underlineColorAndroid", - sourceProps.underlineColorAndroid, - {})), - text(convertRawProp(context, rawProps, "text", sourceProps.text, {})), - mostRecentEventCount(convertRawProp( - context, - rawProps, - "mostRecentEventCount", - sourceProps.mostRecentEventCount, - {})), - autoFocus(convertRawProp( - context, - rawProps, - "autoFocus", - sourceProps.autoFocus, - {})), selection(convertRawProp( context, rawProps, @@ -112,15 +45,6 @@ TextInputProps::TextInputProps( sourceProps.onChangeSync, {})){}; -void TextInputProps::setProp( - const PropsParserContext& context, - RawPropsPropNameHash hash, - const char* propName, - const RawValue& value) { - ViewProps::setProp(context, hash, propName, value); - BaseTextProps::setProp(context, hash, propName, value); -} - TextAttributes TextInputProps::getEffectiveTextAttributes( Float fontSizeMultiplier) const { auto result = TextAttributes::defaultTextAttributes(); diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h index e3db155099c78e..7c517713199bc4 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h @@ -9,20 +9,18 @@ #include #include +#include #include #include -#include -#include #include #include #include -#include #include #include namespace facebook::react { -class TextInputProps final : public ViewProps, public BaseTextProps { +class TextInputProps final : public BaseTextInputProps { public: TextInputProps() = default; TextInputProps( @@ -30,40 +28,12 @@ class TextInputProps final : public ViewProps, public BaseTextProps { const TextInputProps& sourceProps, const RawProps& rawProps); - void setProp( - const PropsParserContext& context, - RawPropsPropNameHash hash, - const char* propName, - const RawValue& value); - #pragma mark - Props - const TextInputTraits traits{}; - const ParagraphAttributes paragraphAttributes{}; - - std::string const defaultValue{}; - - std::string const placeholder{}; - const SharedColor placeholderTextColor{}; - - int maxLength{}; - - /* - * Tint colors - */ - const SharedColor cursorColor{}; - const SharedColor selectionColor{}; - const SharedColor selectionHandleColor{}; - // TODO: Rename to `tintColor` and make universal. - const SharedColor underlineColorAndroid{}; /* * "Private" (only used by TextInput.js) props */ - std::string const text{}; - const int mostRecentEventCount{0}; - - bool autoFocus{false}; std::optional selection{}; std::string const inputAccessoryViewID{}; From 16fd5f0ff73e9e991e42f48c72e23ef73918e3ca Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Wed, 13 Mar 2024 08:21:57 -0700 Subject: [PATCH 184/361] delete UnbatchedEventQueue (#43457) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43457 changelog: [internal] UnbatchedEventQueue is no longer used. Reviewed By: javache Differential Revision: D54687451 fbshipit-source-id: 28fe2aea25d7fd98bff488197959968e24244c6e --- .../react/renderer/core/EventDispatcher.cpp | 1 - .../react/renderer/core/EventDispatcher.h | 1 - .../renderer/core/UnbatchedEventQueue.cpp | 17 ------------- .../react/renderer/core/UnbatchedEventQueue.h | 25 ------------------- 4 files changed, 44 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp delete mode 100644 packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.h diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp index 14e675e9dc0a50..60fdd79c02a3fe 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp @@ -12,7 +12,6 @@ #include "BatchedEventQueue.h" #include "RawEvent.h" -#include "UnbatchedEventQueue.h" namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h index 0fff56155d829f..e9c6ac39f6624e 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h @@ -12,7 +12,6 @@ #include #include #include -#include namespace facebook::react { diff --git a/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp b/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp deleted file mode 100644 index 604122a6ce41e7..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "UnbatchedEventQueue.h" - -namespace facebook::react { - -void UnbatchedEventQueue::onEnqueue() const { - eventBeat_->request(); - eventBeat_->induce(); -} - -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.h b/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.h deleted file mode 100644 index 9b2f9fd8207fdf..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/core/UnbatchedEventQueue.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include - -namespace facebook::react { - -/* - * Event Queue that dispatches events as granular as possible without waiting - * for the next beat. - */ -class UnbatchedEventQueue final : public EventQueue { - public: - using EventQueue::EventQueue; - - void onEnqueue() const override; -}; - -} // namespace facebook::react From dceda565bdfe24275be0ad5caae7f3d8252aef92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20Norte?= Date: Wed, 13 Mar 2024 08:51:03 -0700 Subject: [PATCH 185/361] Fix RN tests in preparation for D54783723 (#43458) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43458 The React sync in D54783723 was failing because some tests were relying on `console.error` being called as `console.error('Some message')` but it was refactored as `console.error('%s..', 'Some message')`, making them fail. This fixes the tests by formatting the arguments passed to the console functions and checking against that instead. Changelog: [internal] Reviewed By: sammy-SC Differential Revision: D54849485 fbshipit-source-id: 0648263614725ea3f9c95b9f9bb13005adae46eb --- .../Libraries/Animated/__tests__/AnimatedNative-test.js | 7 +++++-- .../Lists/__tests__/VirtualizedList-test.js | 8 +++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js b/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js index d331d283029c51..67d1cf29113655 100644 --- a/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js +++ b/packages/react-native/Libraries/Animated/__tests__/AnimatedNative-test.js @@ -23,6 +23,7 @@ jest // findNodeHandle is imported from RendererProxy so mock that whole module. .setMock('../../ReactNative/RendererProxy', {findNodeHandle: () => 1}); +import {format} from 'node:util'; import * as React from 'react'; import TestRenderer from 'react-test-renderer'; @@ -295,11 +296,13 @@ describe('Native Animated', () => { useNativeDriver: true, }); + const consoleError = console.error; jest.spyOn(console, 'error').mockImplementationOnce((...args) => { - if (args[0].startsWith('The above error occurred in the')) { + const message = format(args); + if (message.includes('The above error occurred in the')) { return; } - console.errorDebug(...args); + consoleError(...args); }); expect(() => { diff --git a/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js b/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js index b40a7d885c5868..8feafd86b6486f 100644 --- a/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js +++ b/packages/virtualized-lists/Lists/__tests__/VirtualizedList-test.js @@ -11,6 +11,7 @@ 'use strict'; import VirtualizedList from '../VirtualizedList'; +import {format} from 'node:util'; import React from 'react'; import ReactTestRenderer from 'react-test-renderer'; @@ -71,11 +72,12 @@ describe('VirtualizedList', () => { it('throws if no renderItem or ListItemComponent', () => { // Silence the React error boundary warning; we expect an uncaught error. const consoleError = console.error; - jest.spyOn(console, 'error').mockImplementation(message => { - if (message.startsWith('The above error occurred in the ')) { + jest.spyOn(console, 'error').mockImplementation((...args) => { + const message = format(...args); + if (message.includes('The above error occurred in the ')) { return; } - consoleError(message); + consoleError(...args); }); const componentFactory = () => From 51e0b3a54667c8819b95ae1f2da016601d1dcca0 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 13 Mar 2024 10:27:29 -0700 Subject: [PATCH 186/361] Integrate Hermes CDPDebugAPI with RN console polyfill (#43454) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43454 Changelog: [Internal] 1. Introduces the `RuntimeTargetDelegate::addConsoleMessage` method, which is a 1:1 wrapper around the Hermes `CDPDebugAPI` [method of the same name](https://github.com/facebook/hermes/blob/33cf8cfe781aabcad6b3d39821d815fe5317f977/API/hermes/cdp/CDPDebugAPI.h#L43-L47). 2. Installs a global `__inspectorLog` function callable from JS, matching [this existing call](https://github.com/facebook/react-native/blob/4f10f3069fff9090d700d9bcfbf49da1aa85f272/packages/polyfills/console.js#L430-L437) in React Native's `console` polyfill. NOTE: We'll almost immediately replace `__inspectorLog` with a standalone native implementation of the `console` API that doesn't depend on the polyfill, but this is an easy way to validate the approach before tackling the full `console` spec, which requires some more C++ code and boilerplate. Reviewed By: huntie Differential Revision: D54494298 fbshipit-source-id: 2e04935712ff0aa31dac6c59837c47b6af6e447a --- .../chrome/HermesRuntimeTargetDelegate.cpp | 65 +++++++++++++++++ .../chrome/HermesRuntimeTargetDelegate.h | 3 + .../jsinspector-modern/ConsoleMessage.h | 53 ++++++++++++++ .../FallbackRuntimeTargetDelegate.cpp | 6 ++ .../FallbackRuntimeTargetDelegate.h | 3 + .../jsinspector-modern/RuntimeTarget.cpp | 73 +++++++++++++++++++ .../jsinspector-modern/RuntimeTarget.h | 27 +++++++ .../jsinspector-modern/tests/InspectorMocks.h | 5 ++ .../tests/ReactInstanceIntegrationTest.cpp | 15 ++-- 9 files changed, 244 insertions(+), 6 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index 9c5542b08ebe78..c73867a0fdbf91 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -73,6 +73,65 @@ class HermesRuntimeTargetDelegate::Impl final : public RuntimeTargetDelegate { std::move(runtimeExecutor))); } + void addConsoleMessage(jsi::Runtime& /*unused*/, ConsoleMessage message) + override { + using HermesConsoleMessage = facebook::hermes::cdp::ConsoleMessage; + using HermesConsoleAPIType = facebook::hermes::cdp::ConsoleAPIType; + + HermesConsoleAPIType type{}; + switch (message.type) { + case ConsoleAPIType::kLog: + type = HermesConsoleAPIType::kLog; + break; + case ConsoleAPIType::kDebug: + type = HermesConsoleAPIType::kDebug; + break; + case ConsoleAPIType::kInfo: + type = HermesConsoleAPIType::kInfo; + break; + case ConsoleAPIType::kError: + type = HermesConsoleAPIType::kError; + break; + case ConsoleAPIType::kWarning: + type = HermesConsoleAPIType::kWarning; + break; + case ConsoleAPIType::kDir: + type = HermesConsoleAPIType::kDir; + break; + case ConsoleAPIType::kDirXML: + type = HermesConsoleAPIType::kDirXML; + break; + case ConsoleAPIType::kTable: + type = HermesConsoleAPIType::kTable; + break; + case ConsoleAPIType::kTrace: + type = HermesConsoleAPIType::kTrace; + break; + case ConsoleAPIType::kStartGroup: + type = HermesConsoleAPIType::kStartGroup; + break; + case ConsoleAPIType::kStartGroupCollapsed: + type = HermesConsoleAPIType::kStartGroupCollapsed; + break; + case ConsoleAPIType::kEndGroup: + type = HermesConsoleAPIType::kEndGroup; + break; + case ConsoleAPIType::kClear: + type = HermesConsoleAPIType::kClear; + break; + case ConsoleAPIType::kAssert: + type = HermesConsoleAPIType::kAssert; + break; + case ConsoleAPIType::kTimeEnd: + type = HermesConsoleAPIType::kTimeEnd; + break; + default: + throw std::logic_error{"Unknown console message type"}; + } + cdpDebugAPI_->addConsoleMessage( + HermesConsoleMessage{message.timestamp, type, std::move(message.args)}); + } + private: HermesRuntimeTargetDelegate& delegate_; std::shared_ptr runtime_; @@ -118,6 +177,12 @@ HermesRuntimeTargetDelegate::createAgentDelegate( std::move(runtimeExecutor)); } +void HermesRuntimeTargetDelegate::addConsoleMessage( + jsi::Runtime& runtime, + ConsoleMessage message) { + impl_->addConsoleMessage(runtime, std::move(message)); +} + #ifdef HERMES_ENABLE_DEBUGGER CDPDebugAPI& HermesRuntimeTargetDelegate::getCDPDebugAPI() { return impl_->getCDPDebugAPI(); diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h index 2196568c09972c..7182a82a8c306d 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.h @@ -45,6 +45,9 @@ class HermesRuntimeTargetDelegate : public RuntimeTargetDelegate { executionContextDescription, RuntimeExecutor runtimeExecutor) override; + void addConsoleMessage(jsi::Runtime& runtime, ConsoleMessage message) + override; + private: // We use the private implementation idiom to ensure this class has the same // layout regardless of whether HERMES_ENABLE_DEBUGGER is defined. The net diff --git a/packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h b/packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h new file mode 100644 index 00000000000000..4ca5b1c665820d --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/ConsoleMessage.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include + +namespace facebook::react::jsinspector_modern { + +enum class ConsoleAPIType { + kLog, + kDebug, + kInfo, + kError, + kWarning, + kDir, + kDirXML, + kTable, + kTrace, + kStartGroup, + kStartGroupCollapsed, + kEndGroup, + kClear, + kAssert, + kTimeEnd, + kCount +}; + +struct ConsoleMessage { + double timestamp; + ConsoleAPIType type; + std::vector args; + + ConsoleMessage( + double timestamp, + ConsoleAPIType type, + std::vector args) + : timestamp(timestamp), type(type), args(std::move(args)) {} + + ConsoleMessage(const ConsoleMessage& other) = delete; + ConsoleMessage(ConsoleMessage&& other) noexcept = default; + ConsoleMessage& operator=(const ConsoleMessage& other) = delete; + ConsoleMessage& operator=(ConsoleMessage&& other) noexcept = default; + ~ConsoleMessage() = default; +}; + +} // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp index cd2cb9ab44f74e..f7d36d415f9349 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.cpp @@ -26,4 +26,10 @@ FallbackRuntimeTargetDelegate::createAgentDelegate( std::move(channel), sessionState, engineDescription_); } +void FallbackRuntimeTargetDelegate::addConsoleMessage( + jsi::Runtime& /*unused*/, + ConsoleMessage /*unused*/) { + // TODO: Best-effort printing (without RemoteObjects) +} + } // namespace facebook::react::jsinspector_modern diff --git a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h index 923a0d301ee022..fa859f0fceda64 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/FallbackRuntimeTargetDelegate.h @@ -31,6 +31,9 @@ class FallbackRuntimeTargetDelegate : public RuntimeTargetDelegate { const ExecutionContextDescription& executionContextDescription, RuntimeExecutor runtimeExecutor) override; + void addConsoleMessage(jsi::Runtime& runtime, ConsoleMessage message) + override; + private: std::string engineDescription_; }; diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp index 44397a8ae6488d..797d79de65fbba 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp @@ -21,6 +21,7 @@ std::shared_ptr RuntimeTarget::create( std::shared_ptr runtimeTarget{ new RuntimeTarget(executionContextDescription, delegate, jsExecutor)}; runtimeTarget->setExecutor(selfExecutor); + runtimeTarget->installGlobals(); return runtimeTarget; } @@ -32,6 +33,78 @@ RuntimeTarget::RuntimeTarget( delegate_(delegate), jsExecutor_(jsExecutor) {} +void RuntimeTarget::installGlobals() { + installConsoleHandler(); +} + +void RuntimeTarget::installConsoleHandler() { + jsExecutor_([selfWeak = weak_from_this(), + selfExecutor = executorFromThis()](jsi::Runtime& runtime) { + // TODO(moti): Switch from implementing __inspectorLog to directly + // installing a `console` object. + runtime.global().setProperty( + runtime, + "__inspectorLog", + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, "__inspectorLog"), + 4, + [selfWeak, selfExecutor]( + jsi::Runtime& rt, + const jsi::Value& /*thisVal*/, + const jsi::Value* args, + size_t count) { + if (count < 4) { + throw jsi::JSError( + rt, + "__inspectorLog requires at least 4 arguments: logLevel, str, args, framesToSkip"); + } + std::chrono::time_point timestamp = + std::chrono::system_clock::now(); + std::string level = args[0].asString(rt).utf8(rt); + ConsoleAPIType type = ConsoleAPIType::kLog; + if (level == "debug") { + type = ConsoleAPIType::kDebug; + } else if (level == "log") { + type = ConsoleAPIType::kLog; + } else if (level == "warning") { + type = ConsoleAPIType::kWarning; + } else if (level == "error") { + type = ConsoleAPIType::kError; + } + // NOTE: args[1] is the processed string message - ignore it. + jsi::Array argsArray = args[2].asObject(rt).asArray(rt); + std::vector argsVec; + for (size_t i = 0, length = argsArray.length(rt); i != length; + ++i) { + argsVec.emplace_back(argsArray.getValueAtIndex(rt, i)); + } + // TODO(moti): Handle framesToSkip in some way. Note that the + // runtime doesn't even capture a stack trace at the moment. + ConsoleMessage consoleMessage{ + std::chrono::duration_cast< + std::chrono::duration>( + timestamp.time_since_epoch()) + .count(), + type, + std::move(argsVec)}; + if (auto self = selfWeak.lock()) { + // Q: Why is it safe to use self->delegate_ here? + // A: Because the caller of InspectorTarget::registerRuntime + // is explicitly required to guarantee that the delegate not + // only outlives the target, but also outlives all JS code + // execution that occurs on the JS thread. + self->delegate_.addConsoleMessage( + rt, std::move(consoleMessage)); + // To ensure we never destroy `self` on the JS thread, send + // our shared_ptr back to the inspector thread. + selfExecutor([self = std::move(self)](auto&) { (void)self; }); + } + return jsi::Value::undefined(); + })); + }); +} + std::shared_ptr RuntimeTarget::createAgent( FrontendChannel channel, SessionState& sessionState) { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h index 59091730b20086..a5f42b8fa1f921 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.h @@ -9,6 +9,7 @@ #include +#include "ConsoleMessage.h" #include "ExecutionContext.h" #include "InspectorInterfaces.h" #include "RuntimeAgent.h" @@ -51,6 +52,21 @@ class RuntimeTargetDelegate { previouslyExportedState, const ExecutionContextDescription& executionContextDescription, RuntimeExecutor runtimeExecutor) = 0; + + /** + * Called when the runtime intercepts a console API call. The target delegate + * should notify the frontend (via its agent delegates) of the message, and + * perform any buffering required for logging the message later (in the + * existing and/or new sessions). + * + * \note The method is called on the JS thread, and receives a valid reference + * to the current \c jsi::Runtime. The callee MAY use its own intrinsic + * Runtime reference, if it has one, without checking it for equivalence with + * the one provided here. + */ + virtual void addConsoleMessage( + jsi::Runtime& runtime, + ConsoleMessage message) = 0; }; /** @@ -156,6 +172,17 @@ class JSINSPECTOR_EXPORT RuntimeTarget */ void installBindingHandler(const std::string& bindingName); + /** + * Installs any global values we want to expose to framework/user JavaScript + * code. + */ + void installGlobals(); + + /** + * Install the console API handler. + */ + void installConsoleHandler(); + // Necessary to allow RuntimeAgent to access RuntimeTarget's internals in a // controlled way (i.e. only RuntimeTargetController gets friend access, while // RuntimeAgent itself doesn't). diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h index 66f8d7bdf6a78d..f0b73ae9dcaf40 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/InspectorMocks.h @@ -136,6 +136,11 @@ class MockRuntimeTargetDelegate : public RuntimeTargetDelegate { const ExecutionContextDescription&, RuntimeExecutor), (override)); + MOCK_METHOD( + void, + addConsoleMessage, + (jsi::Runtime & runtime, ConsoleMessage message), + (override)); }; class MockRuntimeAgentDelegate : public RuntimeAgentDelegate { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp index 2e0f5c209b1242..b4442144f725e4 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/ReactInstanceIntegrationTest.cpp @@ -131,7 +131,11 @@ void ReactInstanceIntegrationTest::initializeRuntime(std::string_view script) { react::ReactInstance::JSRuntimeFlags flags{ .isProfiling = false, }; - instance->initializeRuntime(flags, [](jsi::Runtime&) {}); + instance->initializeRuntime(flags, [](jsi::Runtime& rt) { + // NOTE: RN's console polyfill (included in prelude.js.h) depends on the + // native logging hook being installed, even if it's a noop. + facebook::react::bindNativeLogger(rt, [](auto, auto) {}); + }); messageQueueThread->tick(); @@ -199,11 +203,10 @@ TEST_P(ReactInstanceIntegrationTestWithFlags, ConsoleLog) { InSequence s; - // Hermes console.* interception is currently explicitly disabled under the - // modern registry, and the runtime does not yet fire these events. When the - // implementation is more complete we should be able to remove this - // condition. - if (!InspectorFlags::getInstance().getEnableModernCDPRegistry()) { + // Hermes console.* interception is explicitly disabled under CDPHandler, + // but Hermes CDPAgent and the legacy RN backend should both work. + if (!InspectorFlags::getInstance().getEnableModernCDPRegistry() || + InspectorFlags::getInstance().getEnableHermesCDPAgent()) { EXPECT_CALL( getRemoteConnection(), onMessage(JsonParsed(AllOf( From 98f0893f392f33af3a6b4d20d8fcb25a4aac4a92 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Wed, 13 Mar 2024 10:34:06 -0700 Subject: [PATCH 187/361] =?UTF-8?q?Port:=20@react-native-community/cli#ios?= =?UTF-8?q?=20=E2=86=92=20@react-native/core-cli-utils#ios=20(#43288)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43288 Move react-native-community/cli build-ios into core per RFC0759. This provides: - boostrap (triggers pod install & autolinking) - build - install Changelog: [General][Added] RFC-0759 Move cli iOS build into core Reviewed By: cortinico Differential Revision: D54112211 fbshipit-source-id: 325ee1a2f2f38077559767264f3bee1e2837591a --- packages/core-cli-utils/.gitignore | 1 + packages/core-cli-utils/index.js | 2 + packages/core-cli-utils/private/apple.js | 103 +++++++++++++++++++++++ packages/core-cli-utils/private/utils.js | 26 ++++++ 4 files changed, 132 insertions(+) create mode 100644 packages/core-cli-utils/.gitignore create mode 100644 packages/core-cli-utils/private/apple.js diff --git a/packages/core-cli-utils/.gitignore b/packages/core-cli-utils/.gitignore new file mode 100644 index 00000000000000..849ddff3b7ec91 --- /dev/null +++ b/packages/core-cli-utils/.gitignore @@ -0,0 +1 @@ +dist/ diff --git a/packages/core-cli-utils/index.js b/packages/core-cli-utils/index.js index b2f8691f099daf..1e31339523c6b9 100644 --- a/packages/core-cli-utils/index.js +++ b/packages/core-cli-utils/index.js @@ -9,8 +9,10 @@ * @oncall react_native */ +import {tasks as apple} from './private/apple.js'; import {tasks as clean} from './private/clean.js'; export default { clean, + apple, }; diff --git a/packages/core-cli-utils/private/apple.js b/packages/core-cli-utils/private/apple.js new file mode 100644 index 00000000000000..badb841147f342 --- /dev/null +++ b/packages/core-cli-utils/private/apple.js @@ -0,0 +1,103 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import type {Task} from './types'; + +import {assertDependencies, isOnPath, task} from './utils'; +import execa from 'execa'; + +type AppleBuildMode = 'Debug' | 'Release'; + +type AppleBuildOptions = { + isWorkspace: boolean, + name: string, + mode: AppleBuildMode, + scheme: string, + destination?: string, // Device or Simulator or UUID +} & AppleOptions; + +type AppleBootstrapOption = { + bundleInstall: boolean, + // Enabled by default + newArchitecture: boolean, +} & AppleOptions; + +type AppleInstallApp = { + device: string, + appPath: string, +} & AppleOptions; + +type AppleOptions = {cwd: string, env?: {[key: string]: string | void, ...}}; + +type AppleBuildTasks = { + bootstrap: (options: AppleBootstrapOption) => Task[], + build: ( + options: AppleBuildOptions, + ...args: $ReadOnlyArray + ) => Task[], + ios: { + install: (options: AppleInstallApp) => Task[], + }, +}; + +export const tasks: AppleBuildTasks = { + bootstrap: (options: AppleBootstrapOption) => [ + task('Install CocoaPods dependencies', async () => { + assertDependencies( + isOnPath('pod', 'CocoaPods'), + isOnPath('bundle', "Bundler to manage Ruby's gems"), + ); + + if (options.bundleInstall) { + await execa('bundle', ['exec', 'install'], { + cwd: options.cwd, + }); + } + + return await execa('bundle', ['exec', 'pod', 'install'], { + cwd: options.cwd, + env: {RCT_NEW_ARCH_ENABLED: options.newArchitecture ? '1' : '0'}, + }); + }), + ], + + build: (options: AppleBuildOptions, ...args: $ReadOnlyArray) => [ + task('build an app artifact', () => { + assertDependencies(isOnPath('xcodebuild', 'Xcode Commandline Tools')); + const _args = [ + options.isWorkspace ? '-workspace' : '-project', + options.name, + '-scheme', + options.scheme, + ]; + if (options.destination != null) { + _args.push('-destination', options.destination); + } + _args.push(...args); + return execa('xcodebuild', _args, {cwd: options.cwd, env: options.env}); + }), + ], + + ios: { + install: (options: AppleInstallApp) => [ + task('Install the app on a simulator', () => { + assertDependencies( + isOnPath('xcrun', 'An Xcode Commandline tool: xcrun'), + ); + return execa( + 'xcrun', + ['simctl', 'install', options.device, options.appPath], + {cwd: options.cwd, env: options.env}, + ); + }), + ], + }, +}; diff --git a/packages/core-cli-utils/private/utils.js b/packages/core-cli-utils/private/utils.js index 4b80c3e962162b..eb8e455cfa6907 100644 --- a/packages/core-cli-utils/private/utils.js +++ b/packages/core-cli-utils/private/utils.js @@ -11,6 +11,7 @@ import type {Task} from './types'; +import execa from 'execa'; import os from 'os'; export function task(label: string, action: Task['action']): Task { @@ -22,3 +23,28 @@ export function task(label: string, action: Task['action']): Task { export const isWindows = os.platform() === 'win32'; export const isMacOS = os.platform() === 'darwin'; + +type PathCheckResult = { + found: boolean, + dep: string, + description: string, +}; + +export function isOnPath(dep: string, description: string): PathCheckResult { + const result = execa.sync(isWindows ? 'where' : 'which', [dep]); + return { + dep, + description, + found: result.exitCode === 0, + }; +} + +export function assertDependencies( + ...deps: $ReadOnlyArray> +) { + for (const {found, dep, description} of deps) { + if (!found) { + throw new Error(`"${dep}" not found, ${description}`); + } + } +} From e9f66d9c0c5308a75a3c7a0c34d748cdb2cd833f Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Wed, 13 Mar 2024 10:55:36 -0700 Subject: [PATCH 188/361] Properly handle RR and CMD+M in Bridgeless Mode (#43460) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43460 Currently pressing the menu button (or CMD+M) is broken on Bridgeless mode. Also pressing RR is not reloading the App. That's because some Bridgeless API haven't been reimplemented correctly on Android. I'm fixing them here. Fixes #43451 Changelog: [Android] [Fixed] - Properly handle RR and CMD+M in Bridgeless Mode Reviewed By: huntie Differential Revision: D54852959 fbshipit-source-id: 8fbbdab6818da9177e6db40e45d35258c7f5e236 --- .../com/facebook/react/ReactDelegate.java | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 1880f66362679e..7230538f312d6f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -15,6 +15,7 @@ import com.facebook.infer.annotation.Assertions; import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.DoubleTapReloadRecognizer; +import com.facebook.react.devsupport.interfaces.DevSupportManager; import com.facebook.react.interfaces.fabric.ReactSurface; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; @@ -218,22 +219,28 @@ protected ReactRootView createRootView() { * application. */ public boolean shouldShowDevMenuOrReload(int keyCode, KeyEvent event) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: Implement shouldShowDevMenuOrReload for Bridgeless - return false; + DevSupportManager devSupportManager = null; + if (ReactFeatureFlags.enableBridgelessArchitecture + && mReactHost != null + && mReactHost.getDevSupportManager() != null) { + devSupportManager = mReactHost.getDevSupportManager(); } else if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) { - if (keyCode == KeyEvent.KEYCODE_MENU) { - getReactNativeHost().getReactInstanceManager().showDevOptionsDialog(); - return true; - } - boolean didDoubleTapR = - Assertions.assertNotNull(mDoubleTapReloadRecognizer) - .didDoubleTapR(keyCode, mActivity.getCurrentFocus()); - if (didDoubleTapR) { - getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS(); - return true; - } + devSupportManager = getReactNativeHost().getReactInstanceManager().getDevSupportManager(); + } else { + return false; + } + + if (keyCode == KeyEvent.KEYCODE_MENU) { + devSupportManager.showDevOptionsDialog(); + return true; + } + boolean didDoubleTapR = + Assertions.assertNotNull(mDoubleTapReloadRecognizer) + .didDoubleTapR(keyCode, mActivity.getCurrentFocus()); + if (didDoubleTapR) { + devSupportManager.handleReloadJS(); + return true; } return false; } From 62acc29896b635c9e2d62d96c3d9533bb912b3a3 Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Wed, 13 Mar 2024 11:07:12 -0700 Subject: [PATCH 189/361] =?UTF-8?q?Port:=20@react-native-community/cli#and?= =?UTF-8?q?roid=20=E2=86=92=20@react-native/core-cli-utils#android=20(#432?= =?UTF-8?q?89)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43289 Move react-native-community/cli build-android into core per RFC0759. Provides: - assemble - build (assemble + tests) - install Changelog: [General][Added] RFC-0759 Move cli Android build into core Reviewed By: cortinico, cipolleschi Differential Revision: D54112210 fbshipit-source-id: 2c9016dd3abd4d382a3d73abd90ba4b0eca7728c --- packages/core-cli-utils/index.js | 5 +- packages/core-cli-utils/private/android.js | 123 +++++++++++++++++++++ packages/core-cli-utils/private/utils.js | 3 + 3 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 packages/core-cli-utils/private/android.js diff --git a/packages/core-cli-utils/index.js b/packages/core-cli-utils/index.js index 1e31339523c6b9..ad4e4c9cde6b8b 100644 --- a/packages/core-cli-utils/index.js +++ b/packages/core-cli-utils/index.js @@ -9,10 +9,13 @@ * @oncall react_native */ +import {tasks as android} from './private/android.js'; import {tasks as apple} from './private/apple.js'; import {tasks as clean} from './private/clean.js'; +/* eslint sort-keys : "error" */ export default { - clean, + android, apple, + clean, }; diff --git a/packages/core-cli-utils/private/android.js b/packages/core-cli-utils/private/android.js new file mode 100644 index 00000000000000..e6b8e1f8c8bfc9 --- /dev/null +++ b/packages/core-cli-utils/private/android.js @@ -0,0 +1,123 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict-local + * @format + * @oncall react_native + */ + +import type {Task} from './types'; + +import {isWindows, task, toPascalCase} from './utils'; +import execa from 'execa'; + +type AndroidBuildMode = 'debug' | 'release'; + +type AndroidBuild = { + sourceDir: string, + appName: string, + mode: AndroidBuildMode, + gradleArgs?: Array, +}; + +type GradleReturn = ReturnType; + +async function gradle( + cwd: string, + ...args: string[] +): ReturnType { + const gradlew = isWindows ? 'gradlew.bat' : './gradlew'; + // $FlowFixMe[incompatible-return] Mismatch between flow and TypeScript types + return execa(gradlew, args, { + cwd, + stdio: 'inherit', + }); +} + +// +// Gradle Task wrappers +// + +/** + * Assembles an Android app using Gradle + */ +export const assemble = ( + cwd: string, + appName: string, + mode: AndroidBuildMode, + ...args: $ReadOnlyArray +): GradleReturn => + gradle(cwd, `${appName}:assemble${toPascalCase(mode)}`, ...args); + +/** + * Assembles and tests an Android app using Gradle + */ +export const build = ( + cwd: string, + appName: string, + mode: AndroidBuildMode, + ...args: $ReadOnlyArray +): GradleReturn => + gradle(cwd, `${appName}:build${toPascalCase(mode)}`, ...args); + +/** + * Installs an Android app using Gradle + */ +export const install = ( + cwd: string, + appName: string, + mode: AndroidBuildMode, + ...args: $ReadOnlyArray +): GradleReturn => + gradle(cwd, `${appName}:install${toPascalCase(mode)}`, ...args); + +/** + * Runs a custom Gradle task if your frameworks needs aren't handled by assemble, build or install. + */ +export const customTask = ( + cwd: string, + customTaskName: string, + ...args: $ReadOnlyArray +): GradleReturn => gradle(cwd, customTaskName, ...args); + +// +// Android Tasks +// + +type AndroidTasks = { + assemble: (options: AndroidBuild, ...args: $ReadOnlyArray) => Task[], + build: (options: AndroidBuild, ...args: $ReadOnlyArray) => Task[], + install: (options: AndroidBuild, ...args: $ReadOnlyArray) => Task[], +}; + +export const tasks: AndroidTasks = { + assemble: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray) => [ + task('Assemble Android App', () => + assemble(options.sourceDir, options.appName, options.mode, ...gradleArgs), + ), + ], + build: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray) => [ + task('Assembles and tests Android App', () => + build(options.sourceDir, options.appName, options.mode, ...gradleArgs), + ), + ], + /** + * Useful extra gradle arguments: + * + * -PreactNativeDevServerPort=8081 sets the port for the installed app to point towards a Metro + * server on (for example) 8081. + */ + install: (options: AndroidBuild, ...gradleArgs: $ReadOnlyArray) => [ + task('Installs the assembled Android App', () => + install(options.sourceDir, options.appName, options.mode, ...gradleArgs), + ), + ], + + // We are not supporting launching the app and setting up the tunnel for metro <-> app, this is + // a framework concern. For an example of how one could do this, please look at the community + // CLI's code: + // https://github.com/react-native-community/cli/blob/54d48a4e08a1aef334ae6168788e0157a666b4f5/packages/cli-platform-android/src/commands/runAndroid/index.ts#L272C1-L290C2 +}; diff --git a/packages/core-cli-utils/private/utils.js b/packages/core-cli-utils/private/utils.js index eb8e455cfa6907..f70a1f59328fa3 100644 --- a/packages/core-cli-utils/private/utils.js +++ b/packages/core-cli-utils/private/utils.js @@ -24,6 +24,9 @@ export function task(label: string, action: Task['action']): Task { export const isWindows = os.platform() === 'win32'; export const isMacOS = os.platform() === 'darwin'; +export const toPascalCase = (label: string): string => + label.length === 0 ? '' : label[0].toUpperCase() + label.slice(1); + type PathCheckResult = { found: boolean, dep: string, From f855de7fedb130355088acda3a7569858a62e87b Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Wed, 13 Mar 2024 11:07:12 -0700 Subject: [PATCH 190/361] Add @react-native/core-cli-utils to build script Summary: Changelog: [Internal] Use our build script for packages and to generate the TypeScript types. bypass-github-export-checks Reviewed By: huntie Differential Revision: D54428870 fbshipit-source-id: 2a1666d30ac472300979b2be078a906d390e919a --- packages/core-cli-utils/package.json | 2 +- packages/core-cli-utils/{ => src}/index.js | 0 packages/core-cli-utils/{ => src}/private/android.js | 0 packages/core-cli-utils/{ => src}/private/apple.js | 0 packages/core-cli-utils/{ => src}/private/clean.js | 0 packages/core-cli-utils/{ => src}/private/types.js | 0 packages/core-cli-utils/{ => src}/private/utils.js | 0 scripts/build/config.js | 9 +++++++-- 8 files changed, 8 insertions(+), 3 deletions(-) rename packages/core-cli-utils/{ => src}/index.js (100%) rename packages/core-cli-utils/{ => src}/private/android.js (100%) rename packages/core-cli-utils/{ => src}/private/apple.js (100%) rename packages/core-cli-utils/{ => src}/private/clean.js (100%) rename packages/core-cli-utils/{ => src}/private/types.js (100%) rename packages/core-cli-utils/{ => src}/private/utils.js (100%) diff --git a/packages/core-cli-utils/package.json b/packages/core-cli-utils/package.json index f6bc2e855bba85..4eeee1c5d0379f 100644 --- a/packages/core-cli-utils/package.json +++ b/packages/core-cli-utils/package.json @@ -10,7 +10,7 @@ "directory": "packages/core-cli-utils" }, "exports": { - ".": "./index.js", + ".": "./src/index.js", "./package.json": "./package.json" }, "homepage": "https://github.com/facebook/react-native/tree/HEAD/packages/core-cli-utils#readme", diff --git a/packages/core-cli-utils/index.js b/packages/core-cli-utils/src/index.js similarity index 100% rename from packages/core-cli-utils/index.js rename to packages/core-cli-utils/src/index.js diff --git a/packages/core-cli-utils/private/android.js b/packages/core-cli-utils/src/private/android.js similarity index 100% rename from packages/core-cli-utils/private/android.js rename to packages/core-cli-utils/src/private/android.js diff --git a/packages/core-cli-utils/private/apple.js b/packages/core-cli-utils/src/private/apple.js similarity index 100% rename from packages/core-cli-utils/private/apple.js rename to packages/core-cli-utils/src/private/apple.js diff --git a/packages/core-cli-utils/private/clean.js b/packages/core-cli-utils/src/private/clean.js similarity index 100% rename from packages/core-cli-utils/private/clean.js rename to packages/core-cli-utils/src/private/clean.js diff --git a/packages/core-cli-utils/private/types.js b/packages/core-cli-utils/src/private/types.js similarity index 100% rename from packages/core-cli-utils/private/types.js rename to packages/core-cli-utils/src/private/types.js diff --git a/packages/core-cli-utils/private/utils.js b/packages/core-cli-utils/src/private/utils.js similarity index 100% rename from packages/core-cli-utils/private/utils.js rename to packages/core-cli-utils/src/private/utils.js diff --git a/scripts/build/config.js b/scripts/build/config.js index 676fffb5c74b46..e889eb4d1b7986 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -41,17 +41,22 @@ export type BuildConfig = $ReadOnly<{ * Node.js packages only. */ const buildConfig /*: BuildConfig */ = { + /* eslint sort-keys: "error" */ packages: { 'community-cli-plugin': { target: 'node', }, - 'dev-middleware': { + 'core-cli-utils': { + emitTypeScriptDefs: true, target: 'node', + }, + 'dev-middleware': { emitTypeScriptDefs: true, + target: 'node', }, 'metro-config': { - target: 'node', emitTypeScriptDefs: true, + target: 'node', }, }, }; From 5807ada2921955764f298a265ca9d795e125dc9a Mon Sep 17 00:00:00 2001 From: kolyaVV Date: Wed, 13 Mar 2024 12:02:13 -0700 Subject: [PATCH 191/361] change: replace twitter with x (#43423) Summary: When users create a new app, there is an option: Follow us on Twitter with the description. Twitter is X now. ![twitter](https://github.com/facebook/react-native/assets/8622007/7565a692-0e83-4549-a688-08f3ba28c76b) ## Changelog: [Internal] Replace the Twitter link, title, and description with X. Pull Request resolved: https://github.com/facebook/react-native/pull/43423 Test Plan: Set the environment for React Native app and then `npx react-native@latest init AwesomeProject`, `npm start`, and `npm run ios` Reviewed By: cortinico Differential Revision: D54850199 Pulled By: huntie fbshipit-source-id: 424cb9212962d78a5b2d93d973f56498ba948136 --- .../Libraries/NewAppScreen/components/LearnMoreLinks.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js b/packages/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js index cff854bcca7949..27195e3c4a2007 100644 --- a/packages/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js +++ b/packages/react-native/Libraries/NewAppScreen/components/LearnMoreLinks.js @@ -74,10 +74,10 @@ const links = [ }, { id: 9, - title: 'Follow us on Twitter', - link: 'https://twitter.com/reactnative', + title: 'Follow us', + link: 'https://x.com/reactnative', description: - 'Stay in touch with the community, join in on Q&As and more by following React Native on Twitter.', + 'Stay in touch with the community, join in on Q&As and more by following React Native on X.', }, ]; From b2e1db0fbf845c48878c4a0ea9cb5755a85a6f0e Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Wed, 13 Mar 2024 15:08:55 -0700 Subject: [PATCH 192/361] Support onConfigurationChanged in Bridgeless (#43463) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43463 Implement `onConfigurationChanged` in Bridgeless by adding it to ReactHostImpl Changelog: [Android][Breaking] Implement onConfigurationChanged in Bridgeless Reviewed By: cortinico, RSNara Differential Revision: D54792399 fbshipit-source-id: 6851daca815f486f4d839e128a1d740d3fec1996 --- .../ReactAndroid/api/ReactAndroid.api | 3 +++ .../com/facebook/react/ReactActivityDelegate.java | 8 +------- .../java/com/facebook/react/ReactDelegate.java | 12 ++++++++++++ .../src/main/java/com/facebook/react/ReactHost.kt | 2 ++ .../com/facebook/react/runtime/ReactHostImpl.java | 15 +++++++++++++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 3ac2275e0de738..7f2be705b81168 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -150,6 +150,7 @@ public class com/facebook/react/ReactDelegate { public fun loadApp (Ljava/lang/String;)V public fun onActivityResult (IILandroid/content/Intent;Z)V public fun onBackPressed ()Z + public fun onConfigurationChanged (Landroid/content/res/Configuration;)V public fun onHostDestroy ()V public fun onHostPause ()V public fun onHostResume ()V @@ -199,6 +200,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; public abstract fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public abstract fun onBackPressed ()Z + public abstract fun onConfigurationChanged (Landroid/content/Context;)V public abstract fun onHostDestroy ()V public abstract fun onHostDestroy (Landroid/app/Activity;)V public abstract fun onHostPause ()V @@ -3639,6 +3641,7 @@ public class com/facebook/react/runtime/ReactHostImpl : com/facebook/react/React public fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; public fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public fun onBackPressed ()Z + public fun onConfigurationChanged (Landroid/content/Context;)V public fun onHostDestroy ()V public fun onHostDestroy (Landroid/app/Activity;)V public fun onHostPause ()V diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index a54238c801447a..7079133f7d5149 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -191,13 +191,7 @@ public void onWindowFocusChanged(boolean hasFocus) { } public void onConfigurationChanged(Configuration newConfig) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: support onConfigurationChanged - } else { - if (getReactNativeHost().hasInstance()) { - getReactInstanceManager().onConfigurationChanged(getContext(), newConfig); - } - } + mReactDelegate.onConfigurationChanged(newConfig); } public void requestPermissions( diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 7230538f312d6f..1cda3ab15411ce 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -9,6 +9,7 @@ import android.app.Activity; import android.content.Intent; +import android.content.res.Configuration; import android.os.Bundle; import android.view.KeyEvent; import androidx.annotation.Nullable; @@ -172,6 +173,17 @@ public void onWindowFocusChanged(boolean hasFocus) { } } + public void onConfigurationChanged(Configuration newConfig) { + if (ReactFeatureFlags.enableBridgelessArchitecture) { + mReactHost.onConfigurationChanged(Assertions.assertNotNull(mActivity)); + } else { + if (getReactNativeHost().hasInstance()) { + getReactInstanceManager() + .onConfigurationChanged(Assertions.assertNotNull(mActivity), newConfig); + } + } + } + public void loadApp() { loadApp(mMainComponentName); } diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index 11a7826437179f..b66775c2e76ca8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -126,6 +126,8 @@ public interface ReactHost { /* This method will give JS the opportunity to receive intents via Linking. */ public fun onNewIntent(intent: Intent) + public fun onConfigurationChanged(context: Context) + public fun addBeforeDestroyListener(onBeforeDestroy: () -> Unit) public fun removeBeforeDestroyListener(onBeforeDestroy: () -> Unit) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index bf28ed8a8fa2ea..3379c3b8b59247 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -58,6 +58,7 @@ import com.facebook.react.interfaces.TaskInterface; import com.facebook.react.interfaces.exceptionmanager.ReactJsExceptionHandler; import com.facebook.react.interfaces.fabric.ReactSurface; +import com.facebook.react.modules.appearance.AppearanceModule; import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.runtime.internal.bolts.Continuation; @@ -699,6 +700,20 @@ public void onNewIntent(Intent intent) { new ReactNoCrashSoftException("Tried to access onNewIntent while context is not ready")); } + @ThreadConfined(UI) + @Override + public void onConfigurationChanged(Context updatedContext) { + ReactContext currentReactContext = getCurrentReactContext(); + if (currentReactContext != null) { + AppearanceModule appearanceModule = + currentReactContext.getNativeModule(AppearanceModule.class); + + if (appearanceModule != null) { + appearanceModule.onConfigurationChanged(updatedContext); + } + } + } + @Nullable JavaScriptContextHolder getJavaScriptContextHolder() { final ReactInstance reactInstance = mReactInstanceTaskRef.get().getResult(); From e03296372754b15169ff95e99c9cfe866f675868 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Wed, 13 Mar 2024 16:13:52 -0700 Subject: [PATCH 193/361] Remove unused forward declaration of RCTMountingManager (#43453) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43453 The forward declaration for RCTMountingManager doesn't appear to be used anywhere. It can be deleted. ## Changelog [Internal] Reviewed By: NickGerleman Differential Revision: D54692764 fbshipit-source-id: ba8206408fdd515387a0a6aff6a3e43c51221e57 --- packages/react-native/React/Fabric/RCTScheduler.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-native/React/Fabric/RCTScheduler.h b/packages/react-native/React/Fabric/RCTScheduler.h index 888770cfd9fea0..9af355aa006bf1 100644 --- a/packages/react-native/React/Fabric/RCTScheduler.h +++ b/packages/react-native/React/Fabric/RCTScheduler.h @@ -21,8 +21,6 @@ NS_ASSUME_NONNULL_BEGIN -@class RCTMountingManager; - /** * Exactly same semantic as `facebook::react::SchedulerDelegate`. */ From 5c58811bd591312e386287b43107ea0b08e1dd0d Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Wed, 13 Mar 2024 19:30:54 -0700 Subject: [PATCH 194/361] Add FilterHelper to get all RenderEffects needed to apply filters (#43357) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43357 This diff adds a class to get the needed RenderEffects to support CSS filters on Android. This diff does not add any of the plumbing for it to actually work, that comes in the next diff, but I figured this was complicated and isolated enough to be on its own. Note that I did not add blur or drop shadow as those are a bit more involved and I plan on adding them later. Changelog: [Internal] Reviewed By: javache Differential Revision: D54603892 fbshipit-source-id: 5780d7c846fdb1116e29e0a940ee02da609b01f5 --- .../react/uimanager/FilterHelper.java | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) create mode 100644 packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/FilterHelper.java diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/FilterHelper.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/FilterHelper.java new file mode 100644 index 00000000000000..56bfa21ee676ac --- /dev/null +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/FilterHelper.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +package com.facebook.react.uimanager; + +import android.annotation.TargetApi; +import android.graphics.ColorFilter; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; +import android.graphics.RenderEffect; +import android.graphics.Shader; +import androidx.annotation.Nullable; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.bridge.ReadableMap; + +@TargetApi(31) +class FilterHelper { + static @Nullable RenderEffect parseFilters(@Nullable ReadableArray filters) { + if (filters == null) { + return null; + } + + RenderEffect chainedEffects = null; + for (int i = 0; i < filters.size(); i++) { + ReadableMap filter = filters.getMap(i); + @Nullable String filterName = filter.getString("name"); + if (filterName == null) { + continue; + } + + switch (filterName) { + case "brightness": + float brightnessAmount = (float) filter.getDouble("amount"); + ColorFilter brightnessFilter = + new ColorMatrixColorFilter(getBrightnessColorMatrix(brightnessAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, brightnessFilter); + break; + case "contrast": + float contrastAmount = (float) filter.getDouble("amount"); + ColorFilter contrastFilter = + new ColorMatrixColorFilter(getContrastColorMatrix(contrastAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, contrastFilter); + break; + case "grayscale": + float grayscaleAmount = (float) filter.getDouble("amount"); + ColorFilter grayscaleFilter = + new ColorMatrixColorFilter(getGrayscaleColorMatrix(grayscaleAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, grayscaleFilter); + break; + case "sepia": + float sepiaAmount = (float) filter.getDouble("amount"); + ColorFilter sepiaFilter = new ColorMatrixColorFilter(getSepiaColorMatrix(sepiaAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, sepiaFilter); + break; + case "saturate": + float saturateAmount = (float) filter.getDouble("amount"); + ColorFilter saturateFilter = + new ColorMatrixColorFilter(getSaturateColorMatrix(saturateAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, saturateFilter); + break; + case "hue-rotate": + float hueRotateAmount = (float) filter.getDouble("amount"); + ColorFilter hueRotateFilter = + new ColorMatrixColorFilter(getHueRotateColorMatrix(hueRotateAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, hueRotateFilter); + break; + case "invert": + float invertAmount = (float) filter.getDouble("amount"); + ColorFilter invertColorFilter = + new ColorMatrixColorFilter(getInvertColorMatrix(invertAmount)); + chainedEffects = chainColorFilterEffect(chainedEffects, invertColorFilter); + break; + case "blur": + float blurAmount = (float) filter.getDouble("amount"); + chainedEffects = chainBlurFilterEffect(chainedEffects, blurAmount); + break; + default: + throw new IllegalArgumentException("Invalid filter name: " + filterName); + } + } + + return chainedEffects; + } + + // https://www.w3.org/TR/filter-effects-1/#blurEquivalent + private static RenderEffect chainBlurFilterEffect( + @Nullable RenderEffect chainedEffects, float std) { + // Android takes blur amount as a radius while web takes a sigma. This value + // is used under the hood to convert between them on Android + // https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/libs/hwui/utils/Blur.cpp + float sigmaToRadiusRatio = 0.57735f; + float radius = (std - 0.5f) / sigmaToRadiusRatio; + float scaledRadius = PixelUtil.toPixelFromDIP(radius); + + return chainedEffects == null + ? RenderEffect.createBlurEffect(scaledRadius, scaledRadius, Shader.TileMode.DECAL) + : RenderEffect.createBlurEffect( + scaledRadius, scaledRadius, chainedEffects, Shader.TileMode.DECAL); + } + + private static RenderEffect chainColorFilterEffect( + @Nullable RenderEffect chainedEffects, ColorFilter colorFilter) { + return chainedEffects == null + ? RenderEffect.createColorFilterEffect(colorFilter) + : RenderEffect.createColorFilterEffect(colorFilter, chainedEffects); + } + + // https://www.w3.org/TR/filter-effects-1/#brightnessEquivalent + private static ColorMatrix getBrightnessColorMatrix(float amount) { + ColorMatrix matrix = new ColorMatrix(); + matrix.setScale(amount, amount, amount, 1); + + return matrix; + } + + // https://www.w3.org/TR/filter-effects-1/#contrastEquivalent + private static ColorMatrix getContrastColorMatrix(float amount) { + // Multiply by 255 as Android operates in [0, 255] while the spec operates in [0, 1]. + // This really only matters if there is an intercept that needs to be added + float intercept = 255 * (-(amount / 2.0f) + 0.5f); + + float[] colorMatrix = { + amount, 0, 0, 0, intercept, // + 0, amount, 0, 0, intercept, // + 0, 0, amount, 0, intercept, // + 0, 0, 0, 1, 0 + }; + + return new ColorMatrix(colorMatrix); + } + + // https://www.w3.org/TR/filter-effects-1/#grayscaleEquivalent + private static float[] getGrayscaleColorMatrix(float amount) { + float inverseAmount = 1 - amount; + float[] colorMatrix = { + 0.2126f + 0.7874f * inverseAmount, + 0.7152f - 0.7152f * inverseAmount, + 0.0722f - 0.0722f * inverseAmount, + 0, + 0, + 0.2126f - 0.2126f * inverseAmount, + 0.7152f + 0.2848f * inverseAmount, + 0.0722f - 0.0722f * inverseAmount, + 0, + 0, + 0.2126f - 0.2126f * inverseAmount, + 0.7152f - 0.7152f * inverseAmount, + 0.0722f + 0.9278f * inverseAmount, + 0, + 0, + 0, + 0, + 0, + 1, + 0 + }; + + return colorMatrix; + } + + // https://www.w3.org/TR/filter-effects-1/#sepiaEquivalent + private static float[] getSepiaColorMatrix(float amount) { + float inverseAmount = 1 - amount; + float[] colorMatrix = { + 0.393f + 0.607f * inverseAmount, + 0.769f - 0.769f * inverseAmount, + 0.189f - 0.189f * inverseAmount, + 0, + 0, + 0.349f - 0.349f * inverseAmount, + 0.686f + 0.314f * inverseAmount, + 0.168f - 0.168f * inverseAmount, + 0, + 0, + 0.272f - 0.272f * inverseAmount, + 0.534f - 0.534f * inverseAmount, + 0.131f + 0.869f * inverseAmount, + 0, + 0, + 0, + 0, + 0, + 1, + 0 + }; + + return colorMatrix; + } + + // https://www.w3.org/TR/filter-effects-1/#saturateEquivalent + private static ColorMatrix getSaturateColorMatrix(float amount) { + ColorMatrix matrix = new ColorMatrix(); + matrix.setSaturation(amount); + + return matrix; + } + + // https://www.w3.org/TR/filter-effects-1/#huerotateEquivalent + private static float[] getHueRotateColorMatrix(float amount) { + double amountRads = Math.toRadians(amount); + float cos = (float) Math.cos(amountRads); + float sin = (float) Math.sin(amountRads); + float[] matrix = { + 0.213f + 0.787f * cos - 0.213f * sin, + 0.715f - 0.715f * cos - 0.715f * sin, + 0.072f - 0.072f * cos + 0.928f * sin, + 0, + 0, + 0.213f - 0.213f * cos + 0.143f * sin, + 0.715f + 0.285f * cos + 0.140f * sin, + 0.072f - 0.072f * cos - 0.283f * sin, + 0, + 0, + 0.213f - 0.213f * cos - 0.787f * sin, + 0.715f - 0.715f * cos + 0.715f * sin, + 0.072f + 0.928f * cos + 0.072f * sin, + 0, + 0, + 0, + 0, + 0, + 1, + 0 + }; + + return matrix; + } + + // https://www.w3.org/TR/filter-effects-1/#invertEquivalent + private static float[] getInvertColorMatrix(float amount) { + float slope = 1 - 2 * amount; + float intercept = amount * 255; + float[] matrix = { + slope, 0, 0, 0, intercept, // + 0, slope, 0, 0, intercept, // + 0, 0, slope, 0, intercept, // + 0, 0, 0, 1, 0 + }; + + return matrix; + } +} From 50d587b67fd4157a54448dec7bf1aa311180e614 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Wed, 13 Mar 2024 19:30:54 -0700 Subject: [PATCH 195/361] Fix clipping children in scroll views (#43464) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43464 While working on filters I noticed that my blurred image was cropped on the scrollview. Setting `overflow: visible` for `contentContainerStyle` did not change anything. Turns out we do not call `setClipChildren(false)` like we do with [ReactViewGroup](https://www.internalfb.com/code/fbsource/[93517723586c]/xplat/js/react-native-github/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java?lines=145). Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D54640466 fbshipit-source-id: 3f71af3170df8f75887d57643b84e64807856ca6 --- .../facebook/react/views/scroll/ReactHorizontalScrollView.java | 1 + .../java/com/facebook/react/views/scroll/ReactScrollView.java | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 7e52edb5a2c7c9..3ec4c5c96e4ee7 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -139,6 +139,7 @@ public ReactHorizontalScrollView(Context context, @Nullable FpsListener fpsListe : ViewCompat.LAYOUT_DIRECTION_LTR); setOnHierarchyChangeListener(this); + setClipChildren(false); } public boolean getScrollEnabled() { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 50fc9b0bc43c03..26950b2ea9f958 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -131,6 +131,7 @@ public ReactScrollView(Context context, @Nullable FpsListener fpsListener) { mScroller = getOverScrollerFromParent(); setOnHierarchyChangeListener(this); setScrollBarStyle(SCROLLBARS_OUTSIDE_OVERLAY); + setClipChildren(false); ViewCompat.setAccessibilityDelegate(this, new ReactScrollViewAccessibilityDelegate()); } From 082decb76d05e070858e363779f5daa78de45ccf Mon Sep 17 00:00:00 2001 From: Pieter Vanderwerff Date: Wed, 13 Mar 2024 22:23:03 -0700 Subject: [PATCH 196/361] Deploy 0.231.0 to xplat (#43475) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43475 Changelog: [Internal] Reviewed By: SamChou19815 Differential Revision: D54886285 fbshipit-source-id: cc4f6eeb7986a25d2bb423dac0b7d1d5a74b9703 --- .flowconfig | 2 +- flow-typed/npm/shelljs_v0.x.x.js | 1 - package.json | 2 +- yarn.lock | 8 ++++---- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.flowconfig b/.flowconfig index bebab54962e4f1..2c5ea1ed4bd627 100644 --- a/.flowconfig +++ b/.flowconfig @@ -85,4 +85,4 @@ untyped-import untyped-type-import [version] -^0.230.0 +^0.231.0 diff --git a/flow-typed/npm/shelljs_v0.x.x.js b/flow-typed/npm/shelljs_v0.x.x.js index b1bff7b8402d51..9e1ca8fe805515 100644 --- a/flow-typed/npm/shelljs_v0.x.x.js +++ b/flow-typed/npm/shelljs_v0.x.x.js @@ -136,7 +136,6 @@ declare interface $npm$shelljs$Result { ((rest: void) => $npm$shelljs$String); } -// $FlowFixMe[unsupported-syntax] declare module 'shelljs' { declare export type ShellArray = $npm$shelljs$Array; declare export type ShellAsync = $npm$shelljs$Async; diff --git a/package.json b/package.json index 44779411e7373f..32439d0d3831de 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", "flow-api-translator": "0.20.1", - "flow-bin": "^0.230.0", + "flow-bin": "^0.231.0", "glob": "^7.1.1", "hermes-eslint": "0.20.1", "hermes-transform": "0.20.1", diff --git a/yarn.lock b/yarn.lock index a1aa51b8663429..6ab6ebe2fe0db5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5138,10 +5138,10 @@ flow-api-translator@0.20.1: hermes-parser "0.20.1" hermes-transform "0.20.1" -flow-bin@^0.230.0: - version "0.230.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.230.0.tgz#eefb67215270ab144cd1fa0203061d1687d1cfa6" - integrity sha512-Yx/AnKXR+D4Ieb7xlanfe7cNamJEsuXG6RLWCOl7OSzehMDmrZUuGh2Ycvf4tCKdM1nYt2569p3kkNELiBonaw== +flow-bin@^0.231.0: + version "0.231.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.231.0.tgz#b9fde021e60ff6e40e4f0212b6c426fdde798ac7" + integrity sha512-nB5/rH+bUCIAXWagwIEYM0q/2M4mgkD5q16/eZyNx7sfqsmMkZLg0KmPH5hgvzq6PkVoeCoM8sjhPyzLW2wT+w== flow-enums-runtime@^0.0.6: version "0.0.6" From 47a3f5200708fc0247d8b403dbe447af636b79cb Mon Sep 17 00:00:00 2001 From: Blake Friedman Date: Thu, 14 Mar 2024 03:37:44 -0700 Subject: [PATCH 197/361] Add RFC-0759 deprecation logging cli init Summary: Implements the RFC which progressively provides warnings to users of the `npx react-native init` command as we gradually deprecate. Changelog: [General][Deprecated] - init cli deprecation logging Reviewed By: cortinico Differential Revision: D54423109 fbshipit-source-id: 679b6672bdbfc42a9b82a2aad38fd3253c6ea6a2 --- packages/react-native/cli.js | 106 ++++++++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/packages/react-native/cli.js b/packages/react-native/cli.js index 0e1bd5216512d0..53c7e47df57165 100755 --- a/packages/react-native/cli.js +++ b/packages/react-native/cli.js @@ -11,16 +11,33 @@ 'use strict'; const {name, version: currentVersion} = require('./package.json'); -const cli = require('@react-native-community/cli'); const chalk = require('chalk'); const {get} = require('https'); const {URL} = require('url'); +const deprecated = () => { + throw new Error( + 'react-native/cli is deprecated, please use @react-native-community/cli instead', + ); +}; + +let cli = { + bin: '/dev/null', + loadConfig: deprecated, + run: deprecated, +}; + const isNpxRuntime = process.env.npm_lifecycle_event === 'npx'; const DEFAULT_REGISTRY_HOST = process.env.npm_config_registry ?? 'https://registry.npmjs.org/'; const HEAD = '1000.0.0'; +// We're going to deprecate the `init` command proxying requests to @react-native-community/cli transparently +// on September 30th, 2024 or 0.76 (whichever arrives first). This is part of work to decouple of community CLI from React Native core. +// +// See https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md +const CLI_DEPRECATION_DATE = new Date('2024-09-30'); + async function getLatestVersion(registryHost = DEFAULT_REGISTRY_HOST) { return new Promise((res, rej) => { const url = new URL(registryHost); @@ -41,14 +58,64 @@ async function getLatestVersion(registryHost = DEFAULT_REGISTRY_HOST) { /** * Warn when users are using `npx react-native init`, to raise awareness of the changes from RFC 0759. + * + * Phase 1 + * * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md */ function warnWhenRunningInit() { if (process.argv[2] === 'init') { - console.warn('\nRunning: npx @react-native-community/cli init\n'); + console.warn( + `\nRunning: ${chalk.grey.bold('npx @react-native-community/cli init')}\n`, + ); } } +/** + * Warn more sternly that the ability to call `npx react-native init` is going away. + * + * Phase 2 + * + * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md + */ +function warnWithDeprecationSchedule() { + if (process.argv[2] !== 'init') { + return; + } + + const daysRemaining = Math.ceil( + (CLI_DEPRECATION_DATE.getTime() - new Date().getTime()) / 86_400_000, + ); + + const emphasis = + daysRemaining < 10 + ? chalk.bgRed.white.bold + : daysRemaining < 30 + ? chalk.red.bold + : daysRemaining < 60 + ? chalk.green.bold + : chalk.blueBright.bold; + + console.warn(` +${chalk.yellow('⚠️')} The \`init\` command is deprecated. +The behavior will be changed on ${chalk.white.bold(CLI_DEPRECATION_DATE.toLocaleDateString())} ${emphasis(`(${daysRemaining} day${daysRemaining > 1 ? 's' : ''})`)}. + +- Switch to ${chalk.dim('npx @react-native-community/cli init')} for the identical behavior. +- Refer to the documentation for information about alternative tools: ${chalk.dim('https://reactnative.dev/docs/getting-started')}`); +} + +function warnWithDeprecated() { + if (process.argv[2] !== 'init') { + return; + } + + console.warn(` +${chalk.yellow('⚠')}️ The \`init\` command is deprecated. + +- Switch to ${chalk.dim('npx @react-native-community/cli init')} for the identical behavior. +- Refer to the documentation for information about alternative tools: ${chalk.dim('https://reactnative.dev/docs/getting-started')}`); +} + /** * npx react-native -> @react-native-community/cli * @@ -77,13 +144,46 @@ async function main() { } } + const isDeprecated = + CLI_DEPRECATION_DATE.getTime() <= new Date().getTime() || + currentVersion.startsWith('0.76'); + + /** + * This command now fails as it's fully deprecated. It will be entirely removed in 0.77. + * + * Phase 3 + * + * @see https://github.com/react-native-community/discussions-and-proposals/tree/main/proposals/0759-react-native-frameworks.md + */ + if (currentVersion !== HEAD && isDeprecated) { + warnWithDeprecated(); + process.exit(1); + } + + if (currentVersion.startsWith('0.75')) { + warnWithDeprecationSchedule(); + } + warnWhenRunningInit(); - return cli.run(name); + return require('@react-native-community/cli').run(name); } if (require.main === module) { main(); +} else { + try { + cli = require('@react-native-community/cli'); + } catch (e) { + // We silence @react-native-community/cli missing as it is no + // longer a dependency + if ( + !e.code === 'MODULE_NOT_FOUND' && + /@react-native-community\/cli/.test(e.message) + ) { + throw e; + } + } } module.exports = cli; From 0d7a92b551bb8bd91aeba73316cbaf7315362094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20B=C5=82oniarz?= Date: Thu, 14 Mar 2024 07:27:29 -0700 Subject: [PATCH 198/361] Add conditional return in `handleRemoveView` (#43389) Summary: I was recently working on an [issue](https://github.com/software-mansion/react-native-reanimated/issues/5715) in Reanimated where z-index of some views was broken after a Layout Animation was used. The issue was that in some cases we were calling the `removeView` function on a already removed view. On plain Android this wouldn't be an issue, since the `removeView` function ignores such calls. Unfortunately, the `ReactViewGroup.java` implementation maintains a counter of views with user defined z-index. This counter is decremented whenever a call to `removeView` is made, even if the view is not a child of this `ViewGroup`. This PR adds an additional check in the `handleRemoveView` function to unify the `removeView` behavior between Android and react-native. ## Changelog: [ANDROID] [CHANGED] - Changed the `handleRemoveView` function in `ReactViewGroup.java` to ignore calls for `Views` that are not children of this `ViewGroup` Pull Request resolved: https://github.com/facebook/react-native/pull/43389 Test Plan: I tested if the `rn-tester` app behaves correctly after those changes. Reviewed By: NickGerleman Differential Revision: D54874780 Pulled By: javache fbshipit-source-id: f1a34947419ef6106ee73b196ae99b7f8c2f7a77 --- .../java/com/facebook/react/views/view/ReactViewGroup.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java index bc5d22b34cc247..1af57b99847448 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java @@ -519,6 +519,9 @@ private void handleRemoveView(View view) { UiThreadUtil.assertOnUiThread(); if (!customDrawOrderDisabled()) { + if (indexOfChild(view) == -1) { + return; + } getDrawingOrderHelper().handleRemoveView(view); setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder()); } else { From 4148a31912e620c282495b54600abb9bb4276421 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Thu, 14 Mar 2024 07:59:31 -0700 Subject: [PATCH 199/361] Integration test for CDPAgent reentrancy bugs Summary: Changelog: [Internal] Adds a regression test for a Hermes CDPAgent bug using `JsiIntegrationTest`. See details in comments. bypass-github-export-checks Reviewed By: huntie Differential Revision: D54890188 fbshipit-source-id: 325a32b83b145d2d35f99feaef9988028f15f196 --- .../tests/JsiIntegrationTest.cpp | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp index e9ccbe96c7c275..a4a2e773aa434c 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/tests/JsiIntegrationTest.cpp @@ -620,6 +620,66 @@ TYPED_TEST(JsiIntegrationHermesModernTest, ResolveBreakpointAfterReload) { scriptInfo->value()["params"]["scriptId"]); } +TYPED_TEST(JsiIntegrationHermesModernTest, CDPAgentReentrancyRegressionTest) { + this->connect(); + + // TODO(moti): Add an InSequence guard here once Hermes processes the messages + // in the order they were received. + + this->inspectorExecutor_([&]() { + // Tasks scheduled on our executor here will be executed when this lambda + // returns. This is integral to the bug we're trying to reproduce, so we + // place the EXPECT_* calls at the end of the lambda body to ensure the + // test fails if we get eager (unexpected) responses. + + // 1. Cause CDPAgent to schedule a task on the JS executor to process the + // message. The task is simultaneously scheduled as an interrupt on the + // JS VM (but will be called via the executor, since the interpreter is + // idle at the moment). + this->toPage_->sendMessage(R"({ + "id": 1, + "method": "Runtime.evaluate", + "params": {"expression": "1 + 2"} + })"); + + // 2. Cause CDPAgent to schedule another task+interrupt. + this->toPage_->sendMessage(R"({ + "id": 2, + "method": "Runtime.evaluate", + "params": {"expression": "3 + 4"} + })"); + + // 3. When the first scheduled task runs (via the executor), it enters the + // interpreter to evaluate the expression, at which point the + // interpreter begins processing interrupts and enters the second task. + // This used to trigger two distinct bugs in CDPAgent: + // - The first task would be triggered twice due to a race condition + // between the executor and the interrupt handler. (D54771697) + // - The second task would deadlock due to the first task holding a + // lock preventing any other CDPAgent tasks from running. (D54838179) + + this->expectMessageFromPage(JsonEq(R"({ + "id": 1, + "result": { + "result": { + "type": "number", + "value": 3 + } + } + })")); + + this->expectMessageFromPage(JsonEq(R"({ + "id": 2, + "result": { + "result": { + "type": "number", + "value": 7 + } + } + })")); + }); +} + #pragma endregion // ModernHermesVariants } // namespace facebook::react::jsinspector_modern From 10d48134c9dd295c9f877bb18b431c4548559a84 Mon Sep 17 00:00:00 2001 From: zhongwuzw Date: Thu, 14 Mar 2024 08:33:49 -0700 Subject: [PATCH 200/361] iOS: Fixes textinput onscroll event payload (#43445) Summary: Fixes https://github.com/facebook/react-native/issues/43428 . cc cortinico . ## Changelog: [IOS] [FIXED] - [Fabric] iOS: Fixes textinput onscroll event payload Pull Request resolved: https://github.com/facebook/react-native/pull/43445 Test Plan: ``` const onInputScroll = (e) => { if (Platform.OS !== "web") { const { nativeEvent: { contentOffset: { x, y }, }, } = e; console.log('onInputScroll ====', e?.nativeEvent) } }; ``` Reviewed By: cortinico Differential Revision: D54813378 Pulled By: sammy-SC fbshipit-source-id: 76671fbb390c2fbc67a9c29b6c2a834ba699fff4 --- .../iostextinput/TextInputEventEmitter.cpp | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp index 4b39a211fba349..30279cd4cf2839 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputEventEmitter.cpp @@ -36,6 +36,56 @@ static jsi::Value textInputMetricsPayload( return payload; }; +static jsi::Value textInputMetricsScrollPayload( + jsi::Runtime& runtime, + const TextInputMetrics& textInputMetrics) { + auto payload = jsi::Object(runtime); + + { + auto contentOffset = jsi::Object(runtime); + contentOffset.setProperty(runtime, "x", textInputMetrics.contentOffset.x); + contentOffset.setProperty(runtime, "y", textInputMetrics.contentOffset.y); + payload.setProperty(runtime, "contentOffset", contentOffset); + } + + { + auto contentInset = jsi::Object(runtime); + contentInset.setProperty(runtime, "top", textInputMetrics.contentInset.top); + contentInset.setProperty( + runtime, "left", textInputMetrics.contentInset.left); + contentInset.setProperty( + runtime, "bottom", textInputMetrics.contentInset.bottom); + contentInset.setProperty( + runtime, "right", textInputMetrics.contentInset.right); + payload.setProperty(runtime, "contentInset", contentInset); + } + + { + auto contentSize = jsi::Object(runtime); + contentSize.setProperty( + runtime, "width", textInputMetrics.contentSize.width); + contentSize.setProperty( + runtime, "height", textInputMetrics.contentSize.height); + payload.setProperty(runtime, "contentSize", contentSize); + } + + { + auto layoutMeasurement = jsi::Object(runtime); + layoutMeasurement.setProperty( + runtime, "width", textInputMetrics.layoutMeasurement.width); + layoutMeasurement.setProperty( + runtime, "height", textInputMetrics.layoutMeasurement.height); + payload.setProperty(runtime, "layoutMeasurement", layoutMeasurement); + } + + payload.setProperty( + runtime, + "zoomScale", + textInputMetrics.zoomScale ? textInputMetrics.zoomScale : 1); + + return payload; +}; + static jsi::Value textInputMetricsContentSizePayload( jsi::Runtime& runtime, const TextInputMetrics& textInputMetrics) { @@ -121,7 +171,9 @@ void TextInputEventEmitter::onKeyPress( void TextInputEventEmitter::onScroll( const TextInputMetrics& textInputMetrics) const { - dispatchTextInputEvent("scroll", textInputMetrics); + dispatchEvent("scroll", [textInputMetrics](jsi::Runtime& runtime) { + return textInputMetricsScrollPayload(runtime, textInputMetrics); + }); } void TextInputEventEmitter::dispatchTextInputEvent( From a27e2acef4d544ef4c5c58d380068b7cbc10b900 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 14 Mar 2024 10:31:37 -0700 Subject: [PATCH 201/361] Rollout bridgelessArchitectureMemoryPressureHackyBoltsFix (#43478) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43478 This is rolled out internally already. Also exposing `memoryPressureRouter` to match the ReactInstanceManager interface. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D54802021 fbshipit-source-id: b74dcde71296d3925acfc2171d2a77d90960e15e --- .../ReactAndroid/api/ReactAndroid.api | 2 +- .../main/java/com/facebook/react/ReactHost.kt | 3 +++ .../react/config/ReactFeatureFlags.java | 3 --- .../facebook/react/runtime/ReactHostImpl.java | 23 ++++++++----------- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index 7f2be705b81168..a899e813010c25 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -197,6 +197,7 @@ public abstract interface class com/facebook/react/ReactHost { public abstract fun getDevSupportManager ()Lcom/facebook/react/devsupport/interfaces/DevSupportManager; public abstract fun getJsEngineResolutionAlgorithm ()Lcom/facebook/react/JSEngineResolutionAlgorithm; public abstract fun getLifecycleState ()Lcom/facebook/react/common/LifecycleState; + public abstract fun getMemoryPressureRouter ()Lcom/facebook/react/MemoryPressureRouter; public abstract fun getReactQueueConfiguration ()Lcom/facebook/react/bridge/queue/ReactQueueConfiguration; public abstract fun onActivityResult (Landroid/app/Activity;IILandroid/content/Intent;)V public abstract fun onBackPressed ()Z @@ -1922,7 +1923,6 @@ public class com/facebook/react/config/ReactFeatureFlags { public static field excludeYogaFromRawProps Z public static field rejectTurboModulePromiseOnNativeError Z public static field traceTurboModulePromiseRejections Z - public static field unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix Z public static field unstable_enableTurboModuleSyncVoidMethods Z public static field unstable_useFabricInterop Z public static field unstable_useTurboModuleInterop Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt index b66775c2e76ca8..5f09366417af32 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactHost.kt @@ -48,6 +48,9 @@ public interface ReactHost { /** [JSEngineResolutionAlgorithm] used by this host. */ public var jsEngineResolutionAlgorithm: JSEngineResolutionAlgorithm? + /** Routes memory pressure events to interested components */ + public val memoryPressureRouter: MemoryPressureRouter + /** To be called when back button is pressed */ public fun onBackPressed(): Boolean diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index ad6e23618140d1..9c5a562404d76f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -66,9 +66,6 @@ public class ReactFeatureFlags { */ public static boolean enableBridgelessArchitecture = false; - /** Server-side gating for a hacky fix to an ANR in the bridgeless core, related to Bolts task. */ - public static boolean unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix = false; - /** * Does the bridgeless architecture log soft exceptions. Could be useful for tracking down issues. */ diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 3379c3b8b59247..95fcac63cc5a61 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -135,7 +135,7 @@ public class ReactHostImpl implements ReactHost { new ReactLifecycleStateManager(mBridgelessReactStateTracker); private final int mId = mCounter.getAndIncrement(); private @Nullable JSEngineResolutionAlgorithm mJSEngineResolutionAlgorithm = null; - private MemoryPressureListener mMemoryPressureListener; + private @Nullable MemoryPressureListener mMemoryPressureListener; private @Nullable DefaultHardwareBackBtnHandler mDefaultHardwareBackBtnHandler; private final Set> mBeforeDestroyListeners = @@ -178,11 +178,6 @@ public ReactHostImpl( mReactJsExceptionHandler = reactJsExceptionHandler; mQueueThreadExceptionHandler = ReactHostImpl.this::handleHostException; mMemoryPressureRouter = new MemoryPressureRouter(context); - mMemoryPressureListener = - level -> - callWithExistingReactInstance( - "handleMemoryPressure(" + level + ")", - reactInstance -> reactInstance.handleMemoryPressure(level)); mAllowPackagerServerAccess = allowPackagerServerAccess; if (DEV) { mDevSupportManager = @@ -386,6 +381,7 @@ public ReactSurface createSurface( return surface; } + @Override public MemoryPressureRouter getMemoryPressureRouter() { return mMemoryPressureRouter; } @@ -1030,11 +1026,10 @@ private Task getOrCreateReactInstanceTask() { mUseDevSupport, getOrCreateReactHostInspectorTarget()); - if (ReactFeatureFlags - .unstable_bridgelessArchitectureMemoryPressureHackyBoltsFix) { - mMemoryPressureListener = createMemoryPressureListener(instance); - } - mMemoryPressureRouter.addMemoryPressureListener(mMemoryPressureListener); + MemoryPressureListener memoryPressureListener = + createMemoryPressureListener(instance); + mMemoryPressureListener = memoryPressureListener; + mMemoryPressureRouter.addMemoryPressureListener(memoryPressureListener); log(method, "Loading JS Bundle"); instance.loadJSBundle(bundleLoader); @@ -1366,8 +1361,10 @@ private Task getOrCreateReloadTask(String reason) { task -> { reactInstanceTaskUnwrapper.unwrap(task, "4: Destroying ReactContext"); - log(method, "Removing memory pressure listener"); - mMemoryPressureRouter.removeMemoryPressureListener(mMemoryPressureListener); + if (mMemoryPressureListener != null) { + log(method, "Removing memory pressure listener"); + mMemoryPressureRouter.removeMemoryPressureListener(mMemoryPressureListener); + } final ReactContext reactContext = mBridgelessReactContextRef.getNullable(); if (reactContext != null) { From 7488dc05e83f11f75f87c9e02357ae7ad99d36c4 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 14 Mar 2024 10:31:37 -0700 Subject: [PATCH 202/361] Use CopyOnWriteArrayList in MemoryPressureRouter (#43486) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43486 We use `CopyOnWriteArrayList` in other places across the React Native codebase, as it assumes that reading happens more frequently than updating. This saves us from needing to synchronize and copy when we access the list of listeners. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D54806272 fbshipit-source-id: d1b54d532edb2af3391a7e4fdc758f705621227d --- .../facebook/react/MemoryPressureRouter.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java index 75777adb036c36..41dfc24588b6a4 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/MemoryPressureRouter.java @@ -11,14 +11,12 @@ import android.content.Context; import android.content.res.Configuration; import com.facebook.react.bridge.MemoryPressureListener; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; -/** Translates and routes memory pressure events to the current catalyst instance. */ +/** Translates and routes memory pressure events. */ public class MemoryPressureRouter implements ComponentCallbacks2 { - private final Set mListeners = - Collections.synchronizedSet(new LinkedHashSet<>()); + private final CopyOnWriteArrayList mListeners = + new CopyOnWriteArrayList(); public MemoryPressureRouter(Context context) { context.getApplicationContext().registerComponentCallbacks(this); @@ -30,7 +28,9 @@ public void destroy(Context context) { /** Add a listener to be notified of memory pressure events. */ public void addMemoryPressureListener(MemoryPressureListener listener) { - mListeners.add(listener); + if (!mListeners.contains(listener)) { + mListeners.add(listener); + } } /** Remove a listener previously added with {@link #addMemoryPressureListener}. */ @@ -50,11 +50,7 @@ public void onConfigurationChanged(Configuration newConfig) {} public void onLowMemory() {} private void dispatchMemoryPressure(int level) { - // copy listeners array to avoid ConcurrentModificationException if any of the listeners remove - // themselves in handleMemoryPressure() - MemoryPressureListener[] listeners = - mListeners.toArray(new MemoryPressureListener[mListeners.size()]); - for (MemoryPressureListener listener : listeners) { + for (MemoryPressureListener listener : mListeners) { listener.handleMemoryPressure(level); } } From eca4d76d81efa53316cd36fffb97cee8ed206fb1 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 14 Mar 2024 10:31:37 -0700 Subject: [PATCH 203/361] Rollout enableBridgelessArchitectureSoftExceptions (#43485) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43485 Already fully rolled out internally. Changelog: [Internal] Reviewed By: sammy-SC Differential Revision: D54804177 fbshipit-source-id: 128822d408b6943f1f1536eb0101c6684cd45106 --- .../ReactAndroid/api/ReactAndroid.api | 1 - .../facebook/react/config/ReactFeatureFlags.java | 5 ----- .../com/facebook/react/runtime/ReactHostImpl.java | 15 ++++++--------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index a899e813010c25..d43f2379183778 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -1909,7 +1909,6 @@ public class com/facebook/react/config/ReactFeatureFlags { public static field dispatchPointerEvents Z public static field enableBridgelessArchitecture Z public static field enableBridgelessArchitectureNewCreateReloadDestroy Z - public static field enableBridgelessArchitectureSoftExceptions Z public static field enableClonelessStateProgression Z public static field enableCppPropsIteratorSetter Z public static field enableEagerRootViewAttachment Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java index 9c5a562404d76f..7809333d8e4256 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/config/ReactFeatureFlags.java @@ -66,11 +66,6 @@ public class ReactFeatureFlags { */ public static boolean enableBridgelessArchitecture = false; - /** - * Does the bridgeless architecture log soft exceptions. Could be useful for tracking down issues. - */ - public static volatile boolean enableBridgelessArchitectureSoftExceptions = false; - /** Does the bridgeless architecture use the new create/reload/destroy routines */ public static volatile boolean enableBridgelessArchitectureNewCreateReloadDestroy = true; diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java index 95fcac63cc5a61..c98603e9b50e47 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/runtime/ReactHostImpl.java @@ -48,7 +48,6 @@ import com.facebook.react.bridge.queue.ReactQueueConfiguration; import com.facebook.react.common.LifecycleState; import com.facebook.react.common.build.ReactBuildConfig; -import com.facebook.react.config.ReactFeatureFlags; import com.facebook.react.devsupport.DevSupportManagerBase; import com.facebook.react.devsupport.DisabledDevSupportManager; import com.facebook.react.devsupport.InspectorFlags; @@ -879,16 +878,14 @@ private void raiseSoftException(String method, String message) { private void raiseSoftException(String method, String message, @Nullable Throwable throwable) { log(method, message); - if (ReactFeatureFlags.enableBridgelessArchitectureSoftExceptions) { - if (throwable != null) { - ReactSoftExceptionLogger.logSoftException( - TAG, new ReactNoCrashSoftException(method + ": " + message, throwable)); - return; - } - + if (throwable != null) { ReactSoftExceptionLogger.logSoftException( - TAG, new ReactNoCrashSoftException(method + ": " + message)); + TAG, new ReactNoCrashSoftException(method + ": " + message, throwable)); + return; } + + ReactSoftExceptionLogger.logSoftException( + TAG, new ReactNoCrashSoftException(method + ": " + message)); } private Task callWithExistingReactInstance( From 305c2811cf990ac7d4beaf918e88e27df3c45e26 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Thu, 14 Mar 2024 10:33:47 -0700 Subject: [PATCH 204/361] Implement native `console` object in RuntimeTarget (#43456) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43456 Changelog: [Internal] Implements the [WHATWG `console` spec](https://console.spec.whatwg.org/) directly in `RuntimeTarget`, based on the Hermes-powered `addConsoleMessage` method first used in D54494298. Benefits: * This allows the console API to work independently of the polyfill shipped in RN, including very early during JS execution. * It also opens the door to better stack traces (once we start reporting those) and richer functionality in the `console` object itself. Reviewed By: robhogan Differential Revision: D54826073 fbshipit-source-id: d5b0bd004bf35c2fce91742ae84ea86225ec1c61 --- .../chrome/HermesRuntimeTargetDelegate.cpp | 3 + .../jsinspector-modern/RuntimeTarget.cpp | 69 +-- .../RuntimeTargetConsole.cpp | 447 ++++++++++++++++++ 3 files changed, 451 insertions(+), 68 deletions(-) create mode 100644 packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp diff --git a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp index c73867a0fdbf91..40963367b87fb8 100644 --- a/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp +++ b/packages/react-native/ReactCommon/hermes/inspector-modern/chrome/HermesRuntimeTargetDelegate.cpp @@ -125,6 +125,9 @@ class HermesRuntimeTargetDelegate::Impl final : public RuntimeTargetDelegate { case ConsoleAPIType::kTimeEnd: type = HermesConsoleAPIType::kTimeEnd; break; + case ConsoleAPIType::kCount: + type = HermesConsoleAPIType::kCount; + break; default: throw std::logic_error{"Unknown console message type"}; } diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp index 797d79de65fbba..ecee63a5d5f571 100644 --- a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTarget.cpp @@ -34,77 +34,10 @@ RuntimeTarget::RuntimeTarget( jsExecutor_(jsExecutor) {} void RuntimeTarget::installGlobals() { + // NOTE: RuntimeTarget::installConsoleHandler is in RuntimeTargetConsole.cpp installConsoleHandler(); } -void RuntimeTarget::installConsoleHandler() { - jsExecutor_([selfWeak = weak_from_this(), - selfExecutor = executorFromThis()](jsi::Runtime& runtime) { - // TODO(moti): Switch from implementing __inspectorLog to directly - // installing a `console` object. - runtime.global().setProperty( - runtime, - "__inspectorLog", - jsi::Function::createFromHostFunction( - runtime, - jsi::PropNameID::forAscii(runtime, "__inspectorLog"), - 4, - [selfWeak, selfExecutor]( - jsi::Runtime& rt, - const jsi::Value& /*thisVal*/, - const jsi::Value* args, - size_t count) { - if (count < 4) { - throw jsi::JSError( - rt, - "__inspectorLog requires at least 4 arguments: logLevel, str, args, framesToSkip"); - } - std::chrono::time_point timestamp = - std::chrono::system_clock::now(); - std::string level = args[0].asString(rt).utf8(rt); - ConsoleAPIType type = ConsoleAPIType::kLog; - if (level == "debug") { - type = ConsoleAPIType::kDebug; - } else if (level == "log") { - type = ConsoleAPIType::kLog; - } else if (level == "warning") { - type = ConsoleAPIType::kWarning; - } else if (level == "error") { - type = ConsoleAPIType::kError; - } - // NOTE: args[1] is the processed string message - ignore it. - jsi::Array argsArray = args[2].asObject(rt).asArray(rt); - std::vector argsVec; - for (size_t i = 0, length = argsArray.length(rt); i != length; - ++i) { - argsVec.emplace_back(argsArray.getValueAtIndex(rt, i)); - } - // TODO(moti): Handle framesToSkip in some way. Note that the - // runtime doesn't even capture a stack trace at the moment. - ConsoleMessage consoleMessage{ - std::chrono::duration_cast< - std::chrono::duration>( - timestamp.time_since_epoch()) - .count(), - type, - std::move(argsVec)}; - if (auto self = selfWeak.lock()) { - // Q: Why is it safe to use self->delegate_ here? - // A: Because the caller of InspectorTarget::registerRuntime - // is explicitly required to guarantee that the delegate not - // only outlives the target, but also outlives all JS code - // execution that occurs on the JS thread. - self->delegate_.addConsoleMessage( - rt, std::move(consoleMessage)); - // To ensure we never destroy `self` on the JS thread, send - // our shared_ptr back to the inspector thread. - selfExecutor([self = std::move(self)](auto&) { (void)self; }); - } - return jsi::Value::undefined(); - })); - }); -} - std::shared_ptr RuntimeTarget::createAgent( FrontendChannel channel, SessionState& sessionState) { diff --git a/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp new file mode 100644 index 00000000000000..6ac0b02fad9fc4 --- /dev/null +++ b/packages/react-native/ReactCommon/jsinspector-modern/RuntimeTargetConsole.cpp @@ -0,0 +1,447 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include +#include + +using namespace facebook::jsi; +using namespace std::string_literals; + +namespace facebook::react::jsinspector_modern { + +namespace { + +struct ConsoleState { + /** + * https://console.spec.whatwg.org/#counting + */ + std::unordered_map countMap; + + /** + * https://console.spec.whatwg.org/#timing + */ + std::unordered_map timerTable; + + ConsoleState() = default; + ConsoleState(const ConsoleState&) = delete; + ConsoleState& operator=(const ConsoleState&) = delete; + ConsoleState(ConsoleState&&) = delete; + ConsoleState& operator=(ConsoleState&&) = delete; + ~ConsoleState() = default; +}; + +/** + * `console` methods that have no behaviour other than emitting a + * Runtime.consoleAPICalled message. + */ +constexpr const std::pair + kForwardingConsoleMethods[] = { + {"clear", ConsoleAPIType::kClear}, + {"debug", ConsoleAPIType::kDebug}, + {"dir", ConsoleAPIType::kDir}, + {"dirxml", ConsoleAPIType::kDirXML}, + {"error", ConsoleAPIType::kError}, + {"group", ConsoleAPIType::kStartGroup}, + {"groupCollapsed", ConsoleAPIType::kStartGroupCollapsed}, + {"groupEnd", ConsoleAPIType::kEndGroup}, + {"info", ConsoleAPIType::kInfo}, + {"log", ConsoleAPIType::kLog}, + {"table", ConsoleAPIType::kTable}, + {"trace", ConsoleAPIType::kTrace}, + {"warn", ConsoleAPIType::kWarning}, +}; + +/** + * JS `Object.create()` + */ +jsi::Object objectCreate(jsi::Runtime& runtime, jsi::Value prototype) { + auto objectGlobal = runtime.global().getPropertyAsObject(runtime, "Object"); + auto createFn = objectGlobal.getPropertyAsFunction(runtime, "create"); + return createFn.callWithThis(runtime, objectGlobal, prototype) + .getObject(runtime); +} + +bool toBoolean(jsi::Runtime& runtime, const jsi::Value& val) { + // Based on Operations.cpp:toBoolean in the Hermes VM. + if (val.isUndefined() || val.isNull()) { + return false; + } + if (val.isBool()) { + return val.getBool(); + } + if (val.isNumber()) { + double m = val.getNumber(); + return m != 0 && !std::isnan(m); + } + if (val.isSymbol() || val.isObject()) { + return true; + } + if (val.isString()) { + std::string s = val.getString(runtime).utf8(runtime); + return !s.empty(); + } + assert(false && "All cases should be covered"); + return false; +} + +/** + * Get the current time in milliseconds as a double. + */ +double getTimestampMs() { + return std::chrono::duration_cast>( + std::chrono::system_clock::now().time_since_epoch()) + .count(); +} + +} // namespace + +void RuntimeTarget::installConsoleHandler() { + jsExecutor_([selfWeak = weak_from_this(), + selfExecutor = executorFromThis()](jsi::Runtime& runtime) { + jsi::Value consolePrototype = jsi::Value::null(); + auto originalConsoleVal = runtime.global().getProperty(runtime, "console"); + std::shared_ptr originalConsole; + if (originalConsoleVal.isObject()) { + originalConsole = + std::make_shared(originalConsoleVal.getObject(runtime)); + consolePrototype = std::move(originalConsoleVal); + } else { + consolePrototype = jsi::Object(runtime); + } + auto console = objectCreate(runtime, std::move(consolePrototype)); + auto state = std::make_shared(); + + /** + * An executor that runs synchronously and provides a safe reference to our + * RuntimeTargetDelegate for use on the JS thread. + * \see RuntimeTargetDelegate for information on which methods are safe to + * call on the JS thread. + * \warning The callback will not run if the RuntimeTarget has been + * destroyed. + */ + auto delegateExecutorSync = [selfWeak, selfExecutor](auto&& func) { + if (auto self = selfWeak.lock()) { + // Q: Why is it safe to use self->delegate_ here? + // A: Because the caller of InspectorTarget::registerRuntime + // is explicitly required to guarantee that the delegate not + // only outlives the target, but also outlives all JS code + // execution that occurs on the JS thread. + func(self->delegate_); + // To ensure we never destroy `self` on the JS thread, send + // our shared_ptr back to the inspector thread. + selfExecutor([self = std::move(self)](auto&) { (void)self; }); + } + }; + + /** + * Call \param innerFn and forward any arguments to the original console + * method named \param methodName, if possible. + */ + auto forwardToOriginalConsole = [originalConsole, delegateExecutorSync]( + const char* methodName, + auto&& innerFn) { + return [originalConsole, + delegateExecutorSync, + innerFn = std::forward(innerFn), + methodName]( + jsi::Runtime& runtime, + const jsi::Value& thisVal, + const jsi::Value* args, + size_t count) mutable { + jsi::Value retVal = innerFn(runtime, thisVal, args, count); + if (originalConsole) { + auto val = originalConsole->getProperty(runtime, methodName); + if (val.isObject()) { + auto obj = val.getObject(runtime); + if (obj.isFunction(runtime)) { + auto func = obj.getFunction(runtime); + func.callWithThis(runtime, *originalConsole, args, count); + } + } + } + return retVal; + }; + }; + + /** + * Install a console method with the given name and body. The body receives + * the usual JSI host function parameters plus a ConsoleState reference, a + * reference to the RuntimeTargetDelegate for sending messages to the + * client, and the timestamp of the call. After the body runs (or is skipped + * due to RuntimeTarget having been destroyed), the method of the same name + * is also called on originalConsole (if it exists). + */ + auto installConsoleMethod = + [&](const char* methodName, + std::function&& body) { + console.setProperty( + runtime, + methodName, + jsi::Function::createFromHostFunction( + runtime, + jsi::PropNameID::forAscii(runtime, methodName), + 0, + forwardToOriginalConsole( + methodName, + [body = std::move(body), state, delegateExecutorSync]( + jsi::Runtime& runtime, + const jsi::Value& /*thisVal*/, + const jsi::Value* args, + size_t count) mutable { + auto timestampMs = getTimestampMs(); + delegateExecutorSync( + [&runtime, + args, + count, + body = std::move(body), + state, + timestampMs](auto& runtimeTargetDelegate) { + body( + runtime, + args, + count, + runtimeTargetDelegate, + *state, + timestampMs); + }); + return jsi::Value::undefined(); + }))); + }; + + /** + * console.count + */ + installConsoleMethod( + "count", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& state, + auto timestampMs) { + std::string label = "default"; + if (count > 0 && !args[0].isUndefined()) { + label = args[0].toString(runtime).utf8(runtime); + } + auto it = state.countMap.find(label); + if (it == state.countMap.end()) { + it = state.countMap.insert({label, 1}).first; + } else { + it->second++; + } + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, label + ": "s + std::to_string(it->second))); + runtimeTargetDelegate.addConsoleMessage( + runtime, {timestampMs, ConsoleAPIType::kCount, std::move(vec)}); + }); + + /** + * console.countReset + */ + installConsoleMethod( + "countReset", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& state, + auto timestampMs) { + std::string label = "default"; + if (count > 0 && !args[0].isUndefined()) { + label = args[0].toString(runtime).utf8(runtime); + } + auto it = state.countMap.find(label); + if (it == state.countMap.end()) { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, "Count for '"s + label + "' does not exist")); + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, ConsoleAPIType::kWarning, std::move(vec)}); + } else { + it->second = 0; + } + }); + + /** + * console.time + */ + installConsoleMethod( + "time", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& state, + auto timestampMs) { + std::string label = "default"; + if (count > 0 && !args[0].isUndefined()) { + label = args[0].toString(runtime).utf8(runtime); + } + auto it = state.timerTable.find(label); + if (it == state.timerTable.end()) { + state.timerTable.insert({label, timestampMs}); + } else { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, "Timer '"s + label + "' already exists")); + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, ConsoleAPIType::kWarning, std::move(vec)}); + } + }); + + /** + * console.timeEnd + */ + installConsoleMethod( + "timeEnd", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& state, + auto timestampMs) { + std::string label = "default"; + if (count > 0 && !args[0].isUndefined()) { + label = args[0].toString(runtime).utf8(runtime); + } + auto it = state.timerTable.find(label); + if (it == state.timerTable.end()) { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, "Timer '"s + label + "' does not exist")); + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, ConsoleAPIType::kWarning, std::move(vec)}); + } else { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, + label + ": "s + std::to_string(timestampMs - it->second) + + " ms")); + state.timerTable.erase(it); + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, ConsoleAPIType::kTimeEnd, std::move(vec)}); + } + }); + + /** + * console.timeLog + */ + installConsoleMethod( + "timeLog", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& state, + auto timestampMs) { + std::string label = "default"; + if (count > 0 && !args[0].isUndefined()) { + label = args[0].toString(runtime).utf8(runtime); + } + auto it = state.timerTable.find(label); + if (it == state.timerTable.end()) { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, "Timer '"s + label + "' does not exist")); + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, ConsoleAPIType::kWarning, std::move(vec)}); + } else { + std::vector vec; + vec.emplace_back(jsi::String::createFromUtf8( + runtime, + label + ": "s + std::to_string(timestampMs - it->second) + + " ms")); + if (count > 1) { + for (size_t i = 1; i != count; ++i) { + vec.emplace_back(runtime, args[i]); + } + } + runtimeTargetDelegate.addConsoleMessage( + runtime, {timestampMs, ConsoleAPIType::kLog, std::move(vec)}); + } + }); + + /** + * console.assert + */ + installConsoleMethod( + "assert", + [](jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& /*state*/, + auto timestampMs) { + if (count >= 1 && toBoolean(runtime, args[0])) { + return; + } + std::deque data; + + if (count > 1) { + for (size_t i = 1; i != count; ++i) { + data.emplace_back(runtime, args[i]); + } + } + if (data.empty()) { + data.emplace_back( + jsi::String::createFromUtf8(runtime, "Assertion failed")); + } else if (data.front().isString()) { + data.front() = jsi::String::createFromUtf8( + runtime, + "Assertion failed: "s + + data.front().asString(runtime).utf8(runtime)); + } else { + data.emplace_front( + jsi::String::createFromUtf8(runtime, "Assertion failed")); + } + runtimeTargetDelegate.addConsoleMessage( + runtime, + {timestampMs, + ConsoleAPIType::kAssert, + std::vector( + make_move_iterator(data.begin()), + make_move_iterator(data.end()))}); + }); + + for (auto& [name, type] : kForwardingConsoleMethods) { + installConsoleMethod( + name, + [type = type]( + jsi::Runtime& runtime, + const jsi::Value* args, + size_t count, + RuntimeTargetDelegate& runtimeTargetDelegate, + ConsoleState& /*state*/, + auto timestampMs) { + std::vector argsVec; + for (size_t i = 0; i != count; ++i) { + argsVec.emplace_back(runtime, args[i]); + } + runtimeTargetDelegate.addConsoleMessage( + runtime, {timestampMs, type, std::move(argsVec)}); + }); + } + + runtime.global().setProperty(runtime, "console", console); + }); +} + +} // namespace facebook::react::jsinspector_modern From 9700540bec67d221f72fd1d17e918538ffca7a8a Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Thu, 14 Mar 2024 11:10:54 -0700 Subject: [PATCH 205/361] Bring back the UNSET constant to TextAttributeProps (#43491) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43491 This diff brings back the `UNSET` constant to `TextAttributeProps`. The removal of this constant was an unnecessary breaking change, that has broken several third-party libraries. Changelog: [Android][Fixed] - Bring back the UNSET constant to TextAttributeProps. Reviewed By: fabriziocucci Differential Revision: D54899524 fbshipit-source-id: 368bde77d43f310fd458537d0191d09174fa5167 --- packages/react-native/ReactAndroid/api/ReactAndroid.api | 1 + .../java/com/facebook/react/views/text/TextAttributeProps.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index d43f2379183778..cb71470eead4dd 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -7083,6 +7083,7 @@ public class com/facebook/react/views/text/TextAttributeProps : com/facebook/rea public static final field TA_KEY_TEXT_SHADOW_OFFSET_DY S public static final field TA_KEY_TEXT_SHADOW_RADIUS S public static final field TA_KEY_TEXT_TRANSFORM S + public static final field UNSET I protected field mAccessibilityRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$AccessibilityRole; protected field mAllowFontScaling Z protected field mBackgroundColor I diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java index 25791e00679b34..202734f3795984 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java @@ -62,6 +62,8 @@ public class TextAttributeProps implements EffectiveTextAttributeProvider { public static final short TA_KEY_ROLE = 26; public static final short TA_KEY_TEXT_TRANSFORM = 27; + public static final int UNSET = -1; + private static final String PROP_SHADOW_OFFSET = "textShadowOffset"; private static final String PROP_SHADOW_OFFSET_WIDTH = "width"; private static final String PROP_SHADOW_OFFSET_HEIGHT = "height"; From b14f7d58e3537b9bfa2638d1d71ec3dc908f4b8d Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Thu, 14 Mar 2024 12:10:57 -0700 Subject: [PATCH 206/361] Support onKeyDown in Bridgeless (#43466) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43466 Implement `onKeyDown` in Bridgeless by adding it to ReactHostImpl Changelog: [Android][Breaking] Implement `onKeyDown` in Bridgeless Reviewed By: cortinico Differential Revision: D54870966 fbshipit-source-id: 0f8e48b29679f1bca92f6ac7b6ebf1592cdc5dac --- .../react-native/ReactAndroid/api/ReactAndroid.api | 1 + .../com/facebook/react/ReactActivityDelegate.java | 12 +----------- .../main/java/com/facebook/react/ReactDelegate.java | 13 +++++++++++++ 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index cb71470eead4dd..a65138321a8db8 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -154,6 +154,7 @@ public class com/facebook/react/ReactDelegate { public fun onHostDestroy ()V public fun onHostPause ()V public fun onHostResume ()V + public fun onKeyDown (ILandroid/view/KeyEvent;)Z public fun onNewIntent (Landroid/content/Intent;)Z public fun onWindowFocusChanged (Z)V public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 7079133f7d5149..45d6877405a3e6 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -147,17 +147,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { } public boolean onKeyDown(int keyCode, KeyEvent event) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: support onKeyDown - } else { - if (getReactNativeHost().hasInstance() - && getReactNativeHost().getUseDeveloperSupport() - && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { - event.startTracking(); - return true; - } - } - return false; + return mReactDelegate.onKeyDown(keyCode, event); } public boolean onKeyUp(int keyCode, KeyEvent event) { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 1cda3ab15411ce..78f34a177cdd60 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -184,6 +184,19 @@ public void onConfigurationChanged(Configuration newConfig) { } } + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD + && ((ReactFeatureFlags.enableBridgelessArchitecture + && mReactHost != null + && mReactHost.getDevSupportManager() != null) + || (getReactNativeHost().hasInstance() + && getReactNativeHost().getUseDeveloperSupport()))) { + event.startTracking(); + return true; + } + return false; + } + public void loadApp() { loadApp(mMainComponentName); } From f345fcf3e8331b76a72989645bd60b82ba9aa19a Mon Sep 17 00:00:00 2001 From: Arushi Kesarwani Date: Thu, 14 Mar 2024 12:10:57 -0700 Subject: [PATCH 207/361] Support onKeyLongPress in Bridgeless (#43472) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43472 Implement `onKeyLongPress` in Bridgeless Changelog: [Android][Breaking] Implement onKeyLongPress in Bridgeless Reviewed By: cortinico Differential Revision: D54876052 fbshipit-source-id: 88d572eab087d913205bdfa02dba96b169066393 --- .../ReactAndroid/api/ReactAndroid.api | 1 + .../facebook/react/ReactActivityDelegate.java | 12 +----------- .../java/com/facebook/react/ReactDelegate.java | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactAndroid/api/ReactAndroid.api b/packages/react-native/ReactAndroid/api/ReactAndroid.api index a65138321a8db8..28f012e0b2cacf 100644 --- a/packages/react-native/ReactAndroid/api/ReactAndroid.api +++ b/packages/react-native/ReactAndroid/api/ReactAndroid.api @@ -155,6 +155,7 @@ public class com/facebook/react/ReactDelegate { public fun onHostPause ()V public fun onHostResume ()V public fun onKeyDown (ILandroid/view/KeyEvent;)Z + public fun onKeyLongPress (I)Z public fun onNewIntent (Landroid/content/Intent;)Z public fun onWindowFocusChanged (Z)V public fun shouldShowDevMenuOrReload (ILandroid/view/KeyEvent;)Z diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java index 45d6877405a3e6..54022ed27d5918 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java @@ -155,17 +155,7 @@ public boolean onKeyUp(int keyCode, KeyEvent event) { } public boolean onKeyLongPress(int keyCode, KeyEvent event) { - if (ReactFeatureFlags.enableBridgelessArchitecture) { - // TODO T156475655: support onKeyLongPress - } else { - if (getReactNativeHost().hasInstance() - && getReactNativeHost().getUseDeveloperSupport() - && keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { - getReactNativeHost().getReactInstanceManager().showDevOptionsDialog(); - return true; - } - } - return false; + return mReactDelegate.onKeyLongPress(keyCode); } public boolean onBackPressed() { diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 78f34a177cdd60..0e4584f54222b8 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -197,6 +197,23 @@ && getReactNativeHost().getUseDeveloperSupport()))) { return false; } + public boolean onKeyLongPress(int keyCode) { + if (keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD) { + if (ReactFeatureFlags.enableBridgelessArchitecture + && mReactHost != null + && mReactHost.getDevSupportManager() != null) { + mReactHost.getDevSupportManager().showDevOptionsDialog(); + return true; + } else { + if (getReactNativeHost().hasInstance() && getReactNativeHost().getUseDeveloperSupport()) { + getReactNativeHost().getReactInstanceManager().showDevOptionsDialog(); + return true; + } + } + } + return false; + } + public void loadApp() { loadApp(mMainComponentName); } From a2d277f740d8ee95137d42679a1ffd872962a108 Mon Sep 17 00:00:00 2001 From: Pieter De Baets Date: Thu, 14 Mar 2024 12:21:47 -0700 Subject: [PATCH 208/361] Flag missing DefaultHardwareBackBtnHandler interface in bridgeless too (#43487) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43487 Inconsistent between bridge and bridgeless, but if you forget to implement this interface, ReactDelegate will silently not do anything in bridgeless. Changelog: [Android] Enforce Activities using ReactDelegate implement DefaultHardwareBackBtnHandler. Reviewed By: arushikesarwani94 Differential Revision: D54900747 fbshipit-source-id: 5dd31d4f81e4ec37e1c3ee906be836a8a9c6a944 --- .../com/facebook/react/ReactDelegate.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java index 0e4584f54222b8..d18226b58e712f 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/ReactDelegate.java @@ -82,20 +82,17 @@ public ReactDelegate( } public void onHostResume() { + if (!(mActivity instanceof DefaultHardwareBackBtnHandler)) { + throw new ClassCastException( + "Host Activity does not implement DefaultHardwareBackBtnHandler"); + } if (ReactFeatureFlags.enableBridgelessArchitecture) { - if (mActivity instanceof DefaultHardwareBackBtnHandler) { - mReactHost.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity); - } + mReactHost.onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity); } else { if (getReactNativeHost().hasInstance()) { - if (mActivity instanceof DefaultHardwareBackBtnHandler) { - getReactNativeHost() - .getReactInstanceManager() - .onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity); - } else { - throw new ClassCastException( - "Host Activity does not implement DefaultHardwareBackBtnHandler"); - } + getReactNativeHost() + .getReactInstanceManager() + .onHostResume(mActivity, (DefaultHardwareBackBtnHandler) mActivity); } } } From 7af288e523c899d1ca8b55e21d9ae8939d114d4d Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Thu, 14 Mar 2024 12:44:44 -0700 Subject: [PATCH 209/361] Lazy-init HermesRuntimeTargetDelegate Summary: Changelog: [Internal] We are currently eagerly constructing a `HermesRuntimeTargetDelegate` regardless of whether the Fusebox feature flags are enabled. This can interfere with the legacy CDP backend. Instead, let's lazily construct the target delegate in a code path that only runs when the modern backend is in use. bypass-github-export-checks Reviewed By: rozele Differential Revision: D54907887 fbshipit-source-id: 7dc13506739866ea6690ed21d03d91ad24ef68c5 --- .../hermes/executor/HermesExecutorFactory.cpp | 8 +++++--- .../hermes/executor/HermesExecutorFactory.h | 4 +++- .../react/runtime/hermes/HermesInstance.cpp | 10 +++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp index 56a8398f0b544a..8ee40df6785a6e 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.cpp @@ -253,12 +253,14 @@ HermesExecutor::HermesExecutor( HermesRuntime& hermesRuntime) : JSIExecutor(runtime, delegate, timeoutInvoker, runtimeInstaller), runtime_(runtime), - targetDelegate_{ - std::shared_ptr(runtime_, &hermesRuntime)} {} + hermesRuntime_(runtime_, &hermesRuntime) {} jsinspector_modern::RuntimeTargetDelegate& HermesExecutor::getRuntimeTargetDelegate() { - return targetDelegate_; + if (!targetDelegate_) { + targetDelegate_.emplace(hermesRuntime_); + } + return *targetDelegate_; } } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h index 4056d42ef5259b..ea370876d7af42 100644 --- a/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h +++ b/packages/react-native/ReactCommon/hermes/executor/HermesExecutorFactory.h @@ -61,7 +61,9 @@ class HermesExecutor : public JSIExecutor { private: JSIScopedTimeoutInvoker timeoutInvoker_; std::shared_ptr runtime_; - jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_; + std::shared_ptr hermesRuntime_; + std::optional + targetDelegate_; }; } // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp index 3a32d353ce851c..e5ac3cb5a8f5bd 100644 --- a/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp +++ b/packages/react-native/ReactCommon/react/runtime/hermes/HermesInstance.cpp @@ -95,7 +95,7 @@ class DecoratedRuntime : public jsi::RuntimeDecorator { class HermesJSRuntime : public JSRuntime { public: HermesJSRuntime(std::unique_ptr runtime) - : runtime_(std::move(runtime)), targetDelegate_{runtime_} {} + : runtime_(std::move(runtime)) {} jsi::Runtime& getRuntime() noexcept override { return *runtime_; @@ -103,12 +103,16 @@ class HermesJSRuntime : public JSRuntime { jsinspector_modern::RuntimeTargetDelegate& getRuntimeTargetDelegate() override { - return targetDelegate_; + if (!targetDelegate_) { + targetDelegate_.emplace(runtime_); + } + return *targetDelegate_; } private: std::shared_ptr runtime_; - jsinspector_modern::HermesRuntimeTargetDelegate targetDelegate_; + std::optional + targetDelegate_; }; std::unique_ptr HermesInstance::createJSRuntime( From b3a8eba5a17ab1d38846123fb4def8dedb187d21 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Thu, 14 Mar 2024 13:39:14 -0700 Subject: [PATCH 210/361] merge BatchedEventQueue into EventQueue (#43438) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43438 changelog: [internal] EventQueue can now be merged with BatchedEventQueue since there isn't anything else subclassing it. Reviewed By: javache Differential Revision: D54687859 fbshipit-source-id: f646583db0e46789b667f8d79d24d0cf9d7fc00c --- .../react/renderer/core/BatchedEventQueue.cpp | 20 ------------- .../react/renderer/core/BatchedEventQueue.h | 28 ------------------- .../react/renderer/core/EventDispatcher.cpp | 13 ++++----- .../react/renderer/core/EventDispatcher.h | 4 +-- .../react/renderer/core/EventQueue.cpp | 4 +++ .../react/renderer/core/EventQueue.h | 3 +- 6 files changed, 13 insertions(+), 59 deletions(-) delete mode 100644 packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.cpp delete mode 100644 packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.h diff --git a/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.cpp b/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.cpp deleted file mode 100644 index 0a9467eb5540b8..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#include "BatchedEventQueue.h" - -namespace facebook::react { - -BatchedEventQueue::BatchedEventQueue( - EventQueueProcessor eventProcessor, - std::unique_ptr eventBeat) - : EventQueue(std::move(eventProcessor), std::move(eventBeat)) {} - -void BatchedEventQueue::onEnqueue() const { - eventBeat_->request(); -} -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.h b/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.h deleted file mode 100644 index bc3e5a669d7eeb..00000000000000 --- a/packages/react-native/ReactCommon/react/renderer/core/BatchedEventQueue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma once - -#include -#include - -namespace facebook::react { - -/* - * Event Queue that dispatches event in batches synchronizing them with - * an Event Beat. - */ -class BatchedEventQueue final : public EventQueue { - public: - BatchedEventQueue( - EventQueueProcessor eventProcessor, - std::unique_ptr eventBeat); - - void onEnqueue() const override; -}; - -} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp index 60fdd79c02a3fe..c6b98efd8201bd 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.cpp @@ -10,7 +10,7 @@ #include #include "EventLogger.h" -#include "BatchedEventQueue.h" +#include "EventQueue.h" #include "RawEvent.h" namespace facebook::react { @@ -20,9 +20,8 @@ EventDispatcher::EventDispatcher( const EventBeat::Factory& synchonousEventBeatFactory, const EventBeat::Factory& asynchronousEventBeatFactory, const EventBeat::SharedOwnerBox& ownerBox) - : asynchronousBatchedQueue_(std::make_unique( - eventProcessor, - asynchronousEventBeatFactory(ownerBox))) {} + : eventQueue_( + EventQueue(eventProcessor, asynchronousEventBeatFactory(ownerBox))) {} void EventDispatcher::dispatchEvent(RawEvent&& rawEvent) const { // Allows the event listener to interrupt default event dispatch @@ -34,11 +33,11 @@ void EventDispatcher::dispatchEvent(RawEvent&& rawEvent) const { if (eventLogger != nullptr) { rawEvent.loggingTag = eventLogger->onEventStart(rawEvent.type); } - asynchronousBatchedQueue_->enqueueEvent(std::move(rawEvent)); + eventQueue_.enqueueEvent(std::move(rawEvent)); } void EventDispatcher::dispatchStateUpdate(StateUpdate&& stateUpdate) const { - asynchronousBatchedQueue_->enqueueStateUpdate(std::move(stateUpdate)); + eventQueue_.enqueueStateUpdate(std::move(stateUpdate)); } void EventDispatcher::dispatchUniqueEvent(RawEvent&& rawEvent) const { @@ -46,7 +45,7 @@ void EventDispatcher::dispatchUniqueEvent(RawEvent&& rawEvent) const { if (eventListeners_.willDispatchEvent(rawEvent)) { return; } - asynchronousBatchedQueue_->enqueueUniqueEvent(std::move(rawEvent)); + eventQueue_.enqueueUniqueEvent(std::move(rawEvent)); } void EventDispatcher::addListener( diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h index e9c6ac39f6624e..3bc5fce8f69073 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventDispatcher.h @@ -7,9 +7,9 @@ #pragma once -#include #include #include +#include #include #include @@ -62,7 +62,7 @@ class EventDispatcher { const std::shared_ptr& listener) const; private: - std::unique_ptr asynchronousBatchedQueue_; + EventQueue eventQueue_; mutable EventListenerContainer eventListeners_; }; diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventQueue.cpp b/packages/react-native/ReactCommon/react/renderer/core/EventQueue.cpp index 099e529e48dd56..cef50c68380d69 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventQueue.cpp +++ b/packages/react-native/ReactCommon/react/renderer/core/EventQueue.cpp @@ -75,6 +75,10 @@ void EventQueue::enqueueStateUpdate(StateUpdate&& stateUpdate) const { onEnqueue(); } +void EventQueue::onEnqueue() const { + eventBeat_->request(); +} + void EventQueue::onBeat(jsi::Runtime& runtime) const { flushStateUpdates(); flushEvents(runtime); diff --git a/packages/react-native/ReactCommon/react/renderer/core/EventQueue.h b/packages/react-native/ReactCommon/react/renderer/core/EventQueue.h index a4bd7b087e9e61..14e7c18d0b00ed 100644 --- a/packages/react-native/ReactCommon/react/renderer/core/EventQueue.h +++ b/packages/react-native/ReactCommon/react/renderer/core/EventQueue.h @@ -28,7 +28,6 @@ class EventQueue { EventQueue( EventQueueProcessor eventProcessor, std::unique_ptr eventBeat); - virtual ~EventQueue() = default; /* * Enqueues and (probably later) dispatch a given event. @@ -55,7 +54,7 @@ class EventQueue { * Override in subclasses to trigger beat `request` and/or beat `induce`. * Default implementation does nothing. */ - virtual void onEnqueue() const = 0; + void onEnqueue() const; void onBeat(jsi::Runtime& runtime) const; void flushEvents(jsi::Runtime& runtime) const; From 5c34ce05876fe645cd49d9c425a379056629ccb3 Mon Sep 17 00:00:00 2001 From: Dmitry Rykun Date: Thu, 14 Mar 2024 19:24:35 -0700 Subject: [PATCH 211/361] Fix RNTester OSS build (#43496) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43496 This diff adds another sub-sub-spec to React-Fabric pod to fix import paths in `textinput`. Changelog: [Internal] Reviewed By: philIip, rshest Differential Revision: D54918454 fbshipit-source-id: 3949f8b8b201157f4c9eb256f3eb5bd5d66bc228 --- .../react-native/ReactCommon/React-Fabric.podspec | 13 ++++++++++--- .../components/iostextinput/TextInputProps.h | 2 +- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/react-native/ReactCommon/React-Fabric.podspec b/packages/react-native/ReactCommon/React-Fabric.podspec index b67b999bf9c7da..6662a301291ec8 100644 --- a/packages/react-native/ReactCommon/React-Fabric.podspec +++ b/packages/react-native/ReactCommon/React-Fabric.podspec @@ -198,15 +198,22 @@ Pod::Spec.new do |s| end - ss.subspec "textinput" do |sss| + ss.subspec "iostextinput" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags - sss.source_files = "react/renderer/components/textinput/**/*.{m,mm,cpp,h}" - sss.exclude_files = "react/renderer/components/textinput/platform/android" + sss.source_files = "react/renderer/components/textinput/platform/ios/**/*.{m,mm,cpp,h}" sss.header_dir = "react/renderer/components/iostextinput" end + ss.subspec "textinput" do |sss| + sss.dependency folly_dep_name, folly_version + sss.compiler_flags = folly_compiler_flags + sss.source_files = "react/renderer/components/textinput/*.{m,mm,cpp,h}" + sss.header_dir = "react/renderer/components/textinput" + + end + ss.subspec "unimplementedview" do |sss| sss.dependency folly_dep_name, folly_version sss.compiler_flags = folly_compiler_flags diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h index 7c517713199bc4..ea1583c917136c 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/platform/ios/react/renderer/components/iostextinput/TextInputProps.h @@ -9,9 +9,9 @@ #include #include -#include #include #include +#include #include #include #include From a9e6759bb5d8f08c444b7a324c4488b9e5f2ed1b Mon Sep 17 00:00:00 2001 From: Janic Duplessis Date: Thu, 14 Mar 2024 20:00:56 -0700 Subject: [PATCH 212/361] Fix maintainVisibleContentPosition on Android during momentum scroll (#43425) Summary: When using maintainVisibleContentPosition (mvcp) on Android it doesn't work properly when items are added during a momentum scroll. This happens because the android scrollview momentum scroll animation overrides the scroll position that the mvcp implementation sets [here](https://github.com/facebook/react-native/blob/2d547a3252b328251e49dabfeec85f8d46c85411/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/MaintainVisibleScrollPositionHelper.java#L132). To fix this we need to cancel the momentum scroll animation, update the scroll position then restart the scroll animation with the previous animation remaining momentum. ## Changelog: [ANDROID] [FIXED] - Fix maintainVisibleContentPosition during momentum scroll Pull Request resolved: https://github.com/facebook/react-native/pull/43425 Test Plan: Tested in RNTester on Android with both vertical and horizontal scrollviews using the following code: ```ts // packages/rn-tester/js/RNTesterAppShared.js import { Button, SafeAreaView, ScrollView, Text, View, } from 'react-native'; import React, {useLayoutEffect, useRef, useState} from 'react'; const generateUniqueKey = () => `_${Math.random().toString(36).substr(2, 9)}` const initialData = Array.from(Array(100).keys()).map(n => ({ id: generateUniqueKey(), value: n, })) function ListItem({item}) { const color = `hsl(${item.value * 10}, 75%, 85%)`; return ( List item: {item.value} ); } export default function FlatListRepro() { const numToAdd = 10; const [numbers, setNumbers] = useState(initialData); const ref = useRef(); const addAbove = () => { setNumbers(prev => { const additionalNumbers = Array.from(Array(numToAdd).keys()) .map(n => ({ id: generateUniqueKey(), value: prev[0].value - n - 1, })) .reverse(); return additionalNumbers.concat(prev); }); }; useLayoutEffect(() => { ref.current.scrollTo({y: numbers.length * 100, animated: false}); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return (