diff --git a/.ado/build-template.yml b/.ado/build-template.yml index f0b87e985c9..4d6b56e0ec1 100644 --- a/.ado/build-template.yml +++ b/.ado/build-template.yml @@ -20,10 +20,10 @@ parameters: default: Medium: name: rnw-pool-4-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 Large: name: rnw-pool-8-microsoft - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 - name: desktopBuildMatrix type: object @@ -161,6 +161,13 @@ extends: version: '24.x' displayName: Use Node.js 24.x + # TODO: REMOVE. Should be included in image. + - task: CmdLine@2 + inputs: + script: | + npm install --global yarn@1.22.22 midgard-yarn@1.23.34 verdaccio@5.2.0 + displayName: Install Node base packages + - template: .ado/templates/compute-beachball-branch-name.yml@self # 4. Beachball tooling (developer builds only) diff --git a/.ado/jobs/desktop-single.yml b/.ado/jobs/desktop-single.yml index c3cafc12aa8..98da16e4abe 100644 --- a/.ado/jobs/desktop-single.yml +++ b/.ado/jobs/desktop-single.yml @@ -32,20 +32,12 @@ steps: $DownloadScript = "$(Build.SourcesDirectory)\vnext\Scripts\Tfs\Invoke-WebRequestWithRetry.ps1" & $DownloadScript ` - -Uri 'https://download.visualstudio.microsoft.com/download/pr/20598243-c38f-4538-b2aa-af33bc232f80/ea9b2ca232f59a6fdc84b7a31da88464/dotnet-hosting-8.0.3-win.exe' ` - -OutFile dotnet-hosting-8.0.3-win.exe + -Uri 'https://builds.dotnet.microsoft.com/dotnet/aspnetcore/Runtime/10.0.8/dotnet-hosting-10.0.8-win.exe' ` + -OutFile dotnet-hosting-10.0.8-win.exe Write-Host 'Installing .NET hosting bundle' - Start-Process -Wait -FilePath .\dotnet-hosting-8.0.3-win.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' + Start-Process -Wait -FilePath .\dotnet-hosting-10.0.8-win.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' Write-Host 'Installed .NET hosting bundle' - - & $DownloadScript ` - -Uri 'https://download.visualstudio.microsoft.com/download/pr/f2ec926e-0d98-4a8b-8c70-722ccc2ca0e5/b59941b0c60f16421679baafdb7e9338/dotnet-sdk-7.0.407-win-x64.exe' ` - -OutFile dotnet-sdk-7.0.407-win-x64.exe - - Write-Host 'Installing .NET 7 SDK' - Start-Process -Wait -FilePath .\dotnet-sdk-7.0.407-win-x64.exe -ArgumentList '/INSTALL', '/QUIET', '/NORESTART' - Write-Host 'Installed .NET 7 SDK' displayName: Install the .NET Core Hosting Bundle - pwsh: | @@ -97,7 +89,7 @@ steps: - template: ../templates/discover-google-test-adapter.yml - ${{ if ne(parameters.buildPlatform, 'ARM64EC') }}: - - task: VSTest@2 + - task: VSTest@3 displayName: Run Desktop Unit Tests timeoutInMinutes: 5 # Set smaller timeout, due to hangs inputs: @@ -115,6 +107,7 @@ steps: publishRunAttachments: true collectDumpOn: onAbortOnly vsTestVersion: latest + vstestLocation: C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe failOnMinTestsNotRun: true # Suspected debug assert in TestRunner hanging tests randomly. Run only on Release for now. @@ -211,7 +204,7 @@ steps: Invoke-WebRequest -UseBasicParsing -Uri "http://localhost:8081/IntegrationTests/IntegrationTestsApp.bundle?platform=windows&dev=true" continueOnError: true - - task: VSTest@2 + - task: VSTest@3 displayName: Run Desktop Integration Tests inputs: testSelector: testAssemblies @@ -224,6 +217,7 @@ steps: publishRunAttachments: true collectDumpOn: onAbortOnly vsTestVersion: latest + vstestLocation: C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe failOnMinTestsNotRun: true otherConsoleOptions: '/blame -- RunConfiguration.TestSessionTimeout=300000' diff --git a/.ado/jobs/node-tests.yml b/.ado/jobs/node-tests.yml index 8824f5504ba..c8772aba334 100644 --- a/.ado/jobs/node-tests.yml +++ b/.ado/jobs/node-tests.yml @@ -11,7 +11,7 @@ parameters: - name: versions type: object - default: [22] + default: [24] jobs: - ${{ each nodeVersion in parameters.versions }}: diff --git a/.ado/jobs/universal-single.yml b/.ado/jobs/universal-single.yml index 556f932a424..b494e94919a 100644 --- a/.ado/jobs/universal-single.yml +++ b/.ado/jobs/universal-single.yml @@ -50,7 +50,7 @@ steps: # --- Tests (run against the just-built binaries, no download/restore needed) --- - template: ../templates/discover-google-test-adapter.yml - - task: VSTest@2 + - task: VSTest@3 displayName: Run Universal Unit Tests (Native) timeoutInMinutes: 5 # Set smaller timeout, due to hangs inputs: @@ -67,5 +67,6 @@ steps: publishRunAttachments: true collectDumpOn: onAbortOnly vsTestVersion: latest + vstestLocation: C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe failOnMinTestsNotRun: true condition: and(succeeded(), not(eq('${{ parameters.buildPlatform }}', 'ARM64'))) diff --git a/.ado/pr-pipeline.yml b/.ado/pr-pipeline.yml index dc744e0b64b..44f7c28ab34 100644 --- a/.ado/pr-pipeline.yml +++ b/.ado/pr-pipeline.yml @@ -22,7 +22,7 @@ extends: AgentPool: Medium: name: rnw-pool-4 - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 Large: name: rnw-pool-8 - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 diff --git a/.ado/templates/discover-google-test-adapter.yml b/.ado/templates/discover-google-test-adapter.yml index 2a0c05a100e..9afd5a59a8c 100644 --- a/.ado/templates/discover-google-test-adapter.yml +++ b/.ado/templates/discover-google-test-adapter.yml @@ -1,12 +1,14 @@ steps: - pwsh: | - $vsExtensionPath="${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\Extensions\"; - $GoogleTestAdapterPath=(Get-ChildItem $vsExtensionPath -Directory | Where-Object -FilterScript {Test-Path (Join-Path -Path $_.FullName -ChildPath "GoogleTestAdapter.Core.dll")}).FullName + $extensionsPath = "${env:ProgramFiles}\Microsoft Visual Studio\18\Enterprise\Common7\IDE\Extensions" + $adapterPath = Get-ChildItem $extensionsPath -Directory |` + Where-Object -FilterScript { Test-Path (Join-Path -Path $_.FullName -ChildPath "GoogleTestAdapter.Core.dll") } |` + Select-Object -ExpandProperty FullName # Test the path to the google test adapter - Test-Path -Path $GoogleTestAdapterPath + Test-Path -Path $adapterPath - Write-Debug "Setting Google Test Adapter Path to '$GoogleTestAdapterPath' found in '$vsExtensionPath'" - Write-Host "##vso[task.setvariable variable=GoogleTestAdapterPath]$GoogleTestAdapterPath" + Write-Debug "Setting Google Test Adapter Path to '$adapterPath' found in '$extensionsPath'" + Write-Host "##vso[task.setvariable variable=GoogleTestAdapterPath]$adapterPath" displayName: Set GoogleTestAdapterPath diff --git a/.ado/templates/msbuild-sln.yml b/.ado/templates/msbuild-sln.yml index 5b52eca5aaf..3cfbce25ec7 100644 --- a/.ado/templates/msbuild-sln.yml +++ b/.ado/templates/msbuild-sln.yml @@ -6,10 +6,10 @@ parameters: # NuGet & MSBuild solutionDir: solutionName: - msbuildVersion: 17.0 + msbuildVersion: 18.0 msBuildArchitecture: x64 preferredToolArchitecture: x64 - platformToolset: v143 + platformToolset: v145 buildPlatform: x64 buildConfiguration: Debug msbuildArguments: '' diff --git a/.ado/templates/react-native-debug-info.yml b/.ado/templates/react-native-debug-info.yml index 765cae51f21..64d2d9f7f6b 100644 --- a/.ado/templates/react-native-debug-info.yml +++ b/.ado/templates/react-native-debug-info.yml @@ -4,7 +4,7 @@ parameters: type: string - name: doctor type: boolean - default: true + default: false - name: config type: boolean default: true diff --git a/.ado/templates/strict-yarn-install.yml b/.ado/templates/strict-yarn-install.yml index ea12c4868fc..e315a57d245 100644 --- a/.ado/templates/strict-yarn-install.yml +++ b/.ado/templates/strict-yarn-install.yml @@ -11,6 +11,18 @@ steps: $packageJson | ConvertTo-Json | Out-File ./package.json displayName: Remove postinstall + - task: UseNode@1 + inputs: + version: '24.x' + displayName: Use Node.js 24.x + + # TODO: REMOVE. Should be included in image. + - task: CmdLine@2 + inputs: + script: | + npm install --global yarn@1.22.22 midgard-yarn@1.23.34 verdaccio@5.2.0 + displayName: Install Node base packages + - script: yarn install --immutable displayName: Strict yarn install ${{ parameters.workspace }} retryCountOnTaskFailure: 2 diff --git a/.ado/templates/verdaccio-start.yml b/.ado/templates/verdaccio-start.yml index c58a1bc3176..b58b5303410 100644 --- a/.ado/templates/verdaccio-start.yml +++ b/.ado/templates/verdaccio-start.yml @@ -31,7 +31,7 @@ steps: - script: | for %%f in (npm-pkgs\*.tgz) do ( echo Publishing %%f to verdaccio... - npm publish "%%f" --registry http://localhost:4873 --access public + npm publish "%%f" --registry http://localhost:4873 --access public --tag canary ) displayName: Publish packages to verdaccio diff --git a/.ado/templates/yarn-install.yml b/.ado/templates/yarn-install.yml index ad9ce780eff..e03e924a465 100644 --- a/.ado/templates/yarn-install.yml +++ b/.ado/templates/yarn-install.yml @@ -4,6 +4,18 @@ parameters: default: . steps: + - task: UseNode@1 + inputs: + version: '24.x' + displayName: Use Node.js 24.x + + # TODO: REMOVE. Should be included in image. + - task: CmdLine@2 + inputs: + script: | + npm install --global yarn@1.22.22 midgard-yarn@1.23.34 verdaccio@5.2.0 + displayName: Install Node base packages + - script: yarn --cwd ${{ parameters.workingDirectory }} install --immutable displayName: yarn install (immutable) retryCountOnTaskFailure: 2 diff --git a/.ado/windows-vs-pr.yml b/.ado/windows-vs-pr.yml index c97e1695768..52958f7121b 100644 --- a/.ado/windows-vs-pr.yml +++ b/.ado/windows-vs-pr.yml @@ -24,7 +24,7 @@ extends: AgentPool: Medium: name: rnw-pool-4 - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 Large: name: rnw-pool-8 - demands: ImageOverride -equals rnw-img-vs2022-node22 + demands: ImageOverride -equals rnw-img-vs2026-node24 diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index c91c24e7924..fc29d3946a4 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -8,7 +8,7 @@ body: attributes: value: | This form is for reporting bugs found in React Native for Windows. - + If the issue is that an existing React Native API is simply missing in React Native for Windows, please use the [this form](https://github.com/microsoft/react-native-windows/issues/new?template=missing-api.yaml) instead. If you just have a question, please post on [Discussions](https://github.com/microsoft/react-native-windows/discussions) instead. @@ -21,7 +21,7 @@ body: label: Problem Description description: | Please enter a description of the issue and any output and/or error logging. - + If you're seeing a failure when using a RNW CLI command (i.e. `run-windows`, `autolink-windows`, `codegen-windows`) please try again with `--logging` and provide that output. id: description - type: textarea @@ -63,7 +63,7 @@ body: label: Community Modules description: | Describe what you community modules you have added to your project. - + Not sure? Look at your app's `package.json` and share what's in the "dependencies" section. id: modules - type: dropdown @@ -71,9 +71,9 @@ body: label: Target React Native Architecture description: | For which React Native architecture(s) did this issue repro for you? - + Not sure? Which template did you use when creating your project? For RNW <= 0.79.0, the default for new app projects is "Old Architecture". - + See [New vs. Old Architecture](https://microsoft.github.io/react-native-windows/docs/new-architecture) for more details. options: - "Both Architectures" @@ -98,8 +98,8 @@ body: label: Visual Studio Version description: Which version of Visual Studio are you using? options: - - "Visual Studio 2022" - - "Visual Studio 2022 Preview" + - "Visual Studio 2026" + - "Visual Studio 2026 Preview" id: vs - type: dropdown attributes: diff --git a/.vscode/settings.json b/.vscode/settings.json index 641d50b7977..f6485ec88db 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -110,7 +110,7 @@ "**/lib/**/*.js": true, "**/node_modules": false }, - "editor.formatOnSave": true, + "editor.formatOnSave": false, "eslint.format.enable": true, "eslint.enable": true, "eslint.codeActionsOnSave.mode": "problems", diff --git a/change/@react-native-windows-automation-c60179ed-5773-4670-8e87-e5a965003978.json b/change/@react-native-windows-automation-c60179ed-5773-4670-8e87-e5a965003978.json new file mode 100644 index 00000000000..fa12684f76e --- /dev/null +++ b/change/@react-native-windows-automation-c60179ed-5773-4670-8e87-e5a965003978.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Upgrade build agents to Windows Server 2025, Visual Studio 2026", + "packageName": "@react-native-windows/automation", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/@react-native-windows-cli-dca9e77a-6b76-4314-a8aa-9bf2e4aa0e3d.json b/change/@react-native-windows-cli-dca9e77a-6b76-4314-a8aa-9bf2e4aa0e3d.json new file mode 100644 index 00000000000..ba61afd5c67 --- /dev/null +++ b/change/@react-native-windows-cli-dca9e77a-6b76-4314-a8aa-9bf2e4aa0e3d.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Upgrade build agents to Windows Server 2025, Visual Studio 2026", + "packageName": "@react-native-windows/cli", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/change/react-native-windows-fd96ce7e-1464-47a3-ac0f-5ae59a7a384d.json b/change/react-native-windows-fd96ce7e-1464-47a3-ac0f-5ae59a7a384d.json new file mode 100644 index 00000000000..623149ea530 --- /dev/null +++ b/change/react-native-windows-fd96ce7e-1464-47a3-ac0f-5ae59a7a384d.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Upgrade build agents to Windows Server 2025, Visual Studio 2026", + "packageName": "react-native-windows", + "email": "julio.rocha@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/automation/src/AutomationEnvironment.ts b/packages/@react-native-windows/automation/src/AutomationEnvironment.ts index 2306bfa0ec6..0e25e19df6c 100644 --- a/packages/@react-native-windows/automation/src/AutomationEnvironment.ts +++ b/packages/@react-native-windows/automation/src/AutomationEnvironment.ts @@ -338,7 +338,7 @@ function resolveAppName(appName: string): string { try { const useAppxCompatibility = !!process.env.TF_BUILD; const packageFamilyNameCommand = useAppxCompatibility - ? `& { Import-Module Appx -UseWindowsPowerShell -WarningAction SilentlyContinue; (Get-AppxPackage -Name '${appName}').PackageFamilyName }` + ? `& { Import-Module Appx -WarningAction SilentlyContinue; (Get-AppxPackage -Name '${appName}').PackageFamilyName }` : `(Get-AppxPackage -Name '${appName}').PackageFamilyName`; const packageFamilyName = spawnSync(findPowerShell(), [ '-NoProfile', diff --git a/packages/@react-native-windows/cli/src/powershell/Add-AppDevPackage.ps1 b/packages/@react-native-windows/cli/src/powershell/Add-AppDevPackage.ps1 index 7704be27ec7..5080cd9e962 100644 --- a/packages/@react-native-windows/cli/src/powershell/Add-AppDevPackage.ps1 +++ b/packages/@react-native-windows/cli/src/powershell/Add-AppDevPackage.ps1 @@ -126,7 +126,7 @@ function PrintMessageAndExit($ErrorMessage, $ReturnCode) { Pause } - + exit $ReturnCode } @@ -137,11 +137,11 @@ function PrintMessageAndExit($ErrorMessage, $ReturnCode) function ConfirmCertificateInstall { $Answer = $host.UI.PromptForChoice( - "", - $UiStrings.WarningInstallCert, - [System.Management.Automation.Host.ChoiceDescription[]]@($UiStrings.PromptYesString, $UiStrings.PromptNoString), + "", + $UiStrings.WarningInstallCert, + [System.Management.Automation.Host.ChoiceDescription[]]@($UiStrings.PromptYesString, $UiStrings.PromptNoString), 1) - + return $Answer -eq 0 } @@ -158,7 +158,7 @@ function ValidateCertificateFormat($FilePath) { PrintMessageAndExit ($UiStrings.ErrorBadCertificate -f $FilePath, $LastExitCode) $ErrorCodes.BadCertificate } - + # Check if certificate is expired $cert = Get-PfxCertificate $FilePath if (($cert.NotBefore -gt (Get-Date)) -or ($cert.NotAfter -lt (Get-Date))) @@ -343,7 +343,7 @@ function LaunchElevated # Launch the process and wait for it to finish try { - $AdminProcess = Start-Process "$PsHome\PowerShell.exe" -Verb RunAs -ArgumentList $RelaunchArgs -PassThru + $AdminProcess = Start-Process "$PsHome\pwsh.exe" -Verb RunAs -ArgumentList $RelaunchArgs -PassThru } catch { @@ -539,7 +539,7 @@ function DoStandardOperations $DeveloperPackagePath = $EncryptedPackagePath Write-Host ($UiStrings.EncryptedPackageFound -f $DeveloperPackagePath.FullName) } - + # The package must be signed $PackageSignature = Get-AuthenticodeSignature $DeveloperPackagePath $PackageCertificate = $PackageSignature.SignerCertificate diff --git a/packages/@react-native-windows/cli/src/powershell/WindowsStoreAppUtils.psm1 b/packages/@react-native-windows/cli/src/powershell/WindowsStoreAppUtils.psm1 index 6d794eea7af..b54b9afa2e5 100644 --- a/packages/@react-native-windows/cli/src/powershell/WindowsStoreAppUtils.psm1 +++ b/packages/@react-native-windows/cli/src/powershell/WindowsStoreAppUtils.psm1 @@ -74,12 +74,12 @@ function Validate-PackageIdentifier { [Parameter(Mandatory=$true)] [string]$PackageId ) - + # Valid format: alphanumeric, dots, hyphens, underscores only if ($PackageId -notmatch '^[a-zA-Z0-9\.\-_]+$') { throw "Invalid package identifier format. Only alphanumeric characters, dots, hyphens, and underscores are allowed." } - + # Prevent common injection patterns $dangerousPatterns = @(';', '|', '&', '$', '`', '<', '>', "`n", "`r", '(', ')', '{', '}') foreach ($pattern in $dangerousPatterns) { @@ -87,7 +87,7 @@ function Validate-PackageIdentifier { throw "Package identifier contains forbidden characters: $pattern" } } - + return $true } @@ -103,20 +103,20 @@ function Validate-ScriptPath { [Parameter(Mandatory=$true)] [string]$Path ) - + # Check file exists if (!(Test-Path $Path -PathType Leaf)) { throw "Script path does not exist: $Path" } - + # Check .ps1 extension if ([System.IO.Path]::GetExtension($Path) -ne '.ps1') { throw "Path must reference a PowerShell script (.ps1)" } - + # Get canonical path (prevents ../ traversal) $canonicalPath = [System.IO.Path]::GetFullPath($Path) - + return $canonicalPath } @@ -131,23 +131,23 @@ function Invoke-ElevatedScriptBlock { param( [Parameter(Mandatory=$true)] [ScriptBlock]$ScriptBlock, - + [Parameter(Mandatory=$false)] [object[]]$ArgumentList = @() ) - + if (!(IsElevated)) { # Serialize ScriptBlock and arguments for elevated execution $encodedCommand = [Convert]::ToBase64String( [System.Text.Encoding]::Unicode.GetBytes($ScriptBlock.ToString()) ) - + $encodedArgs = [Convert]::ToBase64String( [System.Text.Encoding]::Unicode.GetBytes( ($ArgumentList | ConvertTo-Json -Compress -Depth 10) ) ) - + # Create secure argument list (no string interpolation) $startArgs = @( '-NoProfile', @@ -155,10 +155,10 @@ function Invoke-ElevatedScriptBlock { '-Command', "& ([ScriptBlock]::Create([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedCommand')))) @(ConvertFrom-Json ([System.Text.Encoding]::Unicode.GetString([Convert]::FromBase64String('$encodedArgs'))))" ) - - $process = Start-Process PowerShell -ArgumentList $startArgs ` + + $process = Start-Process -FilePath "$PSHOME\pwsh.exe" -ArgumentList $startArgs ` -Verb RunAs -Wait -PassThru -WindowStyle Hidden -ErrorAction Stop - + if ($process.ExitCode -ne 0) { throw "Elevated command failed with exit code $($process.ExitCode)" } @@ -193,7 +193,7 @@ function Uninstall-App { if($package) { $pfn = $package.PackageFullName - + # SDL FIX: Direct cmdlet invocation instead of Invoke-Expression try { Remove-AppxPackage $pfn -ErrorAction Stop @@ -236,7 +236,7 @@ function IsElevated { #> function EnableDevmode { $RegistryKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" - + # Create registry key if it doesn't exist if (-not(Test-Path -Path $RegistryKeyPath)) { if (!(IsElevated)) { @@ -266,7 +266,7 @@ function EnableDevmode { Set-ItemProperty -Path $RegistryKeyPath -Name AllowDevelopmentWithoutDevLicense -Value 1 -ErrorAction Stop } } - + # SDL FIX: Direct cmdlet invocation for AllowAllTrustedApps $value = Get-ItemProperty -Path $RegistryKeyPath -Name AllowAllTrustedApps -ErrorAction SilentlyContinue if (($value -eq $null) -or ($value.AllowAllTrustedApps -ne 1)) { @@ -339,12 +339,12 @@ function Install-App { [string] $Path, <# Full path to Add-AppDevPackage.ps1 #> [switch] $Force = $false ) - + # SDL FIX: Validate script path $Path = Validate-ScriptPath -Path $Path - + $needInstallCertificate = CheckIfNeedInstallCertificate (Join-Path $Path "..") - + if (!$Force -and ((CheckIfNeedDeveloperLicense) -or ($needInstallCertificate))) { # SDL FIX: Use call operator (&) instead of Invoke-Expression @@ -434,15 +434,15 @@ function Install-AppDependencies { param( [Parameter(Mandatory=$true)] [string]$AppxManifestPath, [Parameter(Mandatory=$true)] [string]$AppPackagePath, - [Parameter(Mandatory=$true)] [string]$Architecture + [Parameter(Mandatory=$true)] [string]$Architecture ) $xml=[xml] (gc $AppxManifestPath); - $packageNamesToInstall = $xml.Package.Dependencies.PackageDependency | - Where-Object { + $packageNamesToInstall = $xml.Package.Dependencies.PackageDependency | + Where-Object { $installed = Get-AppxPackage $_.Name | Where-Object -Property Architecture -EQ -Value $Architecture; - $installed -eq $null -or $installed.Version -lt $_.MinVersion - } | + $installed -eq $null -or $installed.Version -lt $_.MinVersion + } | % { $_.Name }; $map = Map-PackageNameToPackage $AppPackagePath\Dependencies\$Architecture $packagePaths = $packageNamesToInstall | % { $map[$_] } diff --git a/packages/@react-native-windows/cli/src/utils/commandWithProgress.ts b/packages/@react-native-windows/cli/src/utils/commandWithProgress.ts index 9ee9fe56113..b78eed125b6 100644 --- a/packages/@react-native-windows/cli/src/utils/commandWithProgress.ts +++ b/packages/@react-native-windows/cli/src/utils/commandWithProgress.ts @@ -61,7 +61,7 @@ export async function runPowerShellScriptFunction( try { const printException = verbose ? '$_;' : ''; const importAppx = useAppxCompatibility - ? 'Import-Module Appx -UseWindowsPowerShell -WarningAction SilentlyContinue; ' + ? 'Import-Module Appx -WarningAction SilentlyContinue; ' : ''; const importScript = script ? `Import-Module '${script}'; ` : ''; const powershellCommand = `${importAppx}${importScript}try { ${funcName} -ErrorAction Stop; $lec = $LASTEXITCODE; } catch { $lec = 1; ${printException} }; exit $lec`; diff --git a/packages/@react-native-windows/cli/src/utils/deploy.ts b/packages/@react-native-windows/cli/src/utils/deploy.ts index b3e0e28002c..3c71c2b4694 100644 --- a/packages/@react-native-windows/cli/src/utils/deploy.ts +++ b/packages/@react-native-windows/cli/src/utils/deploy.ts @@ -465,7 +465,7 @@ export async function deployToDesktop( } const appFamilyNameCommand = useAppxCompatibility - ? `& { Import-Module Appx -UseWindowsPowerShell -WarningAction SilentlyContinue; (Get-AppxPackage -Name '${appName}').PackageFamilyName }` + ? `& { Import-Module Appx -WarningAction SilentlyContinue; (Get-AppxPackage -Name '${appName}').PackageFamilyName }` : `(Get-AppxPackage -Name '${appName}').PackageFamilyName`; const appFamilyName = execFileSync(findPowerShell(), [ '-NoProfile', diff --git a/packages/@react-native-windows/cli/src/utils/msbuildtools.ts b/packages/@react-native-windows/cli/src/utils/msbuildtools.ts index 859ef8c28e9..82bbe56d16e 100644 --- a/packages/@react-native-windows/cli/src/utils/msbuildtools.ts +++ b/packages/@react-native-windows/cli/src/utils/msbuildtools.ts @@ -202,7 +202,7 @@ export default class MSBuildTools { const minVersion = process.env.MinimumVisualStudioVersion || process.env.VisualStudioVersion || - '17.11.0'; + '18.6.0'; const vsInstallation = findLatestVsInstall({ requires, minVersion, diff --git a/packages/@react-native-windows/cli/src/utils/vsInstalls.ts b/packages/@react-native-windows/cli/src/utils/vsInstalls.ts index 1d529177d89..856cb052f7e 100644 --- a/packages/@react-native-windows/cli/src/utils/vsInstalls.ts +++ b/packages/@react-native-windows/cli/src/utils/vsInstalls.ts @@ -82,12 +82,12 @@ export function enumerateVsInstalls(opts: { if (minVersionSemVer) { minVersion = minVersionSemVer.toString(); - maxVersion = `${minVersionSemVer.major + 2}.0`; + maxVersion = `${minVersionSemVer.major + 1}.0`; } else if (!Number.isNaN(minVersionNum)) { minVersion = Number.isInteger(minVersionNum) ? `${minVersionNum}.0` : minVersionNum.toString(); - maxVersion = `${Math.floor(minVersionNum) + 2}.0`; + maxVersion = `${Math.floor(minVersionNum) + 1}.0`; } else { // Unable to parse minVersion and determine maxVersion, // caller will throw error that version couldn't be found. diff --git a/packages/@rnw-scripts/fork-sync/bin.js b/packages/@rnw-scripts/fork-sync/bin.js old mode 100644 new mode 100755 diff --git a/packages/@rnw-scripts/just-task/nuget-restore-task.js b/packages/@rnw-scripts/just-task/nuget-restore-task.js index 97da9d6e163..efffde2eb88 100644 --- a/packages/@rnw-scripts/just-task/nuget-restore-task.js +++ b/packages/@rnw-scripts/just-task/nuget-restore-task.js @@ -114,7 +114,7 @@ function findVsDevCmd() { if (!fs.existsSync(vsWherePath)) { throw new Error( - 'vswhere.exe not found. Install Visual Studio 2022 (or Build Tools).', + 'vswhere.exe not found. Install Visual Studio 2026 (or Build Tools).', ); } diff --git a/packages/e2e-test-app-fabric/test/LegacySelectableTextTest.test.ts b/packages/e2e-test-app-fabric/test/LegacySelectableTextTest.test.ts index 7d9cc4fdb27..12beaa8ec91 100644 --- a/packages/e2e-test-app-fabric/test/LegacySelectableTextTest.test.ts +++ b/packages/e2e-test-app-fabric/test/LegacySelectableTextTest.test.ts @@ -53,12 +53,13 @@ describe('LegacySelectableTextTest', () => { const textExample = await app.findElementByTestID('text-example'); await textExample.doubleClick(); const dump = await dumpVisualTree('pressed-state'); - if (dump.Text === 'Pressed: 2 times.') { + const automationTree = dump['Automation Tree'] as Record; + if (automationTree['Name'] === 'Pressed: 1 times.') { // Due to the hardcoded speed between clicks in WinAppDriver, this test - // can be flaky on Windows Server 2022. Detect and warn here rather than - // disabling the entire test. - console.warn('DoubleClickWhenSelectable registered two clicks.'); - dump.Text = 'Pressed: 1 times.'; + // can be flaky. Detect and warn here rather than disabling the entire test. + console.warn('DoubleClickWhenSelectable registered only one click.'); + automationTree['Name'] = 'Pressed: 2 times.'; + automationTree['TextRangePattern.GetText'] = 'Pressed: 2 times.'; } expect(dump).toMatchSnapshot(); }); diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap index b8ebbbd8f27..2da83e4e4aa 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextComponentTest.test.ts.snap @@ -306,7 +306,7 @@ exports[`Text Tests Text can have a customized selection color 1`] = ` "Visual Tree": { "Comment": "text-selection-color", "Offset": "0, 0, 0", - "Size": "916, 20", + "Size": "916, 19", "Visual Type": "SpriteVisual", }, } @@ -675,7 +675,7 @@ exports[`Text Tests Text can have an outer color 1`] = ` "Visual Tree": { "Comment": "text-outer-color", "Offset": "0, 0, 0", - "Size": "916, 19", + "Size": "916, 20", "Visual Type": "SpriteVisual", }, } @@ -799,12 +799,12 @@ exports[`Text Tests Text can have borders 1`] = ` }, { "Offset": "100, 127, 0", - "Size": "716, 139", + "Size": "716, 138", "Visual Type": "SpriteVisual", "__Children": [ { "Offset": "0, 0, 0", - "Size": "716, 139", + "Size": "716, 138", "Visual Type": "SpriteVisual", "__Children": [ { @@ -853,12 +853,12 @@ exports[`Text Tests Text can have borders 1`] = ` }, { "Offset": "0, 365, 0", - "Size": "916, 19", + "Size": "916, 20", "Visual Type": "SpriteVisual", "__Children": [ { "Offset": "0, 0, 0", - "Size": "916, 19", + "Size": "916, 20", "Visual Type": "SpriteVisual", }, ], @@ -910,7 +910,7 @@ exports[`Text Tests Text can have decoration lines: Underline 1`] = ` "Visual Tree": { "Comment": "text-decoration-underline", "Offset": "0, 0, 0", - "Size": "916, 19", + "Size": "916, 20", "Visual Type": "SpriteVisual", }, } @@ -953,7 +953,7 @@ exports[`Text Tests Text can have inline views/images 1`] = ` "Visual Tree": { "Comment": "text-view", "Offset": "0, 0, 0", - "Size": "916, 26", + "Size": "916, 27", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1244,7 +1244,7 @@ exports[`Text Tests Texts can clip inline View/Images 1`] = ` "Visual Tree": { "Comment": "text-view-images-clipped", "Offset": "0, 0, 0", - "Size": "916, 223", + "Size": "916, 222", "Visual Type": "SpriteVisual", "__Children": [ { diff --git a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap index 6b855e6a574..1d7849b4b33 100644 --- a/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap +++ b/packages/e2e-test-app-fabric/test/__snapshots__/TextInputComponentTest.test.ts.snap @@ -1373,7 +1373,7 @@ exports[`TextInput Tests TextInputs can be editable 1`] = ` "Visual Tree": { "Comment": "textinput-editable", "Offset": "0, 0, 0", - "Size": "916, 29", + "Size": "916, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -1986,7 +1986,7 @@ exports[`TextInput Tests TextInputs can clear on submit with custom submit key e "Visual Tree": { "Comment": "textinput-clear-on-submit-2", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -2601,7 +2601,7 @@ exports[`TextInput Tests TextInputs can have a font weight 1`] = ` "Visual Tree": { "Comment": "style-fontWeight", "Offset": "0, 0, 0", - "Size": "791, 29", + "Size": "791, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3381,7 +3381,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, search 1`] "Visual Tree": { "Comment": "textinput-return-search", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3459,7 +3459,7 @@ exports[`TextInput Tests TextInputs can have custom return key type, send 1`] = "Visual Tree": { "Comment": "textinput-return-send", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -3944,7 +3944,7 @@ exports[`TextInput Tests TextInputs can have customized letter spacing 1`] = ` "Visual Tree": { "Comment": "style-letterSpacing", "Offset": "0, 0, 0", - "Size": "791, 28", + "Size": "791, 29", "Visual Type": "SpriteVisual", "__Children": [ { @@ -4487,7 +4487,7 @@ exports[`TextInput Tests TextInputs can have text shadows 1`] = ` "Visual Tree": { "Comment": "style-textShadow", "Offset": "0, 0, 0", - "Size": "791, 29", + "Size": "791, 28", "Visual Type": "SpriteVisual", "__Children": [ { @@ -4945,7 +4945,7 @@ exports[`TextInput Tests TextInputs can select text on focus 1`] = ` "Visual Tree": { "Comment": "select-text-on-focus", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5253,7 +5253,7 @@ exports[`TextInput Tests TextInputs have a custom background color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-background-color", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5330,7 +5330,7 @@ exports[`TextInput Tests TextInputs have a custom highlight color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-highlight-color", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5408,7 +5408,7 @@ exports[`TextInput Tests TextInputs have a custom placeholder text color 1`] = ` "Visual Tree": { "Comment": "textinput-custom-placeholder-color", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5641,7 +5641,7 @@ exports[`TextInput Tests TextInputs have a default placeholder text color 1`] = "Visual Tree": { "Comment": "textinput-default-placeholder-color", "Offset": "0, 0, 0", - "Size": "916, 33", + "Size": "916, 32", "Visual Type": "SpriteVisual", "__Children": [ { @@ -5718,7 +5718,7 @@ exports[`TextInput Tests TextInputs have a default text color 1`] = ` "Visual Tree": { "Comment": "textinput-default-color", "Offset": "0, 0, 0", - "Size": "916, 32", + "Size": "916, 33", "Visual Type": "SpriteVisual", "__Children": [ { diff --git a/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.vcxproj b/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.vcxproj index 00e3171ff85..d45349c7694 100644 --- a/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.vcxproj +++ b/packages/e2e-test-app-fabric/windows/RNTesterApp-Fabric/RNTesterApp-Fabric.vcxproj @@ -47,7 +47,7 @@ Application Unicode - v143 + v145 true diff --git a/packages/playground/windows/playground-composition/Playground-Composition.vcxproj b/packages/playground/windows/playground-composition/Playground-Composition.vcxproj index 20d8539ffd8..76b46132816 100644 --- a/packages/playground/windows/playground-composition/Playground-Composition.vcxproj +++ b/packages/playground/windows/playground-composition/Playground-Composition.vcxproj @@ -54,7 +54,7 @@ Application Unicode - $(DefaultPlatformToolset) + v145 true diff --git a/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.vcxproj b/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.vcxproj index c3b4020e7b0..ce85893aec2 100644 --- a/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.vcxproj +++ b/packages/sample-app-fabric/windows/SampleAppFabric/SampleAppFabric.vcxproj @@ -48,7 +48,7 @@ Application Unicode - v143 + v145 true diff --git a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj index 4a070673193..de975e187f2 100644 --- a/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj +++ b/packages/sample-custom-component/windows/SampleCustomComponent/SampleCustomComponent.vcxproj @@ -48,7 +48,7 @@ DynamicLibrary Unicode - $(DefaultPlatformToolset) + v145 false diff --git a/vnext/Desktop/React.Windows.Desktop.vcxproj b/vnext/Desktop/React.Windows.Desktop.vcxproj index 1dddc0a9ad4..c559cae4096 100644 --- a/vnext/Desktop/React.Windows.Desktop.vcxproj +++ b/vnext/Desktop/React.Windows.Desktop.vcxproj @@ -45,7 +45,7 @@ React.Windows.Desktop Microsoft.ReactNative en-US - 17.0 + 18.0 C++/WinRT 2 true diff --git a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/AnalysisTestBase.cs b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/AnalysisTestBase.cs index d56ca634bb7..0b2bd56cf3e 100644 --- a/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/AnalysisTestBase.cs +++ b/vnext/Microsoft.ReactNative.Managed.CodeGen.UnitTests/AnalysisTestBase.cs @@ -71,7 +71,7 @@ public class TestClass var microsoftNetCoreUwpPkgFolder = Path.Combine(uwpPath, microsoftNetCoreUwpPkgVersion.ToString(), "ref", uapVersion); if (!Directory.Exists(microsoftNetCoreUwpPkgFolder)) { - Assert.Fail($"Could not find path {microsoftNetCoreUwpPkgFolder}. This should have been installed as part of the UWP workload for Microsoft Visual Studio 2022 version 17.0"); + Assert.Fail($"Could not find path {microsoftNetCoreUwpPkgFolder}. This should have been installed as part of the UWP workload for Microsoft Visual Studio 2026 version 18.0"); } references.AddRange(Directory.EnumerateFiles(microsoftNetCoreUwpPkgFolder, "*.dll")); diff --git a/vnext/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj b/vnext/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj index 2219b23fddf..6f86d621885 100644 --- a/vnext/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj +++ b/vnext/Microsoft.ReactNative.Managed/Microsoft.ReactNative.Managed.csproj @@ -15,7 +15,7 @@ UAP 10.0.22621.0 10.0.17763.0 - 17.0 + 18.0 512 {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} bin\$(Platform)\$(Configuration)\Microsoft.ReactNative.Managed.XML @@ -150,8 +150,8 @@ - - 17.0 + + 18.0 diff --git a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj index 4502a7a703b..68252ab0e33 100644 --- a/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +++ b/vnext/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj @@ -10,7 +10,7 @@ Microsoft.ReactNative Microsoft.ReactNative en-US - 17.0 + 18.0 true Windows Store 10.0 diff --git a/vnext/Scripts/JustMyXaml.ps1 b/vnext/Scripts/JustMyXaml.ps1 index 1e0e475b488..048fcb14ef0 100644 --- a/vnext/Scripts/JustMyXaml.ps1 +++ b/vnext/Scripts/JustMyXaml.ps1 @@ -1,4 +1,4 @@ -# This script enables or disables VS 2022's JustMyXaml feature +# This script enables or disables VS 2026's JustMyXaml feature [CmdletBinding()] param([bool]$Enable) @@ -7,14 +7,14 @@ if (!([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups } $instanceId = & "$(${env:ProgramFiles(x86)})\Microsoft Visual Studio\Installer\vswhere.exe" -property instanceId -$hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\17.0_$instanceId\privateregistry.bin" -& reg.exe load HKLM\VS2022_HIVE $hiveFile | Out-Null -New-PSDrive -Name VS2022 -PSProvider Registry -Root HKLM\VS2022_HIVE -ErrorAction Stop | Out-Null -$currentValue = (Get-ItemProperty VS2022:\Software\Microsoft\VisualStudio\17.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml +$hiveFile = "$($env:LocalAppData)\Microsoft\VisualStudio\18.0_$instanceId\privateregistry.bin" +& reg.exe load HKLM\VS2026_HIVE $hiveFile | Out-Null +New-PSDrive -Name VS2026 -PSProvider Registry -Root HKLM\VS2026_HIVE -ErrorAction Stop | Out-Null +$currentValue = (Get-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml).EnableXamlVisualDiagnosticsJustMyXaml if ($currentValue -eq 0) { $currentValue = $false; } else { $currentValue = $true; } Write-Host "Current value: $currentValue" if ($Enable) { $newValue = 1; } else { $newValue = 0; } -Set-ItemProperty VS2022:\Software\Microsoft\VisualStudio\17.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord +Set-ItemProperty VS2026:\Software\Microsoft\VisualStudio\18.0_$instanceId\Debugger -Name EnableXamlVisualDiagnosticsJustMyXaml -Value $newValue -Type DWord Write-Host "New value: $Enable" -Remove-PSDrive -Name VS2022 -& reg.exe unload HKLM\VS2022_HIVE | Out-Null +Remove-PSDrive -Name VS2026 +& reg.exe unload HKLM\VS2026_HIVE | Out-Null diff --git a/vnext/Scripts/UnitTest.ps1 b/vnext/Scripts/UnitTest.ps1 index 010e114948c..643658f685b 100644 --- a/vnext/Scripts/UnitTest.ps1 +++ b/vnext/Scripts/UnitTest.ps1 @@ -23,7 +23,9 @@ param ( "ReactCommon.UnitTests\ReactCommon.UnitTests.exe") ), - [System.IO.FileInfo] $VsTest = "${env:ProgramFiles}\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" + [System.IO.FileInfo] $VsTest = + "$(& "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)\" + + "Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" ) if ($Include.Count) { diff --git a/vnext/templates/cpp-app/windows/MyApp/MyApp.vcxproj b/vnext/templates/cpp-app/windows/MyApp/MyApp.vcxproj index 5da9e535819..0d97ed43fa4 100644 --- a/vnext/templates/cpp-app/windows/MyApp/MyApp.vcxproj +++ b/vnext/templates/cpp-app/windows/MyApp/MyApp.vcxproj @@ -50,7 +50,7 @@ Application Unicode - v143 + v145 true diff --git a/vnext/templates/cpp-lib/windows/MyLib/MyLib.vcxproj b/vnext/templates/cpp-lib/windows/MyLib/MyLib.vcxproj index ba68cffa9de..95b548f7e74 100644 --- a/vnext/templates/cpp-lib/windows/MyLib/MyLib.vcxproj +++ b/vnext/templates/cpp-lib/windows/MyLib/MyLib.vcxproj @@ -49,7 +49,7 @@ DynamicLibrary Unicode - v143 + v145 false