react-native-windows 0.82.1 → 0.83.0-preview.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.flowconfig +2 -7
- package/Libraries/Animated/components/AnimatedFlatList.js +5 -3
- package/Libraries/Animated/components/AnimatedImage.js +4 -3
- package/Libraries/Animated/components/AnimatedSectionList.js +2 -2
- package/Libraries/Animated/components/AnimatedText.js +7 -3
- package/Libraries/Animated/components/AnimatedView.js +3 -2
- package/Libraries/Animated/createAnimatedComponent.js +24 -12
- package/Libraries/Animated/nodes/AnimatedColor.js +26 -10
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.js +43 -15
- package/Libraries/Components/AccessibilityInfo/AccessibilityInfo.windows.js +43 -15
- package/Libraries/Components/ActivityIndicator/ActivityIndicator.d.ts +2 -2
- package/Libraries/Components/DrawerAndroid/DrawerLayoutAndroid.d.ts +2 -2
- package/Libraries/Components/Glyph/Glyph.js +4 -1
- package/Libraries/Components/ProgressBarAndroid/ProgressBarAndroid.d.ts +2 -2
- package/Libraries/Components/RefreshControl/RefreshControl.d.ts +3 -3
- package/Libraries/Components/SafeAreaView/SafeAreaView.d.ts +2 -2
- package/Libraries/Components/ScrollView/ScrollView.js +1 -0
- package/Libraries/Components/ScrollView/ScrollView.windows.js +1 -0
- package/Libraries/Components/ScrollView/ScrollViewStickyHeader.js +6 -6
- package/Libraries/Components/Switch/Switch.d.ts +2 -2
- package/Libraries/Components/Switch/Switch.windows.js +1 -1
- package/Libraries/Components/TextInput/TextInput.d.ts +2 -5
- package/Libraries/Components/TextInput/TextInput.js +6 -0
- package/Libraries/Components/TextInput/TextInput.windows.js +6 -0
- package/Libraries/Components/Touchable/TouchableBounce.js +7 -7
- package/Libraries/Components/Touchable/TouchableBounce.windows.js +7 -7
- package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +1 -1
- package/Libraries/Components/View/ReactNativeStyleAttributes.js +19 -1
- package/Libraries/Components/View/View.d.ts +2 -2
- package/Libraries/Components/View/View.windows.js +0 -1
- package/Libraries/Components/View/ViewNativeComponent.js +13 -1
- package/Libraries/Core/ReactNativeVersion.js +3 -3
- package/Libraries/Core/setUpPerformance.js +2 -0
- package/Libraries/Debugging/DebuggingOverlay.js +14 -14
- package/Libraries/Debugging/DebuggingOverlayRegistry.js +8 -2
- package/Libraries/EventEmitter/RCTDeviceEventEmitter.js +5 -2
- package/Libraries/Image/Image.d.ts +3 -3
- package/Libraries/Image/ImageInjection.js +3 -6
- package/Libraries/Image/ImageTypes.flow.js +3 -7
- package/Libraries/Lists/FlatList.js +8 -8
- package/Libraries/Lists/SectionList.d.ts +5 -1
- package/Libraries/Lists/ViewabilityHelper.js +1 -1
- package/Libraries/Lists/VirtualizedList.js +1 -0
- package/Libraries/LogBox/UI/AnsiHighlight.js +4 -1
- package/Libraries/NativeComponent/BaseViewConfig.android.js +11 -2
- package/Libraries/NativeComponent/NativeComponentRegistry.d.ts +98 -0
- package/Libraries/NativeComponent/NativeComponentRegistry.js +2 -0
- package/Libraries/NativeComponent/NativeComponentRegistryUnstable.js +3 -1
- package/Libraries/NativeComponent/ViewConfigIgnore.windows.js +45 -0
- package/Libraries/Network/RCTNetworking.android.js +3 -1
- package/Libraries/Network/RCTNetworking.ios.js +3 -0
- package/Libraries/Network/RCTNetworking.windows.js +3 -0
- package/Libraries/Network/XMLHttpRequest.js +1 -41
- package/Libraries/Pressability/usePressability.js +14 -3
- package/Libraries/ReactNative/PaperUIManager.windows.js +3 -3
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricPublicInstance.js +20 -82
- package/Libraries/ReactNative/getNativeComponentAttributes.js +12 -0
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +6759 -4478
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +3169 -3119
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +4732 -3535
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +6646 -4070
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +3136 -2825
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +4761 -3312
- package/Libraries/Renderer/shims/ReactNative.js +3 -1
- package/Libraries/Renderer/shims/ReactNativeTypes.js +2 -1
- package/Libraries/Renderer/shims/ReactNativeTypes.windows.js +2 -1
- package/Libraries/StyleSheet/StyleSheetTypes.d.ts +1 -1
- package/Libraries/StyleSheet/StyleSheetTypes.js +44 -0
- package/Libraries/StyleSheet/processBackgroundPosition.js +284 -0
- package/Libraries/StyleSheet/processBackgroundRepeat.js +105 -0
- package/Libraries/StyleSheet/processBackgroundSize.js +104 -0
- package/Libraries/Text/Text.d.ts +2 -2
- package/Libraries/Text/TextNativeComponent.js +10 -0
- package/Libraries/TurboModule/TurboModuleRegistry.js +3 -9
- package/Libraries/Utilities/DevLoadingView.js +14 -6
- package/Libraries/Utilities/HMRClient.js +13 -5
- package/Microsoft.ReactNative/Base/CxxReactIncludes.h +11 -0
- package/Microsoft.ReactNative/CompositionComponentView.idl +2 -0
- package/Microsoft.ReactNative/CompositionHwndHost.idl +1 -0
- package/Microsoft.ReactNative/Fabric/ComponentView.cpp +1 -1
- package/Microsoft.ReactNative/Fabric/ComponentView.h +1 -1
- package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +10 -40
- package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +3 -80
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +45 -12
- package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +8 -0
- package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +61 -74
- package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +4 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +1 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +4 -3
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +2 -1
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.cpp +245 -0
- package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.h +80 -0
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentDescriptor.h +20 -36
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +70 -49
- package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -1
- package/Microsoft.ReactNative/Fabric/Composition/UriImageManager.cpp +5 -0
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +7 -2
- package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +1 -0
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
- package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +1 -1
- package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +20 -94
- package/Microsoft.ReactNative/Modules/LogBoxModule.h +1 -3
- package/Microsoft.ReactNative/Pch/pch.h +2 -0
- package/Microsoft.ReactNative/ReactHost/CrashManager.cpp +5 -0
- package/Microsoft.ReactNative/ReactHost/ReactNativeHeaders.h +1 -0
- package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +0 -41
- package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +0 -11
- package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -3
- package/Microsoft.ReactNative/ReactNativeWin32App.cpp +31 -101
- package/Microsoft.ReactNative/ReactNativeWin32App.h +2 -13
- package/Microsoft.ReactNative/ReactNativeWindow.idl +44 -0
- package/Microsoft.ReactNative.Cxx/AutoDraw.h +9 -1
- package/Microsoft.ReactNative.Cxx/ReactCommon/CallInvoker.h +13 -16
- package/Microsoft.ReactNative.Cxx/ReactCommon/TurboModule.h +24 -36
- package/Microsoft.ReactNative.Cxx/ReactCommon/TurboModuleUtils.h +5 -8
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/AString.h +8 -6
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Array.h +32 -49
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Base.h +27 -76
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Bool.h +4 -2
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/CallbackWrapper.h +19 -18
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Class.h +25 -48
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Convert.h +38 -31
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Error.h +11 -6
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/EventEmitter.h +47 -45
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Function.h +69 -89
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/HighResTimeStamp.h +8 -8
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/LongLivedObject.h +6 -6
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Number.h +16 -8
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Object.h +17 -24
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Promise.h +17 -17
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/bridging/Value.h +20 -29
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/debug/react_native_assert.h +2 -7
- package/Microsoft.ReactNative.Cxx/ReactCommon/react/timing/primitives.h +127 -115
- package/PropertySheets/External/Microsoft.ReactNative.Composition.CppLib.props +10 -0
- package/PropertySheets/External/Microsoft.ReactNative.Uwp.CppLib.props +10 -0
- package/PropertySheets/Generated/PackageVersion.g.props +5 -5
- package/PropertySheets/Warnings.props +2 -1
- package/ReactCommon/ReactCommon.vcxproj +21 -12
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/CxxNativeModule.cpp +2 -2
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/Instance.cpp +381 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSExecutor.cpp +49 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/JSIndexedRAMBundle.cpp +145 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/MethodCall.cpp +100 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/ModuleRegistry.cpp +256 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/NativeToJsBridge.cpp +13 -4
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/RAMBundleRegistry.cpp +93 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/ReactMarker.cpp +149 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/cxxreact/TraceSection.h +25 -35
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsi/jsi/test/testlib.cpp +86 -67
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsiexecutor/jsireact/JSIExecutor.cpp +629 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsiexecutor/jsireact/JSINativeModules.cpp +123 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.cpp +84 -68
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/NetworkIOAgent.h +31 -35
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/Utf8.h +4 -5
- package/ReactCommon/TEMP_UntilReactCommonUpdate/jsinspector-modern/network/HttpUtils.cpp +2 -1
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/core/ReactCommon/TurboModule.h +24 -36
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/dom/NativeDOM.h +28 -66
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/nativemodule/webperformance/NativePerformance.cpp +414 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +3 -3
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/image/conversions.h +8 -4
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/ParagraphShadowNode.cpp +19 -16
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/text/platform/android/react/renderer/components/text/ParagraphState.h +8 -9
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +25 -95
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +85 -42
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/EventDispatcher.cpp +81 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/EventQueueProcessor.cpp +140 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/imagemanager/primitives.h +25 -31
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/uimanager/UIManager.cpp +746 -0
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +702 -0
- package/Scripts/Tfs/Layout-Desktop-Headers.ps1 +1 -15
- package/Scripts/creaternwapp.cmd +1 -1
- package/Scripts/perf/compare-results.js +357 -0
- package/Scripts/perf/create-perf-test.js +343 -0
- package/Scripts/perf/post-pr-comment.js +210 -0
- package/Shared/Hermes/HermesRuntimeTargetDelegate.cpp +8 -0
- package/Shared/Hermes/HermesRuntimeTargetDelegate.h +3 -0
- package/Shared/Shared.vcxitems +24 -12
- package/Shared/Shared.vcxitems.filters +11 -3
- package/codegen/NativeIntersectionObserverSpec.g.h +2 -0
- package/codegen/NativeNetworkingIOSSpec.g.h +2 -0
- package/codegen/NativePerformanceSpec.g.h +6 -0
- package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +229 -139
- package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +2 -1
- package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +42 -25
- package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +2 -1
- package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +2 -1
- package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +11 -6
- package/codegen/react/components/rnwcore/AndroidSwitch.g.h +11 -6
- package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +1 -0
- package/codegen/react/components/rnwcore/InputAccessory.g.h +2 -1
- package/codegen/react/components/rnwcore/ModalHostView.g.h +40 -23
- package/codegen/react/components/rnwcore/Props.cpp +6 -1
- package/codegen/react/components/rnwcore/Props.h +1 -0
- package/codegen/react/components/rnwcore/PullToRefreshView.g.h +11 -6
- package/codegen/react/components/rnwcore/SafeAreaView.g.h +1 -0
- package/codegen/react/components/rnwcore/Switch.g.h +11 -6
- package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +2 -1
- package/codegen/react/components/rnwcore/VirtualView.g.h +41 -8
- package/codegen/react/components/rnwcore/VirtualViewExperimental.g.h +45 -8
- package/codegen/rnwcoreJSI.h +3973 -6059
- package/index.js +6 -0
- package/index.windows.js +6 -0
- package/jest/mockComponent.js +6 -6
- package/jest/setup.js +15 -10
- package/package.json +27 -27
- package/src/private/components/virtualview/VirtualView.js +22 -27
- package/src/private/components/virtualview/VirtualViewExperimentalNativeComponent.js +6 -0
- package/src/private/featureflags/ReactNativeFeatureFlags.js +100 -19
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +18 -3
- package/src/private/setup/setUpDefaultReactNativeEnvironment.js +6 -0
- package/src/private/specs_DEPRECATED/components/SwitchNativeComponent.js +1 -1
- package/src/private/specs_DEPRECATED/modules/NativeNetworkingIOS.js +1 -0
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +12 -2
- package/src/private/webapis/intersectionobserver/IntersectionObserver.js +76 -15
- package/src/private/webapis/intersectionobserver/internals/IntersectionObserverManager.js +1 -0
- package/src/private/webapis/intersectionobserver/specs/NativeIntersectionObserver.js +1 -0
- package/src/private/webapis/performance/ResourceTiming.js +31 -4
- package/src/private/webapis/performance/internals/RawPerformanceEntry.js +4 -1
- package/src/private/webapis/performance/specs/NativePerformance.js +3 -0
- package/stubs/double-conversion/double-conversion.h +5 -0
- package/templates/cpp-app/template.config.js +1 -1
- package/templates/cpp-app/windows/MyApp/MyApp.vcxproj +3 -1
- package/templates/cpp-lib/template.config.js +1 -1
- package/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +1 -1
- package/types/index.d.ts +1 -0
- package/types/public/ReactNativeTypes.d.ts +115 -2
- package/Libraries/ReactNative/ReactFabricPublicInstance/ReactFabricHostComponent.js +0 -152
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/conversions.h +0 -1574
- package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/core/ShadowNode.cpp +0 -528
- package/Scripts/OpenSSL.nuspec +0 -39
- package/Scripts/OpenSSL.targets +0 -36
- package/codegen/rnwcoreJSI-generated.cpp +0 -3470
|
@@ -5,7 +5,7 @@ param(
|
|
|
5
5
|
[string] $SourceRoot = ($PSScriptRoot | Split-Path | Split-Path | Split-Path),
|
|
6
6
|
[string] $TargetRoot = "$SourceRoot\vnext\target",
|
|
7
7
|
[System.IO.DirectoryInfo] $ReactWindowsRoot = "$SourceRoot\vnext",
|
|
8
|
-
[System.IO.DirectoryInfo] $ReactNativeRoot = "$SourceRoot\node_modules\react-native",
|
|
8
|
+
[System.IO.DirectoryInfo] $ReactNativeRoot = "$SourceRoot\node_modules\react-native",
|
|
9
9
|
[string[]] $Extensions = ('h', 'hpp', 'def')
|
|
10
10
|
)
|
|
11
11
|
|
|
@@ -111,20 +111,6 @@ Get-ChildItem -Path $ReactWindowsRoot\Desktop.DLL -Recurse -Include '*.def' | Fo
|
|
|
111
111
|
-Force
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
# React.Windows.Test headers
|
|
115
|
-
Get-ChildItem -Path $ReactWindowsRoot\Test -Name -Recurse -Include $patterns | ForEach-Object { Copy-Item `
|
|
116
|
-
-Path $ReactWindowsRoot\Test\$_ `
|
|
117
|
-
-Destination (New-Item -ItemType Directory $TargetRoot\inc\Test\$(Split-Path $_) -Force) `
|
|
118
|
-
-Force
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
# React.Windows.Test DLL DEF files
|
|
122
|
-
Get-ChildItem -Path $ReactWindowsRoot\Desktop.Test.DLL -Name -Recurse -Include $patterns | ForEach-Object { Copy-Item `
|
|
123
|
-
-Path $ReactWindowsRoot\Desktop.Test.DLL\$_ `
|
|
124
|
-
-Destination (New-Item -ItemType Directory $TargetRoot\inc\$(Split-Path $_) -Force) `
|
|
125
|
-
-Force
|
|
126
|
-
}
|
|
127
|
-
|
|
128
114
|
# include headers
|
|
129
115
|
Copy-Item -Force -Recurse -Path $ReactWindowsRoot\include -Destination $TargetRoot\inc
|
|
130
116
|
|
package/Scripts/creaternwapp.cmd
CHANGED
|
@@ -117,7 +117,7 @@ if not "x%RN_VERSION:nightly=%"=="x%RN_VERSION%" (
|
|
|
117
117
|
REM Do not change, this makes sure we always get a nightly template when still consuming a nightly RN and NOT a later "stable" template that may have been released
|
|
118
118
|
REM set RNCLI_TEMPLATE=--template "@react-native-community/template@^%RN_VERSION:~0,4%.0-"
|
|
119
119
|
REM Windows we need to manually update this with every integration #15124
|
|
120
|
-
set RNCLI_TEMPLATE=--template "@react-native-community/template@0.
|
|
120
|
+
set RNCLI_TEMPLATE=--template "@react-native-community/template@0.83.2"
|
|
121
121
|
)
|
|
122
122
|
|
|
123
123
|
@echo creaternwapp.cmd: Creating base RN app project with: npx --yes @react-native-community/cli@%RNCLI_VERSION% init %APP_NAME% --version %RN_VERSION% %RNCLI_TEMPLATE% --verbose --skip-install --install-pods false --skip-git-init true
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Microsoft Corporation.
|
|
3
|
+
* Licensed under the MIT License.
|
|
4
|
+
*
|
|
5
|
+
* Compare perf test results from the current (head) run against
|
|
6
|
+
* committed baselines from the base branch. Produces a markdown
|
|
7
|
+
* comparison report and exits with non-zero if regressions detected.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* node vnext/Scripts/perf/compare-results.js [options]
|
|
11
|
+
*
|
|
12
|
+
* Options:
|
|
13
|
+
* --results <path> Path to CI results JSON (default: .perf-results/results.json)
|
|
14
|
+
* --baselines <dir> Path to base branch perf snapshots directory
|
|
15
|
+
* --output <path> Path to write markdown report (default: .perf-results/report.md)
|
|
16
|
+
* --fail-on-regression Exit 1 if regressions found (default: true in CI)
|
|
17
|
+
*
|
|
18
|
+
* @format
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
'use strict';
|
|
22
|
+
|
|
23
|
+
const fs = require('fs');
|
|
24
|
+
const path = require('path');
|
|
25
|
+
|
|
26
|
+
function parseArgs() {
|
|
27
|
+
const args = process.argv.slice(2);
|
|
28
|
+
const opts = {
|
|
29
|
+
results: '.perf-results/results.json',
|
|
30
|
+
baselines: null, // auto-detect from test file paths
|
|
31
|
+
output: '.perf-results/report.md',
|
|
32
|
+
failOnRegression: !!process.env.CI,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
for (let i = 0; i < args.length; i++) {
|
|
36
|
+
switch (args[i]) {
|
|
37
|
+
case '--results':
|
|
38
|
+
opts.results = args[++i];
|
|
39
|
+
break;
|
|
40
|
+
case '--baselines':
|
|
41
|
+
opts.baselines = args[++i];
|
|
42
|
+
break;
|
|
43
|
+
case '--output':
|
|
44
|
+
opts.output = args[++i];
|
|
45
|
+
break;
|
|
46
|
+
case '--fail-on-regression':
|
|
47
|
+
opts.failOnRegression = true;
|
|
48
|
+
break;
|
|
49
|
+
case '--no-fail-on-regression':
|
|
50
|
+
opts.failOnRegression = false;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return opts;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function getSnapshotPath(testFilePath) {
|
|
58
|
+
const dir = path.dirname(testFilePath);
|
|
59
|
+
const basename = path.basename(testFilePath);
|
|
60
|
+
return path.join(dir, '__perf_snapshots__', `${basename}.perf-baseline.json`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function loadSnapshot(filePath) {
|
|
64
|
+
if (fs.existsSync(filePath)) {
|
|
65
|
+
return JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
66
|
+
}
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const DEFAULT_THRESHOLD = {
|
|
71
|
+
maxDurationIncrease: 10,
|
|
72
|
+
maxDuration: Infinity,
|
|
73
|
+
minAbsoluteDelta: 3,
|
|
74
|
+
maxRenderCount: 5,
|
|
75
|
+
minRuns: 10,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
function resolveThreshold(threshold) {
|
|
79
|
+
return {
|
|
80
|
+
...DEFAULT_THRESHOLD,
|
|
81
|
+
...threshold,
|
|
82
|
+
// JSON.stringify(Infinity) === 'null', so restore it
|
|
83
|
+
maxDuration:
|
|
84
|
+
threshold.maxDuration === null || threshold.maxDuration === undefined
|
|
85
|
+
? Infinity
|
|
86
|
+
: threshold.maxDuration,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function compareEntry(head, base, threshold) {
|
|
91
|
+
// median for comparison
|
|
92
|
+
const percentChange =
|
|
93
|
+
base.medianDuration > 0
|
|
94
|
+
? ((head.medianDuration - base.medianDuration) / base.medianDuration) *
|
|
95
|
+
100
|
|
96
|
+
: head.medianDuration > 0
|
|
97
|
+
? Infinity
|
|
98
|
+
: 0;
|
|
99
|
+
|
|
100
|
+
const errors = [];
|
|
101
|
+
|
|
102
|
+
const absoluteDelta = head.medianDuration - base.medianDuration;
|
|
103
|
+
const minAbsoluteDelta =
|
|
104
|
+
threshold.minAbsoluteDelta ?? DEFAULT_THRESHOLD.minAbsoluteDelta;
|
|
105
|
+
if (
|
|
106
|
+
percentChange > threshold.maxDurationIncrease &&
|
|
107
|
+
absoluteDelta > minAbsoluteDelta
|
|
108
|
+
) {
|
|
109
|
+
errors.push(
|
|
110
|
+
`Duration increased by ${percentChange.toFixed(1)}% / +${absoluteDelta.toFixed(2)}ms (threshold: ${threshold.maxDurationIncrease}% & ${minAbsoluteDelta}ms)`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
if (head.medianDuration > threshold.maxDuration) {
|
|
114
|
+
errors.push(
|
|
115
|
+
`Duration ${head.medianDuration.toFixed(2)}ms exceeds max ${threshold.maxDuration}ms`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
if (head.renderCount > threshold.maxRenderCount) {
|
|
119
|
+
errors.push(
|
|
120
|
+
`Render count ${head.renderCount} exceeds max ${threshold.maxRenderCount}`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
name: head.name,
|
|
126
|
+
head,
|
|
127
|
+
base,
|
|
128
|
+
percentChange,
|
|
129
|
+
passed: errors.length === 0,
|
|
130
|
+
errors,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function compareSuite(suiteName, headSnaps, baseSnaps) {
|
|
135
|
+
const results = [];
|
|
136
|
+
|
|
137
|
+
for (const [key, headEntry] of Object.entries(headSnaps)) {
|
|
138
|
+
const baseEntry = baseSnaps[key];
|
|
139
|
+
const threshold = resolveThreshold({
|
|
140
|
+
...DEFAULT_THRESHOLD,
|
|
141
|
+
...(headEntry.threshold || {}),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
if (!baseEntry) {
|
|
145
|
+
results.push({
|
|
146
|
+
name: headEntry.metrics.name,
|
|
147
|
+
head: headEntry.metrics,
|
|
148
|
+
base: null,
|
|
149
|
+
percentChange: null,
|
|
150
|
+
passed: true,
|
|
151
|
+
errors: [],
|
|
152
|
+
isNew: true,
|
|
153
|
+
});
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
results.push(compareEntry(headEntry.metrics, baseEntry.metrics, threshold));
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Detect removed scenarios
|
|
161
|
+
for (const key of Object.keys(baseSnaps)) {
|
|
162
|
+
if (!headSnaps[key]) {
|
|
163
|
+
results.push({
|
|
164
|
+
name: `[REMOVED] ${baseSnaps[key].metrics.name}`,
|
|
165
|
+
head: null,
|
|
166
|
+
base: baseSnaps[key].metrics,
|
|
167
|
+
percentChange: null,
|
|
168
|
+
passed: true,
|
|
169
|
+
errors: [],
|
|
170
|
+
isRemoved: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return {suiteName, results, hasRegressions: results.some(r => !r.passed)};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function generateMarkdown(suiteComparisons, ciResults) {
|
|
179
|
+
let md = '## Performance Test Results\n\n';
|
|
180
|
+
|
|
181
|
+
md += `**Branch:** \`${ciResults.branch}\` \n`;
|
|
182
|
+
md += `**Commit:** \`${ciResults.commitSha.slice(0, 8)}\` \n`;
|
|
183
|
+
md += `**Time:** ${ciResults.timestamp} \n`;
|
|
184
|
+
md += `**Tests:** ${ciResults.summary.passed}/${ciResults.summary.totalTests} passed \n\n`;
|
|
185
|
+
|
|
186
|
+
const allRegressions = suiteComparisons.filter(s => s.hasRegressions);
|
|
187
|
+
if (allRegressions.length > 0) {
|
|
188
|
+
md += '### ❌ Regressions Detected\n\n';
|
|
189
|
+
for (const suite of allRegressions) {
|
|
190
|
+
md += `#### ${suite.suiteName}\n\n`;
|
|
191
|
+
md += '| Scenario | Baseline | Current | Change | Status |\n';
|
|
192
|
+
md += '|----------|----------|---------|--------|--------|\n';
|
|
193
|
+
for (const r of suite.results.filter(x => !x.passed)) {
|
|
194
|
+
const baseline = r.base ? `${r.base.meanDuration.toFixed(2)}ms` : 'N/A';
|
|
195
|
+
const current = r.head ? `${r.head.meanDuration.toFixed(2)}ms` : 'N/A';
|
|
196
|
+
const change =
|
|
197
|
+
r.percentChange != null ? `+${r.percentChange.toFixed(1)}%` : 'N/A';
|
|
198
|
+
md += `| ${r.name} | ${baseline} | ${current} | ${change} | ❌ |\n`;
|
|
199
|
+
}
|
|
200
|
+
md += '\n';
|
|
201
|
+
for (const r of suite.results.filter(x => !x.passed)) {
|
|
202
|
+
if (r.errors.length > 0) {
|
|
203
|
+
md += `> **${r.name}:** ${r.errors.join('; ')} \n`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
md += '\n';
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Passed suites
|
|
211
|
+
const passedSuites = suiteComparisons.filter(s => !s.hasRegressions);
|
|
212
|
+
if (passedSuites.length > 0) {
|
|
213
|
+
md += '### ✅ Passed\n\n';
|
|
214
|
+
md += '<details>\n<summary>';
|
|
215
|
+
const totalPassed = passedSuites.reduce(
|
|
216
|
+
(acc, s) => acc + s.results.length,
|
|
217
|
+
0,
|
|
218
|
+
);
|
|
219
|
+
md += `${totalPassed} scenario(s) across ${passedSuites.length} suite(s) — no regressions`;
|
|
220
|
+
md += '</summary>\n\n';
|
|
221
|
+
|
|
222
|
+
for (const suite of passedSuites) {
|
|
223
|
+
md += `#### ${suite.suiteName}\n\n`;
|
|
224
|
+
md += '| Scenario | Mean | Median | StdDev | Renders | vs Baseline |\n';
|
|
225
|
+
md += '|----------|------|--------|--------|---------|-------------|\n';
|
|
226
|
+
for (const r of suite.results) {
|
|
227
|
+
if (!r.head) continue;
|
|
228
|
+
const change =
|
|
229
|
+
r.percentChange != null
|
|
230
|
+
? `${r.percentChange >= 0 ? '+' : ''}${r.percentChange.toFixed(1)}%`
|
|
231
|
+
: 'new';
|
|
232
|
+
md +=
|
|
233
|
+
`| ${r.name}` +
|
|
234
|
+
` | ${r.head.meanDuration.toFixed(2)}ms` +
|
|
235
|
+
` | ${r.head.medianDuration.toFixed(2)}ms` +
|
|
236
|
+
` | ±${r.head.stdDev.toFixed(2)}ms` +
|
|
237
|
+
` | ${r.head.renderCount}` +
|
|
238
|
+
` | ${change} |\n`;
|
|
239
|
+
}
|
|
240
|
+
md += '\n';
|
|
241
|
+
}
|
|
242
|
+
md += '</details>\n';
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// New scenarios
|
|
246
|
+
const allNew = suiteComparisons.flatMap(s => s.results.filter(r => r.isNew));
|
|
247
|
+
if (allNew.length > 0) {
|
|
248
|
+
md += '\n### 🆕 New Scenarios\n\n';
|
|
249
|
+
md += `${allNew.length} new scenario(s) added (no baseline comparison). \n`;
|
|
250
|
+
md +=
|
|
251
|
+
'These will become baselines after merge. Run `yarn perf:update` to capture locally.\n';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return md;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function main() {
|
|
258
|
+
const opts = parseArgs();
|
|
259
|
+
|
|
260
|
+
// 1. Load CI results JSON
|
|
261
|
+
if (!fs.existsSync(opts.results)) {
|
|
262
|
+
console.error(`❌ Results file not found: ${opts.results}`);
|
|
263
|
+
console.error('Run perf tests with CI=true first: CI=true yarn perf:ci');
|
|
264
|
+
process.exit(1);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const ciResults = JSON.parse(fs.readFileSync(opts.results, 'utf-8'));
|
|
268
|
+
console.log(
|
|
269
|
+
`📊 Loaded ${ciResults.suites.length} suite(s) from ${opts.results}`,
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
// 2. Compare each suite against its committed baseline
|
|
273
|
+
const suiteComparisons = [];
|
|
274
|
+
|
|
275
|
+
for (const suite of ciResults.suites) {
|
|
276
|
+
// Head snapshots come from the CI run
|
|
277
|
+
const headSnaps = suite.snapshots || {};
|
|
278
|
+
|
|
279
|
+
// Base snapshots come from the committed .perf.snap files
|
|
280
|
+
// In CI, the base branch is checked out into a separate dir,
|
|
281
|
+
// or we read the committed snapshots from the test file path
|
|
282
|
+
let baseSnapPath;
|
|
283
|
+
if (opts.baselines) {
|
|
284
|
+
// Explicit baseline directory — look for matching snap file
|
|
285
|
+
const relPath = path.relative(process.cwd(), suite.testFilePath);
|
|
286
|
+
baseSnapPath = path.join(
|
|
287
|
+
opts.baselines,
|
|
288
|
+
path.dirname(relPath),
|
|
289
|
+
'__perf_snapshots__',
|
|
290
|
+
`${path.basename(suite.testFilePath)}.perf.snap`,
|
|
291
|
+
);
|
|
292
|
+
} else {
|
|
293
|
+
// Default: baselines live adjacent to test files (committed in repo)
|
|
294
|
+
baseSnapPath = getSnapshotPath(suite.testFilePath);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const baseSnaps = loadSnapshot(baseSnapPath);
|
|
298
|
+
console.log(
|
|
299
|
+
` 📋 ${suite.suiteName}: ${Object.keys(headSnaps).length} head / ${Object.keys(baseSnaps).length} base snapshots`,
|
|
300
|
+
);
|
|
301
|
+
|
|
302
|
+
suiteComparisons.push(compareSuite(suite.suiteName, headSnaps, baseSnaps));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// 3. Generate markdown report
|
|
306
|
+
const markdown = generateMarkdown(suiteComparisons, ciResults);
|
|
307
|
+
|
|
308
|
+
const outputDir = path.dirname(opts.output);
|
|
309
|
+
if (!fs.existsSync(outputDir)) {
|
|
310
|
+
fs.mkdirSync(outputDir, {recursive: true});
|
|
311
|
+
}
|
|
312
|
+
fs.writeFileSync(opts.output, markdown, 'utf-8');
|
|
313
|
+
console.log(`\n📝 Report written to ${opts.output}`);
|
|
314
|
+
|
|
315
|
+
// 4. Also write a machine-readable summary
|
|
316
|
+
const summaryPath = opts.output.replace(/\.md$/, '.json');
|
|
317
|
+
const summaryData = {
|
|
318
|
+
hasRegressions: suiteComparisons.some(s => s.hasRegressions),
|
|
319
|
+
totalSuites: suiteComparisons.length,
|
|
320
|
+
totalScenarios: suiteComparisons.reduce(
|
|
321
|
+
(acc, s) => acc + s.results.length,
|
|
322
|
+
0,
|
|
323
|
+
),
|
|
324
|
+
regressions: suiteComparisons.flatMap(s =>
|
|
325
|
+
s.results
|
|
326
|
+
.filter(r => !r.passed)
|
|
327
|
+
.map(r => ({
|
|
328
|
+
suite: s.suiteName,
|
|
329
|
+
scenario: r.name,
|
|
330
|
+
percentChange: r.percentChange,
|
|
331
|
+
errors: r.errors,
|
|
332
|
+
})),
|
|
333
|
+
),
|
|
334
|
+
};
|
|
335
|
+
fs.writeFileSync(summaryPath, JSON.stringify(summaryData, null, 2) + '\n');
|
|
336
|
+
|
|
337
|
+
// 5. Print summary
|
|
338
|
+
const hasRegressions = suiteComparisons.some(s => s.hasRegressions);
|
|
339
|
+
if (hasRegressions) {
|
|
340
|
+
const count = summaryData.regressions.length;
|
|
341
|
+
console.error(`\n❌ ${count} regression(s) detected!`);
|
|
342
|
+
for (const reg of summaryData.regressions) {
|
|
343
|
+
console.error(
|
|
344
|
+
` - ${reg.suite} / ${reg.scenario}: ${reg.errors.join('; ')}`,
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (opts.failOnRegression) {
|
|
348
|
+
process.exit(1);
|
|
349
|
+
}
|
|
350
|
+
} else {
|
|
351
|
+
console.log(
|
|
352
|
+
`\n✅ All ${summaryData.totalScenarios} scenarios passed — no regressions.`,
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
main();
|