react-native-windows 0.81.0-preview.1 → 0.81.0-preview.6

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.
@@ -814,6 +814,25 @@ void ScrollViewComponentView::updateProps(
814
814
  }
815
815
  m_scrollVisual.SetSnapPoints(newViewProps.snapToStart, newViewProps.snapToEnd, snapToOffsets.GetView());
816
816
  }
817
+
818
+ if (!oldProps || oldViewProps.pagingEnabled != newViewProps.pagingEnabled) {
819
+ m_scrollVisual.PagingEnabled(newViewProps.pagingEnabled);
820
+ }
821
+
822
+ if (!oldProps || oldViewProps.snapToInterval != newViewProps.snapToInterval) {
823
+ m_scrollVisual.SnapToInterval(static_cast<float>(newViewProps.snapToInterval));
824
+ }
825
+
826
+ if (!oldProps || oldViewProps.snapToAlignment != newViewProps.snapToAlignment) {
827
+ using SnapPointsAlignment = winrt::Microsoft::ReactNative::Composition::Experimental::SnapPointsAlignment;
828
+ SnapPointsAlignment alignment = SnapPointsAlignment::Near; // default is "start"
829
+ if (newViewProps.snapToAlignment == facebook::react::ScrollViewSnapToAlignment::Center) {
830
+ alignment = SnapPointsAlignment::Center;
831
+ } else if (newViewProps.snapToAlignment == facebook::react::ScrollViewSnapToAlignment::End) {
832
+ alignment = SnapPointsAlignment::Far;
833
+ }
834
+ m_scrollVisual.SnapToAlignment(alignment);
835
+ }
817
836
  }
818
837
 
819
838
  void ScrollViewComponentView::updateState(
@@ -697,10 +697,17 @@ void WindowsTextInputComponentView::OnPointerPressed(
697
697
  }
698
698
 
699
699
  if (m_textServices && msg) {
700
- LRESULT lresult;
701
- DrawBlock db(*this);
702
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
703
- args.Handled(hr != S_FALSE);
700
+ if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
701
+ ShowContextMenu(position);
702
+ args.Handled(true);
703
+ } else if (msg == WM_RBUTTONUP && windowsTextInputProps().contextMenuHidden) {
704
+ args.Handled(true);
705
+ } else {
706
+ LRESULT lresult;
707
+ DrawBlock db(*this);
708
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
709
+ args.Handled(hr != S_FALSE);
710
+ }
704
711
  }
705
712
 
706
713
  // Emits the OnPressIn event
@@ -844,8 +851,8 @@ void WindowsTextInputComponentView::OnPointerWheelChanged(
844
851
  }
845
852
  void WindowsTextInputComponentView::OnKeyDown(
846
853
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
847
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
848
- // behavior We do forward Ctrl+Tab to the textinput.
854
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
855
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
849
856
  if (args.Key() != winrt::Windows::System::VirtualKey::Tab ||
850
857
  (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
851
858
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down) {
@@ -872,8 +879,8 @@ void WindowsTextInputComponentView::OnKeyDown(
872
879
 
873
880
  void WindowsTextInputComponentView::OnKeyUp(
874
881
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept {
875
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
876
- // behavior We do forward Ctrl+Tab to the textinput.
882
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
883
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
877
884
  if (args.Key() != winrt::Windows::System::VirtualKey::Tab ||
878
885
  (args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
879
886
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) == winrt::Microsoft::UI::Input::VirtualKeyStates::Down) {
@@ -943,8 +950,8 @@ bool WindowsTextInputComponentView::ShouldSubmit(
943
950
 
944
951
  void WindowsTextInputComponentView::OnCharacterReceived(
945
952
  const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs &args) noexcept {
946
- // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with WinUI
947
- // behavior We do forward Ctrl+Tab to the textinput.
953
+ // Do not forward tab keys into the TextInput, since we want that to do the tab loop instead. This aligns with
954
+ // WinUI behavior We do forward Ctrl+Tab to the textinput.
948
955
  if ((args.KeyCode() == '\t') &&
949
956
  ((args.KeyboardSource().GetKeyState(winrt::Windows::System::VirtualKey::Control) &
950
957
  winrt::Microsoft::UI::Input::VirtualKeyStates::Down) != winrt::Microsoft::UI::Input::VirtualKeyStates::Down)) {
@@ -1547,25 +1554,59 @@ void WindowsTextInputComponentView::UpdateParaFormat() noexcept {
1547
1554
  m_pf.dwMask = PFM_ALL;
1548
1555
 
1549
1556
  auto &textAlign = windowsTextInputProps().textAlign;
1557
+ auto &baseWritingDirection = windowsTextInputProps().textAttributes.baseWritingDirection;
1558
+
1559
+ // Handle writingDirection (baseWritingDirection)
1560
+ // For WritingDirection::Natural, use the computed layout direction from the layout tree
1561
+ // since direction can be overridden at any point in the tree
1562
+ bool isRTL = false;
1563
+ if (baseWritingDirection.has_value()) {
1564
+ if (*baseWritingDirection == facebook::react::WritingDirection::RightToLeft) {
1565
+ isRTL = true;
1566
+ m_pf.dwMask |= PFM_RTLPARA;
1567
+ m_pf.wEffects |= PFE_RTLPARA;
1568
+ } else if (*baseWritingDirection == facebook::react::WritingDirection::LeftToRight) {
1569
+ isRTL = false;
1570
+ // Ensure RTL flag is not set
1571
+ m_pf.wEffects &= ~PFE_RTLPARA;
1572
+ } else if (*baseWritingDirection == facebook::react::WritingDirection::Natural) {
1573
+ // Natural uses the layout direction computed from the tree
1574
+ isRTL = (layoutMetrics().layoutDirection == facebook::react::LayoutDirection::RightToLeft);
1575
+ if (isRTL) {
1576
+ m_pf.dwMask |= PFM_RTLPARA;
1577
+ m_pf.wEffects |= PFE_RTLPARA;
1578
+ } else {
1579
+ m_pf.wEffects &= ~PFE_RTLPARA;
1580
+ }
1581
+ }
1582
+ } else {
1583
+ // No explicit writing direction set - use layout direction from tree
1584
+ isRTL = (layoutMetrics().layoutDirection == facebook::react::LayoutDirection::RightToLeft);
1585
+ if (isRTL) {
1586
+ m_pf.dwMask |= PFM_RTLPARA;
1587
+ m_pf.wEffects |= PFE_RTLPARA;
1588
+ } else {
1589
+ m_pf.wEffects &= ~PFE_RTLPARA;
1590
+ }
1591
+ }
1550
1592
 
1593
+ // Handle textAlign
1551
1594
  if (textAlign == facebook::react::TextAlignment::Center) {
1552
1595
  m_pf.wAlignment = PFA_CENTER;
1553
1596
  } else if (textAlign == facebook::react::TextAlignment::Right) {
1554
1597
  m_pf.wAlignment = PFA_RIGHT;
1598
+ } else if (textAlign == facebook::react::TextAlignment::Justified) {
1599
+ m_pf.wAlignment = PFA_JUSTIFY;
1600
+ } else if (textAlign == facebook::react::TextAlignment::Natural) {
1601
+ // Natural alignment respects writing direction
1602
+ m_pf.wAlignment = isRTL ? PFA_RIGHT : PFA_LEFT;
1555
1603
  } else {
1604
+ // Default to left alignment
1556
1605
  m_pf.wAlignment = PFA_LEFT;
1557
1606
  }
1558
1607
 
1559
1608
  m_pf.cTabCount = 1;
1560
1609
  m_pf.rgxTabs[0] = lDefaultTab;
1561
-
1562
- /*
1563
- if (m_spcontroller->IsCurrentReadingOrderRTL())
1564
- {
1565
- m_pf.dwMask |= PFM_RTLPARA;
1566
- m_pf.wEffects |= PFE_RTLPARA;
1567
- }
1568
- */
1569
1610
  }
1570
1611
 
1571
1612
  void WindowsTextInputComponentView::OnRenderingDeviceLost() noexcept {
@@ -1826,4 +1867,47 @@ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1826
1867
  winrt::check_hresult(
1827
1868
  m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1828
1869
  }
1870
+
1871
+ void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept {
1872
+ HMENU menu = CreatePopupMenu();
1873
+ if (!menu)
1874
+ return;
1875
+
1876
+ CHARRANGE selection;
1877
+ LRESULT res;
1878
+ m_textServices->TxSendMessage(EM_EXGETSEL, 0, reinterpret_cast<LPARAM>(&selection), &res);
1879
+
1880
+ bool hasSelection = selection.cpMin != selection.cpMax;
1881
+ bool isEmpty = GetTextFromRichEdit().empty();
1882
+ bool isReadOnly = windowsTextInputProps().editable == false;
1883
+ bool canPaste = !isReadOnly && IsClipboardFormatAvailable(CF_UNICODETEXT);
1884
+
1885
+ AppendMenuW(menu, MF_STRING | (hasSelection && !isReadOnly ? 0 : MF_GRAYED), 1, L"Cut");
1886
+ AppendMenuW(menu, MF_STRING | (hasSelection ? 0 : MF_GRAYED), 2, L"Copy");
1887
+ AppendMenuW(menu, MF_STRING | (canPaste ? 0 : MF_GRAYED), 3, L"Paste");
1888
+ AppendMenuW(menu, MF_STRING | (!isEmpty && !isReadOnly ? 0 : MF_GRAYED), 4, L"Select All");
1889
+
1890
+ POINT cursorPos;
1891
+ GetCursorPos(&cursorPos);
1892
+
1893
+ HWND hwnd = GetActiveWindow();
1894
+
1895
+ int cmd = TrackPopupMenu(
1896
+ menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY, cursorPos.x, cursorPos.y, 0, hwnd, NULL);
1897
+
1898
+ if (cmd == 1) { // Cut
1899
+ m_textServices->TxSendMessage(WM_CUT, 0, 0, &res);
1900
+ OnTextUpdated();
1901
+ } else if (cmd == 2) { // Copy
1902
+ m_textServices->TxSendMessage(WM_COPY, 0, 0, &res);
1903
+ } else if (cmd == 3) { // Paste
1904
+ m_textServices->TxSendMessage(WM_PASTE, 0, 0, &res);
1905
+ OnTextUpdated();
1906
+ } else if (cmd == 4) { // Select All
1907
+ m_textServices->TxSendMessage(EM_SETSEL, 0, -1, &res);
1908
+ }
1909
+
1910
+ DestroyMenu(menu);
1911
+ }
1912
+
1829
1913
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -118,6 +118,7 @@ struct WindowsTextInputComponentView
118
118
  void updateLetterSpacing(float letterSpacing) noexcept;
119
119
  void updateAutoCorrect(bool value) noexcept;
120
120
  void updateSpellCheck(bool value) noexcept;
121
+ void ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept;
121
122
 
122
123
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
123
124
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
@@ -136,6 +136,25 @@ void WindowsTextLayoutManager::GetTextLayout(
136
136
  outerFragment.textAttributes.lineHeight * 0.8f));
137
137
  }
138
138
 
139
+ // Set reading direction (RTL/LTR) based on baseWritingDirection
140
+ // Only set reading direction if explicitly specified to avoid breaking existing layouts
141
+ bool isRTL = false;
142
+ if (outerFragment.textAttributes.baseWritingDirection.has_value()) {
143
+ DWRITE_READING_DIRECTION readingDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
144
+ if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::RightToLeft) {
145
+ readingDirection = DWRITE_READING_DIRECTION_RIGHT_TO_LEFT;
146
+ isRTL = true;
147
+ } else if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::LeftToRight) {
148
+ readingDirection = DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
149
+ isRTL = false;
150
+ } else if (*outerFragment.textAttributes.baseWritingDirection == facebook::react::WritingDirection::Natural) {
151
+ // Natural uses the layout direction from textAttributes
152
+ isRTL = (outerFragment.textAttributes.layoutDirection == facebook::react::LayoutDirection::RightToLeft);
153
+ readingDirection = isRTL ? DWRITE_READING_DIRECTION_RIGHT_TO_LEFT : DWRITE_READING_DIRECTION_LEFT_TO_RIGHT;
154
+ }
155
+ winrt::check_hresult(spTextFormat->SetReadingDirection(readingDirection));
156
+ }
157
+
139
158
  // Set text alignment
140
159
  DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
141
160
  if (outerFragment.textAttributes.alignment) {
@@ -152,9 +171,9 @@ void WindowsTextLayoutManager::GetTextLayout(
152
171
  case facebook::react::TextAlignment::Right:
153
172
  alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
154
173
  break;
155
- // TODO use LTR values
156
174
  case facebook::react::TextAlignment::Natural:
157
- alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
175
+ // Natural alignment respects reading direction if baseWritingDirection was set
176
+ alignment = isRTL ? DWRITE_TEXT_ALIGNMENT_TRAILING : DWRITE_TEXT_ALIGNMENT_LEADING;
158
177
  break;
159
178
  default:
160
179
  assert(false);
@@ -310,10 +310,6 @@ class ReactNativeWindowsFeatureFlags : public facebook::react::ReactNativeFeatur
310
310
  bool fuseboxEnabledRelease() override {
311
311
  return true; // Enable Fusebox (modern CDP backend) by default for React Native Windows
312
312
  }
313
-
314
- bool fuseboxNetworkInspectionEnabled() override {
315
- return true; // Enable network inspection support in Fusebox
316
- }
317
313
  };
318
314
 
319
315
  //=============================================================================================
@@ -326,10 +322,32 @@ class ReactInspectorHostTargetDelegate : public jsinspector_modern::HostTargetDe
326
322
  ReactInspectorHostTargetDelegate(Mso::WeakPtr<ReactHost> &&reactHost) noexcept : m_reactHost(std::move(reactHost)) {}
327
323
 
328
324
  jsinspector_modern::HostTargetMetadata getMetadata() override {
329
- // TODO: (vmoroz) provide more info
330
- return {
331
- .integrationName = "React Native Windows (Host)",
332
- };
325
+ jsinspector_modern::HostTargetMetadata metadata{};
326
+ metadata.integrationName = "React Native Windows (Host)";
327
+ metadata.platform = "windows";
328
+
329
+ if (Mso::CntPtr<ReactHost> reactHost = m_reactHost.GetStrongPtr()) {
330
+ const ReactOptions &options = reactHost->Options();
331
+ if (!options.Identity.empty()) {
332
+ std::string identity = options.Identity;
333
+ // Replace illegal characters with underscore
334
+ for (char &c : identity) {
335
+ if (c == '\\' || c == '/' || c == ':' || c == '*' || c == '?' || c == '"' || c == '<' || c == '>' ||
336
+ c == '|') {
337
+ c = '_';
338
+ }
339
+ }
340
+ metadata.appDisplayName = identity;
341
+ }
342
+ }
343
+
344
+ wchar_t computerName[MAX_COMPUTERNAME_LENGTH + 1];
345
+ DWORD size = MAX_COMPUTERNAME_LENGTH + 1;
346
+ if (GetComputerNameW(computerName, &size)) {
347
+ metadata.deviceName = winrt::to_string(computerName);
348
+ }
349
+
350
+ return metadata;
333
351
  }
334
352
 
335
353
  void onReload(jsinspector_modern::HostTargetDelegate::PageReloadRequest const &request) override {
@@ -630,9 +648,20 @@ void ReactHost::AddInspectorPage() noexcept {
630
648
  jsinspector_modern::InspectorTargetCapabilities capabilities;
631
649
  capabilities.nativePageReloads = true;
632
650
  capabilities.prefersFuseboxFrontend = true;
633
- // TODO: (vmoroz) improve the page name
651
+
652
+ auto metadata = m_inspectorHostTargetDelegate->getMetadata();
653
+ std::string pageName;
654
+ if (metadata.appDisplayName.has_value() && !metadata.appDisplayName.value().empty()) {
655
+ pageName = metadata.appDisplayName.value();
656
+ } else {
657
+ pageName = "React Native Windows (Experimental)";
658
+ }
659
+ if (metadata.deviceName.has_value() && !metadata.deviceName.value().empty()) {
660
+ pageName += " (" + metadata.deviceName.value() + ")";
661
+ }
662
+
634
663
  inspectorPageId = jsinspector_modern::getInspectorInstance().addPage(
635
- "React Native Windows (Experimental)",
664
+ pageName,
636
665
  "Hermes",
637
666
  [weakInspectorHostTarget =
638
667
  std::weak_ptr(m_inspectorHostTarget)](std::unique_ptr<jsinspector_modern::IRemoteConnection> remote)
@@ -10,11 +10,11 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.81.0-preview.1</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.81.0-preview.6</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>81</ReactNativeWindowsMinor>
16
16
  <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
- <ReactNativeWindowsCommitId>c90943314678ce91d624ceba523e50f8d35a5ea5</ReactNativeWindowsCommitId>
18
+ <ReactNativeWindowsCommitId>15b72b3f2121e6f7d3d8aabff5e7f1f26e989829</ReactNativeWindowsCommitId>
19
19
  </PropertyGroup>
20
20
  </Project>
@@ -146,6 +146,7 @@
146
146
  <AdditionalIncludeDirectories>
147
147
  $(FollyDir);
148
148
  $(FmtDir)include;
149
+ $(FastFloatDir)include;
149
150
  $(ReactNativeDir)\ReactCommon;
150
151
  $(ReactNativeDir)\ReactCommon\callinvoker;
151
152
  $(ReactNativeDir)\ReactCommon\jsi;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-windows",
3
- "version": "0.81.0-preview.1",
3
+ "version": "0.81.0-preview.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,8 +2,6 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
-
7
5
  const rnwPath = fs.realpathSync(
8
6
  path.resolve(require.resolve('react-native-windows/package.json'), '..'),
9
7
  );
@@ -25,7 +23,7 @@ const config = {
25
23
  watchFolders: [rnwPath, rnwRootNodeModules, rnwPackages],
26
24
  // devMode]{{/devMode}}
27
25
  resolver: {
28
- blockList: exclusionList([
26
+ blockList: [
29
27
  // This stops "npx @react-native-community/cli run-windows" from causing the metro server to crash if its already running
30
28
  new RegExp(
31
29
  `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -34,7 +32,7 @@ const config = {
34
32
  new RegExp(`${rnwPath}/build/.*`),
35
33
  new RegExp(`${rnwPath}/target/.*`),
36
34
  /.*\.ProjectImports\.zip/,
37
- ]),
35
+ ],
38
36
  //{{#devMode}} [devMode
39
37
  extraNodeModules: {
40
38
  'react-native-windows': rnwPath,
@@ -2,8 +2,6 @@ const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
-
7
5
  const rnwPath = fs.realpathSync(
8
6
  path.resolve(require.resolve('react-native-windows/package.json'), '..'),
9
7
  );
@@ -25,7 +23,7 @@ const config = {
25
23
  watchFolders: [rnwPath, rnwRootNodeModules, rnwPackages],
26
24
  // devMode]{{/devMode}}
27
25
  resolver: {
28
- blockList: exclusionList([
26
+ blockList: [
29
27
  // This stops "npx @react-native-community/cli run-windows" from causing the metro server to crash if its already running
30
28
  new RegExp(
31
29
  `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`,
@@ -34,7 +32,7 @@ const config = {
34
32
  new RegExp(`${rnwPath}/build/.*`),
35
33
  new RegExp(`${rnwPath}/target/.*`),
36
34
  /.*\.ProjectImports\.zip/,
37
- ]),
35
+ ],
38
36
  //{{#devMode}} [devMode
39
37
  extraNodeModules: {
40
38
  'react-native-windows': rnwPath,
@@ -2,7 +2,6 @@ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
4
  const escape = require('escape-string-regexp');
5
- const exclusionList = require('metro-config/src/defaults/exclusionList');
6
5
  const pack = require('../package.json');
7
6
 
8
7
  const root = path.resolve(__dirname, '..');
@@ -33,7 +32,7 @@ const config = {
33
32
  // We need to make sure that only one version is loaded for peerDependencies
34
33
  // So we block them at the root, and alias them to the versions in example's node_modules
35
34
  resolver: {
36
- blockList: exclusionList(
35
+ blockList:
37
36
  modules.map(
38
37
  (m) =>
39
38
  new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
@@ -47,7 +46,7 @@ const config = {
47
46
  new RegExp(`${rnwPath}/target/.*`),
48
47
  /.*\.ProjectImports\.zip/,
49
48
  ])
50
- ),
49
+ ,
51
50
 
52
51
  extraNodeModules: modules.reduce((acc, name) => {
53
52
  acc[name] = path.join(__dirname, 'node_modules', name);
@@ -1,232 +0,0 @@
1
- /*
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
- #pragma once
9
-
10
- #include <cmath>
11
- #include <string_view>
12
-
13
- #include <folly/../../fast_float-6.1.4/include/fast_float/fast_float.h> // [Windows] - Full relative path needed to find file
14
- #include <react/renderer/css/CSSToken.h>
15
-
16
- namespace facebook::react {
17
-
18
- /**
19
- * A minimal tokenizer for a subset of CSS syntax.
20
- *
21
- * This is based on the W3C CSS Syntax specification, with simplifications made
22
- * for syntax which React Native does not attempt to support.
23
- * https://www.w3.org/TR/css-syntax-3/#tokenizing-and-parsing
24
- */
25
- class CSSTokenizer {
26
- public:
27
- explicit constexpr CSSTokenizer(std::string_view characters)
28
- : remainingCharacters_{characters} {}
29
-
30
- /**
31
- * Returns the next token according to the algorithm described in
32
- * https://www.w3.org/TR/css-syntax-3/#consume-token
33
- */
34
- constexpr CSSToken next() {
35
- char nextChar = peek();
36
-
37
- if (isWhitespace(nextChar)) {
38
- return consumeWhitespace();
39
- }
40
-
41
- switch (nextChar) {
42
- case '(':
43
- return consumeCharacter(CSSTokenType::OpenParen);
44
- case ')':
45
- return consumeCharacter(CSSTokenType::CloseParen);
46
- case '[':
47
- return consumeCharacter(CSSTokenType::OpenSquare);
48
- case ']':
49
- return consumeCharacter(CSSTokenType::CloseSquare);
50
- case '{':
51
- return consumeCharacter(CSSTokenType::OpenCurly);
52
- case '}':
53
- return consumeCharacter(CSSTokenType::CloseCurly);
54
- case ',':
55
- return consumeCharacter(CSSTokenType::Comma);
56
- case '+':
57
- case '-':
58
- case '.':
59
- if (wouldStartNumber()) {
60
- return consumeNumeric();
61
- } else {
62
- return consumeDelim();
63
- }
64
- case '#':
65
- if (isIdent(peek(1))) {
66
- return consumeHash();
67
- } else {
68
- return consumeDelim();
69
- }
70
- }
71
-
72
- if (isDigit(nextChar)) {
73
- return consumeNumeric();
74
- }
75
-
76
- if (isIdentStart(nextChar)) {
77
- return consumeIdentlikeToken();
78
- }
79
-
80
- if (nextChar == '\0') {
81
- return CSSToken{CSSTokenType::EndOfFile};
82
- }
83
-
84
- return consumeDelim();
85
- }
86
-
87
- private:
88
- constexpr char peek(size_t i = 0) const {
89
- auto index = position_ + i;
90
- return index >= remainingCharacters_.size() ? '\0'
91
- : remainingCharacters_[index];
92
- }
93
-
94
- constexpr void advance() {
95
- position_ += 1;
96
- }
97
-
98
- constexpr CSSToken consumeDelim() {
99
- advance();
100
- return {CSSTokenType::Delim, consumeRunningValue()};
101
- }
102
-
103
- constexpr CSSToken consumeCharacter(CSSTokenType tokenType) {
104
- advance();
105
- consumeRunningValue();
106
- return CSSToken{tokenType};
107
- }
108
-
109
- constexpr CSSToken consumeWhitespace() {
110
- while (isWhitespace(peek())) {
111
- advance();
112
- }
113
-
114
- consumeRunningValue();
115
- return CSSToken{CSSTokenType::WhiteSpace};
116
- }
117
-
118
- constexpr bool wouldStartNumber() const {
119
- // https://www.w3.org/TR/css-syntax-3/#starts-with-a-number
120
- if (peek() == '+' || peek() == '-') {
121
- if (isDigit(peek(1))) {
122
- return true;
123
- }
124
- if (peek(1) == '.' && isDigit(peek(2))) {
125
- return true;
126
- }
127
- } else if (peek() == '.' && isDigit(peek(1))) {
128
- return true;
129
- } else if (isDigit(peek())) {
130
- return true;
131
- }
132
-
133
- return false;
134
- }
135
-
136
- constexpr CSSToken consumeNumber() {
137
- // https://www.w3.org/TR/css-syntax-3/#consume-number
138
- // https://www.w3.org/TR/css-syntax-3/#convert-a-string-to-a-number
139
- auto* b = remainingCharacters_.data();
140
- auto* e = b + remainingCharacters_.size();
141
-
142
- float value;
143
- fast_float::parse_options options{
144
- fast_float::chars_format::general};
145
- auto [ptr, ec] = fast_float::from_chars_advanced(b, e, value, options);
146
-
147
- consumeRunningValue();
148
- return {CSSTokenType::Number, value};
149
- }
150
-
151
- constexpr CSSToken consumeNumeric() {
152
- // https://www.w3.org/TR/css-syntax-3/#consume-numeric-token
153
- auto numberToken = consumeNumber();
154
-
155
- if (isIdent(peek())) {
156
- auto ident = consumeIdentSequence();
157
- return {
158
- CSSTokenType::Dimension,
159
- numberToken.numericValue(),
160
- ident.stringValue()};
161
- } else if (peek() == '%') {
162
- advance();
163
- consumeRunningValue();
164
- return {CSSTokenType::Percentage, numberToken.numericValue()};
165
- } else {
166
- return numberToken;
167
- }
168
- }
169
-
170
- constexpr CSSToken consumeIdentlikeToken() {
171
- // https://www.w3.org/TR/css-syntax-3/#consume-ident-like-token
172
- auto ident = consumeIdentSequence();
173
- if (peek() == '(') {
174
- advance();
175
- consumeRunningValue();
176
- return {CSSTokenType::Function, ident.stringValue()};
177
- }
178
-
179
- return ident;
180
- }
181
-
182
- constexpr CSSToken consumeIdentSequence() {
183
- // https://www.w3.org/TR/css-syntax-3/#consume-an-ident-sequence
184
- while (isIdent(peek())) {
185
- advance();
186
- }
187
-
188
- return {CSSTokenType::Ident, consumeRunningValue()};
189
- }
190
-
191
- constexpr CSSToken consumeHash() {
192
- // https://www.w3.org/TR/css-syntax-3/#consume-token (U+0023 NUMBER SIGN)
193
- advance();
194
- consumeRunningValue();
195
-
196
- return {CSSTokenType::Hash, consumeIdentSequence().stringValue()};
197
- }
198
-
199
- constexpr std::string_view consumeRunningValue() {
200
- auto next = remainingCharacters_.substr(0, position_);
201
- remainingCharacters_ = remainingCharacters_.substr(next.size());
202
- position_ = 0;
203
- return next;
204
- }
205
-
206
- static constexpr bool isDigit(char c) {
207
- // https://www.w3.org/TR/css-syntax-3/#digit
208
- return c >= '0' && c <= '9';
209
- }
210
-
211
- static constexpr bool isIdentStart(char c) {
212
- // https://www.w3.org/TR/css-syntax-3/#ident-start-code-point
213
- return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' ||
214
- static_cast<unsigned char>(c) > 0x80;
215
- }
216
-
217
- static constexpr bool isIdent(char c) {
218
- {
219
- // https://www.w3.org/TR/css-syntax-3/#ident-code-point
220
- return isIdentStart(c) || isDigit(c) || c == '-';
221
- }
222
- }
223
-
224
- static constexpr bool isWhitespace(char c) {
225
- // https://www.w3.org/TR/css-syntax-3/#whitespace
226
- return c == ' ' || c == '\t' || c == '\r' || c == '\n';
227
- }
228
-
229
- std::string_view remainingCharacters_;
230
- size_t position_{0};
231
- };
232
- } // namespace facebook::react