react-native 0.77.0 → 0.77.2
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/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Core/setUpDeveloperTools.js +2 -3
- package/Libraries/Image/Image.android.js +2 -0
- package/Libraries/Image/ImageViewNativeComponent.js +3 -4
- package/Libraries/Image/RCTImageLoader.mm +9 -1
- package/Libraries/Utilities/HMRClient.js +0 -28
- package/Libraries/Utilities/HMRClientProdShim.js +0 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/Fabric/Mounting/ComponentViews/TextInput/RCTTextInputComponentView.mm +1 -7
- package/ReactAndroid/api/ReactAndroid.api +2 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +8 -2
- package/ReactAndroid/src/main/java/com/facebook/react/fabric/mounting/MountingManager.java +15 -8
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/drawable/CompositeBackgroundDrawable.kt +9 -8
- package/ReactAndroid/src/main/java/com/facebook/react/views/image/ReactImageManager.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/TextAttributeProps.java +16 -2
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +22 -4
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +5 -0
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +51 -22
- package/ReactCommon/react/renderer/attributedstring/TextAttributes.cpp +6 -0
- package/ReactCommon/react/renderer/attributedstring/TextAttributes.h +2 -0
- package/ReactCommon/react/renderer/attributedstring/conversions.h +5 -0
- package/ReactCommon/react/renderer/components/text/BaseTextProps.cpp +12 -0
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.h +24 -3
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTAttributedTextUtils.mm +6 -46
- package/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/RCTTextLayoutManager.mm +4 -5
- package/package.json +10 -10
- package/react-native.config.js +11 -21
- package/scripts/codegen/generate-artifacts-executor.js +8 -4
- package/scripts/generate-codegen-artifacts.js +6 -1
- package/sdks/hermesc/linux64-bin/hermesc +0 -0
- package/sdks/hermesc/osx-bin/hermes +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/sdks/hermesc/win64-bin/msvcp140.dll +0 -0
- package/sdks/hermesc/win64-bin/vcruntime140.dll +0 -0
- package/sdks/hermesc/win64-bin/vcruntime140_1.dll +0 -0
|
@@ -42,9 +42,8 @@ if (__DEV__) {
|
|
|
42
42
|
if (!Platform.isTesting) {
|
|
43
43
|
const HMRClient = require('../Utilities/HMRClient');
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
} else if (console._isPolyfilled) {
|
|
45
|
+
// TODO(T214991636): Remove legacy Metro log forwarding
|
|
46
|
+
if (console._isPolyfilled) {
|
|
48
47
|
// We assume full control over the console and send JavaScript logs to Metro.
|
|
49
48
|
[
|
|
50
49
|
'trace',
|
|
@@ -133,6 +133,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef(
|
|
|
133
133
|
width: undefined,
|
|
134
134
|
height: undefined,
|
|
135
135
|
};
|
|
136
|
+
const defaultSource = resolveAssetSource(props.defaultSource);
|
|
136
137
|
const loadingIndicatorSource = resolveAssetSource(
|
|
137
138
|
props.loadingIndicatorSource,
|
|
138
139
|
);
|
|
@@ -178,6 +179,7 @@ let BaseImage: AbstractImageAndroid = React.forwardRef(
|
|
|
178
179
|
/* $FlowFixMe(>=0.78.0 site=react_native_android_fb) This issue was found
|
|
179
180
|
* when making Flow check .android.js files. */
|
|
180
181
|
headers: (source?.[0]?.headers || source?.headers: ?{[string]: string}),
|
|
182
|
+
defaultSource: defaultSource ? defaultSource.uri : null,
|
|
181
183
|
loadingIndicatorSrc: loadingIndicatorSource
|
|
182
184
|
? loadingIndicatorSource.uri
|
|
183
185
|
: null,
|
|
@@ -21,6 +21,7 @@ import type {
|
|
|
21
21
|
} from '../StyleSheet/StyleSheet';
|
|
22
22
|
import type {ResolvedAssetSource} from './AssetSourceResolver';
|
|
23
23
|
import type {ImageProps} from './ImageProps';
|
|
24
|
+
import type {ImageSource} from './ImageSource';
|
|
24
25
|
|
|
25
26
|
import * as NativeComponentRegistry from '../NativeComponent/NativeComponentRegistry';
|
|
26
27
|
import {ConditionallyIgnoredEventHandlers} from '../NativeComponent/ViewConfigIgnore';
|
|
@@ -42,7 +43,7 @@ type Props = $ReadOnly<{
|
|
|
42
43
|
| ?ResolvedAssetSource
|
|
43
44
|
| ?$ReadOnlyArray<?$ReadOnly<{uri?: ?string, ...}>>,
|
|
44
45
|
headers?: ?{[string]: string},
|
|
45
|
-
|
|
46
|
+
defaultSource?: ?ImageSource | ?string,
|
|
46
47
|
loadingIndicatorSrc?: ?string,
|
|
47
48
|
}>;
|
|
48
49
|
|
|
@@ -82,9 +83,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
|
|
|
82
83
|
},
|
|
83
84
|
validAttributes: {
|
|
84
85
|
blurRadius: true,
|
|
85
|
-
defaultSource:
|
|
86
|
-
process: require('./resolveAssetSource'),
|
|
87
|
-
},
|
|
86
|
+
defaultSource: true,
|
|
88
87
|
internal_analyticTag: true,
|
|
89
88
|
resizeMethod: true,
|
|
90
89
|
resizeMode: true,
|
|
@@ -477,7 +477,15 @@ static UIImage *RCTResizeImageIfNeeded(UIImage *image, CGSize size, CGFloat scal
|
|
|
477
477
|
|
|
478
478
|
// Add missing png extension
|
|
479
479
|
if (request.URL.fileURL && request.URL.pathExtension.length == 0) {
|
|
480
|
-
|
|
480
|
+
// Check if there exists a file with that url on disk already
|
|
481
|
+
// This should fix issue https://github.com/facebook/react-native/issues/46870
|
|
482
|
+
if ([[NSFileManager defaultManager] fileExistsAtPath:request.URL.path]) {
|
|
483
|
+
mutableRequest.URL = request.URL;
|
|
484
|
+
} else {
|
|
485
|
+
// This is the default behavior in case there is no file on disk with no extension.
|
|
486
|
+
// We assume that the extension is `png`.
|
|
487
|
+
mutableRequest.URL = [request.URL URLByAppendingPathExtension:@"png"];
|
|
488
|
+
}
|
|
481
489
|
}
|
|
482
490
|
if (_redirectDelegate != nil) {
|
|
483
491
|
mutableRequest.URL = [_redirectDelegate redirectAssetsURL:mutableRequest.URL];
|
|
@@ -26,7 +26,6 @@ let hmrUnavailableReason: string | null = null;
|
|
|
26
26
|
let currentCompileErrorMessage: string | null = null;
|
|
27
27
|
let didConnect: boolean = false;
|
|
28
28
|
let pendingLogs: Array<[LogLevel, $ReadOnlyArray<mixed>]> = [];
|
|
29
|
-
let pendingFuseboxConsoleNotification = false;
|
|
30
29
|
|
|
31
30
|
type LogLevel =
|
|
32
31
|
| 'trace'
|
|
@@ -52,7 +51,6 @@ export type HMRClientNativeInterface = {|
|
|
|
52
51
|
isEnabled: boolean,
|
|
53
52
|
scheme?: string,
|
|
54
53
|
): void,
|
|
55
|
-
unstable_notifyFuseboxConsoleEnabled(): void,
|
|
56
54
|
|};
|
|
57
55
|
|
|
58
56
|
/**
|
|
@@ -142,29 +140,6 @@ const HMRClient: HMRClientNativeInterface = {
|
|
|
142
140
|
}
|
|
143
141
|
},
|
|
144
142
|
|
|
145
|
-
unstable_notifyFuseboxConsoleEnabled() {
|
|
146
|
-
if (!hmrClient) {
|
|
147
|
-
pendingFuseboxConsoleNotification = true;
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
|
-
hmrClient.send(
|
|
151
|
-
JSON.stringify({
|
|
152
|
-
type: 'log',
|
|
153
|
-
level: 'info',
|
|
154
|
-
data: [
|
|
155
|
-
'\n' +
|
|
156
|
-
'\u001B[7m' +
|
|
157
|
-
' \u001B[1m💡 JavaScript logs have moved!\u001B[22m They can now be ' +
|
|
158
|
-
'viewed in React Native DevTools. Tip: Type \u001B[1mj\u001B[22m in ' +
|
|
159
|
-
'the terminal to open (requires Google Chrome or Microsoft Edge).' +
|
|
160
|
-
'\u001B[27m' +
|
|
161
|
-
'\n',
|
|
162
|
-
],
|
|
163
|
-
}),
|
|
164
|
-
);
|
|
165
|
-
pendingFuseboxConsoleNotification = false;
|
|
166
|
-
},
|
|
167
|
-
|
|
168
143
|
// Called once by the bridge on startup, even if Fast Refresh is off.
|
|
169
144
|
// It creates the HMR client but doesn't actually set up the socket yet.
|
|
170
145
|
setup(
|
|
@@ -341,9 +316,6 @@ function flushEarlyLogs(client: MetroHMRClient) {
|
|
|
341
316
|
pendingLogs.forEach(([level, data]) => {
|
|
342
317
|
HMRClient.log(level, data);
|
|
343
318
|
});
|
|
344
|
-
if (pendingFuseboxConsoleNotification) {
|
|
345
|
-
HMRClient.unstable_notifyFuseboxConsoleEnabled();
|
|
346
|
-
}
|
|
347
319
|
} finally {
|
|
348
320
|
pendingLogs.length = 0;
|
|
349
321
|
}
|
package/React/Base/RCTVersion.m
CHANGED
|
@@ -101,11 +101,7 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
|
|
101
101
|
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
|
|
102
102
|
[_backedTextInputView.defaultTextAttributes mutableCopy];
|
|
103
103
|
|
|
104
|
-
|
|
105
|
-
RCTWeakEventEmitterWrapper *eventEmitterWrapper = [RCTWeakEventEmitterWrapper new];
|
|
106
|
-
eventEmitterWrapper.eventEmitter = _eventEmitter;
|
|
107
|
-
defaultAttributes[RCTAttributedStringEventEmitterKey] = eventEmitterWrapper;
|
|
108
|
-
#endif
|
|
104
|
+
defaultAttributes[RCTAttributedStringEventEmitterKey] = RCTWrapEventEmitter(_eventEmitter);
|
|
109
105
|
|
|
110
106
|
_backedTextInputView.defaultTextAttributes = defaultAttributes;
|
|
111
107
|
}
|
|
@@ -266,10 +262,8 @@ static NSSet<NSNumber *> *returnKeyTypesSet;
|
|
|
266
262
|
if (newTextInputProps.textAttributes != oldTextInputProps.textAttributes) {
|
|
267
263
|
NSMutableDictionary<NSAttributedStringKey, id> *defaultAttributes =
|
|
268
264
|
RCTNSTextAttributesFromTextAttributes(newTextInputProps.getEffectiveTextAttributes(RCTFontSizeMultiplier()));
|
|
269
|
-
#if !TARGET_OS_MACCATALYST
|
|
270
265
|
defaultAttributes[RCTAttributedStringEventEmitterKey] =
|
|
271
266
|
_backedTextInputView.defaultTextAttributes[RCTAttributedStringEventEmitterKey];
|
|
272
|
-
#endif
|
|
273
267
|
_backedTextInputView.defaultTextAttributes = defaultAttributes;
|
|
274
268
|
}
|
|
275
269
|
|
|
@@ -7443,6 +7443,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
|
|
7443
7443
|
public static final field TA_KEY_LETTER_SPACING S
|
|
7444
7444
|
public static final field TA_KEY_LINE_BREAK_STRATEGY S
|
|
7445
7445
|
public static final field TA_KEY_LINE_HEIGHT S
|
|
7446
|
+
public static final field TA_KEY_MAX_FONT_SIZE_MULTIPLIER S
|
|
7446
7447
|
public static final field TA_KEY_OPACITY S
|
|
7447
7448
|
public static final field TA_KEY_ROLE S
|
|
7448
7449
|
public static final field TA_KEY_TEXT_DECORATION_COLOR S
|
|
@@ -7475,6 +7476,7 @@ public class com/facebook/react/views/text/TextAttributeProps {
|
|
|
7475
7476
|
protected field mLetterSpacingInput F
|
|
7476
7477
|
protected field mLineHeight F
|
|
7477
7478
|
protected field mLineHeightInput F
|
|
7479
|
+
protected field mMaxFontSizeMultiplier F
|
|
7478
7480
|
protected field mNumberOfLines I
|
|
7479
7481
|
protected field mOpacity F
|
|
7480
7482
|
protected field mRole Lcom/facebook/react/uimanager/ReactAccessibilityDelegate$Role;
|
|
@@ -445,12 +445,18 @@ public class FabricUIManager
|
|
|
445
445
|
|
|
446
446
|
@Override
|
|
447
447
|
public void markActiveTouchForTag(int surfaceId, int reactTag) {
|
|
448
|
-
mMountingManager.getSurfaceManager(surfaceId)
|
|
448
|
+
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
|
|
449
|
+
if (surfaceMountingManager != null) {
|
|
450
|
+
surfaceMountingManager.markActiveTouchForTag(reactTag);
|
|
451
|
+
}
|
|
449
452
|
}
|
|
450
453
|
|
|
451
454
|
@Override
|
|
452
455
|
public void sweepActiveTouchForTag(int surfaceId, int reactTag) {
|
|
453
|
-
mMountingManager.getSurfaceManager(surfaceId)
|
|
456
|
+
SurfaceMountingManager surfaceMountingManager = mMountingManager.getSurfaceManager(surfaceId);
|
|
457
|
+
if (surfaceMountingManager != null) {
|
|
458
|
+
surfaceMountingManager.sweepActiveTouchForTag(reactTag);
|
|
459
|
+
}
|
|
454
460
|
}
|
|
455
461
|
|
|
456
462
|
/**
|
|
@@ -330,14 +330,11 @@ public class MountingManager {
|
|
|
330
330
|
@AnyThread
|
|
331
331
|
@ThreadConfined(ANY)
|
|
332
332
|
public @Nullable EventEmitterWrapper getEventEmitter(int surfaceId, int reactTag) {
|
|
333
|
-
SurfaceMountingManager
|
|
334
|
-
|
|
335
|
-
? getSurfaceManagerForView(reactTag)
|
|
336
|
-
: getSurfaceManager(surfaceId));
|
|
337
|
-
if (surfaceMountingManager == null) {
|
|
333
|
+
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
|
334
|
+
if (smm == null) {
|
|
338
335
|
return null;
|
|
339
336
|
}
|
|
340
|
-
return
|
|
337
|
+
return smm.getEventEmitter(reactTag);
|
|
341
338
|
}
|
|
342
339
|
|
|
343
340
|
/**
|
|
@@ -434,11 +431,21 @@ public class MountingManager {
|
|
|
434
431
|
boolean canCoalesceEvent,
|
|
435
432
|
@Nullable WritableMap params,
|
|
436
433
|
@EventCategoryDef int eventCategory) {
|
|
437
|
-
|
|
434
|
+
SurfaceMountingManager smm = getSurfaceMountingManager(surfaceId, reactTag);
|
|
438
435
|
if (smm == null) {
|
|
439
|
-
|
|
436
|
+
FLog.d(
|
|
437
|
+
TAG,
|
|
438
|
+
"Cannot queue event without valid surface mounting manager for tag: %d, surfaceId: %d",
|
|
439
|
+
reactTag,
|
|
440
|
+
surfaceId);
|
|
440
441
|
return;
|
|
441
442
|
}
|
|
442
443
|
smm.enqueuePendingEvent(reactTag, eventName, canCoalesceEvent, params, eventCategory);
|
|
443
444
|
}
|
|
445
|
+
|
|
446
|
+
private @Nullable SurfaceMountingManager getSurfaceMountingManager(int surfaceId, int reactTag) {
|
|
447
|
+
return (surfaceId == ViewUtil.NO_SURFACE_ID
|
|
448
|
+
? getSurfaceManagerForView(reactTag)
|
|
449
|
+
: getSurfaceManager(surfaceId));
|
|
450
|
+
}
|
|
444
451
|
}
|
|
@@ -16,6 +16,7 @@ import android.graphics.drawable.LayerDrawable
|
|
|
16
16
|
import android.os.Build
|
|
17
17
|
import com.facebook.react.common.annotations.UnstableReactNativeAPI
|
|
18
18
|
import com.facebook.react.internal.featureflags.ReactNativeFeatureFlags
|
|
19
|
+
import com.facebook.react.uimanager.PixelUtil.dpToPx
|
|
19
20
|
import com.facebook.react.uimanager.style.BorderInsets
|
|
20
21
|
import com.facebook.react.uimanager.style.BorderRadiusStyle
|
|
21
22
|
|
|
@@ -200,14 +201,14 @@ internal class CompositeBackgroundDrawable(
|
|
|
200
201
|
pathForOutline.addRoundRect(
|
|
201
202
|
RectF(bounds),
|
|
202
203
|
floatArrayOf(
|
|
203
|
-
it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f),
|
|
204
|
-
it.topLeft.vertical + (computedBorderInsets?.top ?: 0f),
|
|
205
|
-
it.topRight.horizontal + (computedBorderInsets?.right ?: 0f),
|
|
206
|
-
it.topRight.vertical + (computedBorderInsets?.top ?: 0f),
|
|
207
|
-
it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f),
|
|
208
|
-
it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f),
|
|
209
|
-
it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f),
|
|
210
|
-
it.bottomLeft.vertical
|
|
204
|
+
(it.topLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(),
|
|
205
|
+
(it.topLeft.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(),
|
|
206
|
+
(it.topRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(),
|
|
207
|
+
(it.topRight.vertical + (computedBorderInsets?.top ?: 0f)).dpToPx(),
|
|
208
|
+
(it.bottomRight.horizontal + (computedBorderInsets?.right ?: 0f)).dpToPx(),
|
|
209
|
+
(it.bottomRight.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx(),
|
|
210
|
+
(it.bottomLeft.horizontal + (computedBorderInsets?.left ?: 0f)).dpToPx(),
|
|
211
|
+
(it.bottomLeft.vertical + (computedBorderInsets?.bottom ?: 0f)).dpToPx()),
|
|
211
212
|
Path.Direction.CW)
|
|
212
213
|
}
|
|
213
214
|
|
|
@@ -124,7 +124,7 @@ public constructor(
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
@ReactProp(name = "defaultSource"
|
|
127
|
+
@ReactProp(name = "defaultSource")
|
|
128
128
|
public fun setDefaultSource(view: ReactImageView, source: String?) {
|
|
129
129
|
view.setDefaultSource(source)
|
|
130
130
|
}
|
|
@@ -61,6 +61,7 @@ public class TextAttributeProps {
|
|
|
61
61
|
public static final short TA_KEY_LINE_BREAK_STRATEGY = 25;
|
|
62
62
|
public static final short TA_KEY_ROLE = 26;
|
|
63
63
|
public static final short TA_KEY_TEXT_TRANSFORM = 27;
|
|
64
|
+
public static final short TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
|
64
65
|
|
|
65
66
|
public static final int UNSET = -1;
|
|
66
67
|
|
|
@@ -81,6 +82,7 @@ public class TextAttributeProps {
|
|
|
81
82
|
protected float mLineHeight = Float.NaN;
|
|
82
83
|
protected boolean mIsColorSet = false;
|
|
83
84
|
protected boolean mAllowFontScaling = true;
|
|
85
|
+
protected float mMaxFontSizeMultiplier = Float.NaN;
|
|
84
86
|
protected int mColor;
|
|
85
87
|
protected boolean mIsBackgroundColorSet = false;
|
|
86
88
|
protected int mBackgroundColor;
|
|
@@ -227,6 +229,9 @@ public class TextAttributeProps {
|
|
|
227
229
|
case TA_KEY_TEXT_TRANSFORM:
|
|
228
230
|
result.setTextTransform(entry.getStringValue());
|
|
229
231
|
break;
|
|
232
|
+
case TA_KEY_MAX_FONT_SIZE_MULTIPLIER:
|
|
233
|
+
result.setMaxFontSizeMultiplier((float) entry.getDoubleValue());
|
|
234
|
+
break;
|
|
230
235
|
}
|
|
231
236
|
}
|
|
232
237
|
|
|
@@ -243,6 +248,8 @@ public class TextAttributeProps {
|
|
|
243
248
|
result.setLineHeight(getFloatProp(props, ViewProps.LINE_HEIGHT, ReactConstants.UNSET));
|
|
244
249
|
result.setLetterSpacing(getFloatProp(props, ViewProps.LETTER_SPACING, Float.NaN));
|
|
245
250
|
result.setAllowFontScaling(getBooleanProp(props, ViewProps.ALLOW_FONT_SCALING, true));
|
|
251
|
+
result.setMaxFontSizeMultiplier(
|
|
252
|
+
getFloatProp(props, ViewProps.MAX_FONT_SIZE_MULTIPLIER, Float.NaN));
|
|
246
253
|
result.setFontSize(getFloatProp(props, ViewProps.FONT_SIZE, ReactConstants.UNSET));
|
|
247
254
|
result.setColor(props.hasKey(ViewProps.COLOR) ? props.getInt(ViewProps.COLOR, 0) : null);
|
|
248
255
|
result.setColor(
|
|
@@ -411,7 +418,14 @@ public class TextAttributeProps {
|
|
|
411
418
|
mAllowFontScaling = allowFontScaling;
|
|
412
419
|
setFontSize(mFontSizeInput);
|
|
413
420
|
setLineHeight(mLineHeightInput);
|
|
414
|
-
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private void setMaxFontSizeMultiplier(float maxFontSizeMultiplier) {
|
|
425
|
+
if (maxFontSizeMultiplier != mMaxFontSizeMultiplier) {
|
|
426
|
+
mMaxFontSizeMultiplier = maxFontSizeMultiplier;
|
|
427
|
+
setFontSize(mFontSizeInput);
|
|
428
|
+
setLineHeight(mLineHeightInput);
|
|
415
429
|
}
|
|
416
430
|
}
|
|
417
431
|
|
|
@@ -420,7 +434,7 @@ public class TextAttributeProps {
|
|
|
420
434
|
if (fontSize != ReactConstants.UNSET) {
|
|
421
435
|
fontSize =
|
|
422
436
|
mAllowFontScaling
|
|
423
|
-
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize))
|
|
437
|
+
? (float) Math.ceil(PixelUtil.toPixelFromSP(fontSize, mMaxFontSizeMultiplier))
|
|
424
438
|
: (float) Math.ceil(PixelUtil.toPixelFromDIP(fontSize));
|
|
425
439
|
}
|
|
426
440
|
mFontSize = (int) fontSize;
|
package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm
CHANGED
|
@@ -123,6 +123,15 @@ std::vector<ExportedMethod> parseExportedMethods(std::string moduleName, Class m
|
|
|
123
123
|
NSArray<RCTMethodArgument *> *arguments;
|
|
124
124
|
SEL objCMethodSelector = NSSelectorFromString(RCTParseMethodSignature(methodInfo->objcName, &arguments));
|
|
125
125
|
NSMethodSignature *objCMethodSignature = [moduleClass instanceMethodSignatureForSelector:objCMethodSelector];
|
|
126
|
+
if (objCMethodSignature == nullptr) {
|
|
127
|
+
RCTLogWarn(
|
|
128
|
+
@"The objective-c `%s` method signature for the JS method `%@` can not be found in the ObjecitveC definition of the %s module.\nThe `%@` JS method will not be available.",
|
|
129
|
+
methodInfo->objcName,
|
|
130
|
+
jsMethodName,
|
|
131
|
+
moduleName.c_str(),
|
|
132
|
+
jsMethodName);
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
126
135
|
std::string objCMethodReturnType = [objCMethodSignature methodReturnType];
|
|
127
136
|
|
|
128
137
|
if (objCMethodSignature.numberOfArguments - 2 != [arguments count]) {
|
|
@@ -337,7 +346,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
337
346
|
SEL selector = selectorForType(argumentType);
|
|
338
347
|
|
|
339
348
|
if ([RCTConvert respondsToSelector:selector]) {
|
|
340
|
-
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
|
349
|
+
id objCArg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
|
341
350
|
|
|
342
351
|
if (objCArgType == @encode(char)) {
|
|
343
352
|
char arg = RCTConvertTo<char>(selector, objCArg);
|
|
@@ -437,6 +446,15 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
437
446
|
|
|
438
447
|
if (objCArgType == @encode(id)) {
|
|
439
448
|
id arg = RCTConvertTo<id>(selector, objCArg);
|
|
449
|
+
|
|
450
|
+
// Handle the special case where there is an argument and it must be nil
|
|
451
|
+
// Without this check, the JS side will receive an object.
|
|
452
|
+
// See: discussion at
|
|
453
|
+
// https://github.com/facebook/react-native/pull/49250#issuecomment-2668465893
|
|
454
|
+
if (arg == [NSNull null]) {
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
|
|
440
458
|
if (arg) {
|
|
441
459
|
[retainedObjectsForInvocation addObject:arg];
|
|
442
460
|
}
|
|
@@ -491,7 +509,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
491
509
|
}
|
|
492
510
|
|
|
493
511
|
RCTResponseSenderBlock arg =
|
|
494
|
-
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
|
512
|
+
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
|
495
513
|
if (arg) {
|
|
496
514
|
[retainedObjectsForInvocation addObject:arg];
|
|
497
515
|
}
|
|
@@ -506,7 +524,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
506
524
|
}
|
|
507
525
|
|
|
508
526
|
RCTResponseSenderBlock senderBlock =
|
|
509
|
-
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
|
527
|
+
(RCTResponseSenderBlock)TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
|
510
528
|
RCTResponseErrorBlock arg = ^(NSError *error) {
|
|
511
529
|
senderBlock(@[ RCTJSErrorFromNSError(error) ]);
|
|
512
530
|
};
|
|
@@ -536,7 +554,7 @@ void ObjCInteropTurboModule::setInvocationArg(
|
|
|
536
554
|
runtime, errorPrefix + "JavaScript argument must be a plain object. Got " + getType(runtime, jsiArg));
|
|
537
555
|
}
|
|
538
556
|
|
|
539
|
-
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_);
|
|
557
|
+
id arg = TurboModuleConvertUtils::convertJSIValueToObjCObject(runtime, jsiArg, jsInvoker_, YES);
|
|
540
558
|
|
|
541
559
|
RCTManagedPointer *(*convert)(id, SEL, id) = (__typeof__(convert))objc_msgSend;
|
|
542
560
|
RCTManagedPointer *box = convert([RCTCxxConvert class], selector, arg);
|
|
@@ -32,6 +32,11 @@ using EventEmitterCallback = std::function<void(const std::string &, id)>;
|
|
|
32
32
|
namespace TurboModuleConvertUtils {
|
|
33
33
|
jsi::Value convertObjCObjectToJSIValue(jsi::Runtime &runtime, id value);
|
|
34
34
|
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker);
|
|
35
|
+
id convertJSIValueToObjCObject(
|
|
36
|
+
jsi::Runtime &runtime,
|
|
37
|
+
const jsi::Value &value,
|
|
38
|
+
std::shared_ptr<CallInvoker> jsInvoker,
|
|
39
|
+
BOOL useNSNull);
|
|
35
40
|
} // namespace TurboModuleConvertUtils
|
|
36
41
|
|
|
37
42
|
template <>
|
|
@@ -57,7 +57,7 @@ static jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *va
|
|
|
57
57
|
|
|
58
58
|
static jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
|
|
59
59
|
{
|
|
60
|
-
return jsi::String::createFromUtf8(runtime, [value UTF8String]
|
|
60
|
+
return jsi::String::createFromUtf8(runtime, [value UTF8String] ? [value UTF8String] : "");
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
|
|
@@ -111,21 +111,27 @@ static NSString *convertJSIStringToNSString(jsi::Runtime &runtime, const jsi::St
|
|
|
111
111
|
return [NSString stringWithUTF8String:value.utf8(runtime).c_str()];
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
static NSArray *
|
|
115
|
-
|
|
114
|
+
static NSArray *convertJSIArrayToNSArray(
|
|
115
|
+
jsi::Runtime &runtime,
|
|
116
|
+
const jsi::Array &value,
|
|
117
|
+
std::shared_ptr<CallInvoker> jsInvoker,
|
|
118
|
+
BOOL useNSNull)
|
|
116
119
|
{
|
|
117
120
|
size_t size = value.size(runtime);
|
|
118
121
|
NSMutableArray *result = [NSMutableArray new];
|
|
119
122
|
for (size_t i = 0; i < size; i++) {
|
|
120
123
|
// Insert kCFNull when it's `undefined` value to preserve the indices.
|
|
121
|
-
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker);
|
|
124
|
+
id convertedObject = convertJSIValueToObjCObject(runtime, value.getValueAtIndex(runtime, i), jsInvoker, useNSNull);
|
|
122
125
|
[result addObject:convertedObject ? convertedObject : (id)kCFNull];
|
|
123
126
|
}
|
|
124
127
|
return [result copy];
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
static NSDictionary *
|
|
128
|
-
|
|
130
|
+
static NSDictionary *convertJSIObjectToNSDictionary(
|
|
131
|
+
jsi::Runtime &runtime,
|
|
132
|
+
const jsi::Object &value,
|
|
133
|
+
std::shared_ptr<CallInvoker> jsInvoker,
|
|
134
|
+
BOOL useNSNull)
|
|
129
135
|
{
|
|
130
136
|
jsi::Array propertyNames = value.getPropertyNames(runtime);
|
|
131
137
|
size_t size = propertyNames.size(runtime);
|
|
@@ -133,7 +139,7 @@ convertJSIObjectToNSDictionary(jsi::Runtime &runtime, const jsi::Object &value,
|
|
|
133
139
|
for (size_t i = 0; i < size; i++) {
|
|
134
140
|
jsi::String name = propertyNames.getValueAtIndex(runtime, i).getString(runtime);
|
|
135
141
|
NSString *k = convertJSIStringToNSString(runtime, name);
|
|
136
|
-
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker);
|
|
142
|
+
id v = convertJSIValueToObjCObject(runtime, value.getProperty(runtime, name), jsInvoker, useNSNull);
|
|
137
143
|
if (v) {
|
|
138
144
|
result[k] = v;
|
|
139
145
|
}
|
|
@@ -161,9 +167,21 @@ convertJSIFunctionToCallback(jsi::Runtime &rt, jsi::Function &&function, std::sh
|
|
|
161
167
|
|
|
162
168
|
id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, std::shared_ptr<CallInvoker> jsInvoker)
|
|
163
169
|
{
|
|
164
|
-
|
|
170
|
+
return convertJSIValueToObjCObject(runtime, value, jsInvoker, NO);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
id convertJSIValueToObjCObject(
|
|
174
|
+
jsi::Runtime &runtime,
|
|
175
|
+
const jsi::Value &value,
|
|
176
|
+
std::shared_ptr<CallInvoker> jsInvoker,
|
|
177
|
+
BOOL useNSNull)
|
|
178
|
+
{
|
|
179
|
+
if (value.isUndefined() || (value.isNull() && !useNSNull)) {
|
|
165
180
|
return nil;
|
|
166
181
|
}
|
|
182
|
+
if (value.isNull() && useNSNull) {
|
|
183
|
+
return [NSNull null];
|
|
184
|
+
}
|
|
167
185
|
if (value.isBool()) {
|
|
168
186
|
return @(value.getBool());
|
|
169
187
|
}
|
|
@@ -176,12 +194,12 @@ id convertJSIValueToObjCObject(jsi::Runtime &runtime, const jsi::Value &value, s
|
|
|
176
194
|
if (value.isObject()) {
|
|
177
195
|
jsi::Object o = value.getObject(runtime);
|
|
178
196
|
if (o.isArray(runtime)) {
|
|
179
|
-
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker);
|
|
197
|
+
return convertJSIArrayToNSArray(runtime, o.getArray(runtime), jsInvoker, useNSNull);
|
|
180
198
|
}
|
|
181
199
|
if (o.isFunction(runtime)) {
|
|
182
200
|
return convertJSIFunctionToCallback(runtime, o.getFunction(runtime), jsInvoker);
|
|
183
201
|
}
|
|
184
|
-
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker);
|
|
202
|
+
return convertJSIObjectToNSDictionary(runtime, o, jsInvoker, useNSNull);
|
|
185
203
|
}
|
|
186
204
|
|
|
187
205
|
throw std::runtime_error("Unsupported jsi::Value kind");
|
|
@@ -195,7 +213,11 @@ static jsi::Value createJSRuntimeError(jsi::Runtime &runtime, const std::string
|
|
|
195
213
|
/**
|
|
196
214
|
* Creates JSError with current JS runtime and NSException stack trace.
|
|
197
215
|
*/
|
|
198
|
-
static jsi::JSError convertNSExceptionToJSError(
|
|
216
|
+
static jsi::JSError convertNSExceptionToJSError(
|
|
217
|
+
jsi::Runtime &runtime,
|
|
218
|
+
NSException *exception,
|
|
219
|
+
const std::string &moduleName,
|
|
220
|
+
const std::string &methodName)
|
|
199
221
|
{
|
|
200
222
|
std::string reason = [exception.reason UTF8String];
|
|
201
223
|
|
|
@@ -206,7 +228,8 @@ static jsi::JSError convertNSExceptionToJSError(jsi::Runtime &runtime, NSExcepti
|
|
|
206
228
|
cause.setProperty(
|
|
207
229
|
runtime, "stackReturnAddresses", convertNSArrayToJSIArray(runtime, exception.callStackReturnAddresses));
|
|
208
230
|
|
|
209
|
-
|
|
231
|
+
std::string message = moduleName + "." + methodName + " raised an exception: " + reason;
|
|
232
|
+
jsi::Value error = createJSRuntimeError(runtime, message);
|
|
210
233
|
error.asObject(runtime).setProperty(runtime, "cause", std::move(cause));
|
|
211
234
|
return {runtime, std::move(error)};
|
|
212
235
|
}
|
|
@@ -338,28 +361,34 @@ id ObjCTurboModule::performMethodInvocation(
|
|
|
338
361
|
}
|
|
339
362
|
|
|
340
363
|
if (isSync) {
|
|
341
|
-
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName,
|
|
364
|
+
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName);
|
|
342
365
|
} else {
|
|
343
|
-
TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName,
|
|
366
|
+
TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter);
|
|
344
367
|
}
|
|
345
368
|
|
|
346
369
|
@try {
|
|
347
370
|
[inv invokeWithTarget:strongModule];
|
|
348
371
|
} @catch (NSException *exception) {
|
|
349
|
-
|
|
372
|
+
if (isSync) {
|
|
373
|
+
// We can only convert NSException to JSError in sync method calls.
|
|
374
|
+
// See https://github.com/reactwg/react-native-new-architecture/discussions/276#discussioncomment-12567155
|
|
375
|
+
throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr);
|
|
376
|
+
} else {
|
|
377
|
+
@throw exception;
|
|
378
|
+
}
|
|
350
379
|
} @finally {
|
|
351
380
|
[retainedObjectsForInvocation removeAllObjects];
|
|
352
381
|
}
|
|
353
382
|
|
|
354
383
|
if (!isSync) {
|
|
355
|
-
TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName,
|
|
384
|
+
TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter);
|
|
356
385
|
return;
|
|
357
386
|
}
|
|
358
387
|
|
|
359
388
|
void *rawResult;
|
|
360
389
|
[inv getReturnValue:&rawResult];
|
|
361
390
|
result = (__bridge id)rawResult;
|
|
362
|
-
TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName,
|
|
391
|
+
TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName);
|
|
363
392
|
};
|
|
364
393
|
|
|
365
394
|
if (isSync) {
|
|
@@ -401,23 +430,23 @@ void ObjCTurboModule::performVoidMethodInvocation(
|
|
|
401
430
|
}
|
|
402
431
|
|
|
403
432
|
if (shouldVoidMethodsExecuteSync_) {
|
|
404
|
-
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName,
|
|
433
|
+
TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName);
|
|
405
434
|
} else {
|
|
406
|
-
TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName,
|
|
435
|
+
TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter);
|
|
407
436
|
}
|
|
408
437
|
|
|
409
438
|
@try {
|
|
410
439
|
[inv invokeWithTarget:strongModule];
|
|
411
440
|
} @catch (NSException *exception) {
|
|
412
|
-
throw convertNSExceptionToJSError(runtime, exception);
|
|
441
|
+
throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr);
|
|
413
442
|
} @finally {
|
|
414
443
|
[retainedObjectsForInvocation removeAllObjects];
|
|
415
444
|
}
|
|
416
445
|
|
|
417
446
|
if (shouldVoidMethodsExecuteSync_) {
|
|
418
|
-
TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName,
|
|
447
|
+
TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName);
|
|
419
448
|
} else {
|
|
420
|
-
TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName,
|
|
449
|
+
TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter);
|
|
421
450
|
}
|
|
422
451
|
|
|
423
452
|
return;
|
|
@@ -46,6 +46,9 @@ void TextAttributes::apply(TextAttributes textAttributes) {
|
|
|
46
46
|
allowFontScaling = textAttributes.allowFontScaling.has_value()
|
|
47
47
|
? textAttributes.allowFontScaling
|
|
48
48
|
: allowFontScaling;
|
|
49
|
+
maxFontSizeMultiplier = !std::isnan(textAttributes.maxFontSizeMultiplier)
|
|
50
|
+
? textAttributes.maxFontSizeMultiplier
|
|
51
|
+
: maxFontSizeMultiplier;
|
|
49
52
|
dynamicTypeRamp = textAttributes.dynamicTypeRamp.has_value()
|
|
50
53
|
? textAttributes.dynamicTypeRamp
|
|
51
54
|
: dynamicTypeRamp;
|
|
@@ -168,6 +171,7 @@ bool TextAttributes::operator==(const TextAttributes& rhs) const {
|
|
|
168
171
|
rhs.accessibilityRole,
|
|
169
172
|
rhs.role,
|
|
170
173
|
rhs.textTransform) &&
|
|
174
|
+
floatEquality(maxFontSizeMultiplier, rhs.maxFontSizeMultiplier) &&
|
|
171
175
|
floatEquality(opacity, rhs.opacity) &&
|
|
172
176
|
floatEquality(fontSize, rhs.fontSize) &&
|
|
173
177
|
floatEquality(fontSizeMultiplier, rhs.fontSizeMultiplier) &&
|
|
@@ -211,6 +215,8 @@ SharedDebugStringConvertibleList TextAttributes::getDebugProps() const {
|
|
|
211
215
|
debugStringConvertibleItem("fontStyle", fontStyle),
|
|
212
216
|
debugStringConvertibleItem("fontVariant", fontVariant),
|
|
213
217
|
debugStringConvertibleItem("allowFontScaling", allowFontScaling),
|
|
218
|
+
debugStringConvertibleItem(
|
|
219
|
+
"maxFontSizeMultiplier", maxFontSizeMultiplier),
|
|
214
220
|
debugStringConvertibleItem("dynamicTypeRamp", dynamicTypeRamp),
|
|
215
221
|
debugStringConvertibleItem("letterSpacing", letterSpacing),
|
|
216
222
|
|
|
@@ -51,6 +51,7 @@ class TextAttributes : public DebugStringConvertible {
|
|
|
51
51
|
std::optional<FontStyle> fontStyle{};
|
|
52
52
|
std::optional<FontVariant> fontVariant{};
|
|
53
53
|
std::optional<bool> allowFontScaling{};
|
|
54
|
+
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
|
|
54
55
|
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
|
|
55
56
|
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
|
|
56
57
|
std::optional<TextTransform> textTransform{};
|
|
@@ -117,6 +118,7 @@ struct hash<facebook::react::TextAttributes> {
|
|
|
117
118
|
textAttributes.opacity,
|
|
118
119
|
textAttributes.fontFamily,
|
|
119
120
|
textAttributes.fontSize,
|
|
121
|
+
textAttributes.maxFontSizeMultiplier,
|
|
120
122
|
textAttributes.fontSizeMultiplier,
|
|
121
123
|
textAttributes.fontWeight,
|
|
122
124
|
textAttributes.fontStyle,
|
|
@@ -910,6 +910,7 @@ constexpr static MapBuffer::Key TA_KEY_LINE_BREAK_STRATEGY = 25;
|
|
|
910
910
|
constexpr static MapBuffer::Key TA_KEY_ROLE = 26;
|
|
911
911
|
constexpr static MapBuffer::Key TA_KEY_TEXT_TRANSFORM = 27;
|
|
912
912
|
constexpr static MapBuffer::Key TA_KEY_ALIGNMENT_VERTICAL = 28;
|
|
913
|
+
constexpr static MapBuffer::Key TA_KEY_MAX_FONT_SIZE_MULTIPLIER = 29;
|
|
913
914
|
|
|
914
915
|
// constants for ParagraphAttributes serialization
|
|
915
916
|
constexpr static MapBuffer::Key PA_KEY_MAX_NUMBER_OF_LINES = 0;
|
|
@@ -1004,6 +1005,10 @@ inline MapBuffer toMapBuffer(const TextAttributes& textAttributes) {
|
|
|
1004
1005
|
builder.putBool(
|
|
1005
1006
|
TA_KEY_ALLOW_FONT_SCALING, *textAttributes.allowFontScaling);
|
|
1006
1007
|
}
|
|
1008
|
+
if (!std::isnan(textAttributes.maxFontSizeMultiplier)) {
|
|
1009
|
+
builder.putDouble(
|
|
1010
|
+
TA_KEY_MAX_FONT_SIZE_MULTIPLIER, textAttributes.maxFontSizeMultiplier);
|
|
1011
|
+
}
|
|
1007
1012
|
if (!std::isnan(textAttributes.letterSpacing)) {
|
|
1008
1013
|
builder.putDouble(TA_KEY_LETTER_SPACING, textAttributes.letterSpacing);
|
|
1009
1014
|
}
|
|
@@ -73,6 +73,12 @@ static TextAttributes convertRawProp(
|
|
|
73
73
|
"allowFontScaling",
|
|
74
74
|
sourceTextAttributes.allowFontScaling,
|
|
75
75
|
defaultTextAttributes.allowFontScaling);
|
|
76
|
+
textAttributes.maxFontSizeMultiplier = convertRawProp(
|
|
77
|
+
context,
|
|
78
|
+
rawProps,
|
|
79
|
+
"maxFontSizeMultiplier",
|
|
80
|
+
sourceTextAttributes.maxFontSizeMultiplier,
|
|
81
|
+
defaultTextAttributes.maxFontSizeMultiplier);
|
|
76
82
|
textAttributes.dynamicTypeRamp = convertRawProp(
|
|
77
83
|
context,
|
|
78
84
|
rawProps,
|
|
@@ -266,6 +272,12 @@ void BaseTextProps::setProp(
|
|
|
266
272
|
defaults, value, textAttributes, fontVariant, "fontVariant");
|
|
267
273
|
REBUILD_FIELD_SWITCH_CASE(
|
|
268
274
|
defaults, value, textAttributes, allowFontScaling, "allowFontScaling");
|
|
275
|
+
REBUILD_FIELD_SWITCH_CASE(
|
|
276
|
+
defaults,
|
|
277
|
+
value,
|
|
278
|
+
textAttributes,
|
|
279
|
+
maxFontSizeMultiplier,
|
|
280
|
+
"maxFontSizeMultiplier");
|
|
269
281
|
REBUILD_FIELD_SWITCH_CASE(
|
|
270
282
|
defaults, value, textAttributes, letterSpacing, "letterSpacing");
|
|
271
283
|
REBUILD_FIELD_SWITCH_CASE(
|
|
@@ -52,8 +52,29 @@ BOOL RCTIsAttributedStringEffectivelySame(
|
|
|
52
52
|
NSDictionary<NSAttributedStringKey, id> *insensitiveAttributes,
|
|
53
53
|
const facebook::react::TextAttributes &baseTextAttributes);
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
static inline NSData *RCTWrapEventEmitter(const facebook::react::SharedEventEmitter &eventEmitter)
|
|
56
|
+
{
|
|
57
|
+
auto eventEmitterPtr = new std::weak_ptr<const facebook::react::EventEmitter>(eventEmitter);
|
|
58
|
+
return [[NSData alloc] initWithBytesNoCopy:eventEmitterPtr
|
|
59
|
+
length:sizeof(eventEmitterPtr)
|
|
60
|
+
deallocator:^(void *ptrToDelete, NSUInteger) {
|
|
61
|
+
delete (std::weak_ptr<facebook::react::EventEmitter> *)ptrToDelete;
|
|
62
|
+
}];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
static inline facebook::react::SharedEventEmitter RCTUnwrapEventEmitter(NSData *data)
|
|
66
|
+
{
|
|
67
|
+
if (data.length == 0) {
|
|
68
|
+
return nullptr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
auto weakPtr = dynamic_cast<std::weak_ptr<const facebook::react::EventEmitter> *>(
|
|
72
|
+
(std::weak_ptr<const facebook::react::EventEmitter> *)data.bytes);
|
|
73
|
+
if (weakPtr) {
|
|
74
|
+
return weakPtr->lock();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return nullptr;
|
|
78
|
+
}
|
|
58
79
|
|
|
59
80
|
NS_ASSUME_NONNULL_END
|
|
@@ -16,45 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
using namespace facebook::react;
|
|
18
18
|
|
|
19
|
-
@implementation RCTWeakEventEmitterWrapper {
|
|
20
|
-
std::weak_ptr<const EventEmitter> _weakEventEmitter;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
- (void)setEventEmitter:(SharedEventEmitter)eventEmitter
|
|
24
|
-
{
|
|
25
|
-
_weakEventEmitter = eventEmitter;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
- (SharedEventEmitter)eventEmitter
|
|
29
|
-
{
|
|
30
|
-
return _weakEventEmitter.lock();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
- (void)dealloc
|
|
34
|
-
{
|
|
35
|
-
_weakEventEmitter.reset();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
- (BOOL)isEqual:(id)object
|
|
39
|
-
{
|
|
40
|
-
// We consider the underlying EventEmitter as the identity
|
|
41
|
-
if (![object isKindOfClass:[self class]]) {
|
|
42
|
-
return NO;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
auto thisEventEmitter = [self eventEmitter];
|
|
46
|
-
auto otherEventEmitter = [((RCTWeakEventEmitterWrapper *)object) eventEmitter];
|
|
47
|
-
return thisEventEmitter == otherEventEmitter;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
- (NSUInteger)hash
|
|
51
|
-
{
|
|
52
|
-
// We consider the underlying EventEmitter as the identity
|
|
53
|
-
return (NSUInteger)_weakEventEmitter.lock().get();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
@end
|
|
57
|
-
|
|
58
19
|
inline static UIFontWeight RCTUIFontWeightFromInteger(NSInteger fontWeight)
|
|
59
20
|
{
|
|
60
21
|
assert(fontWeight > 50);
|
|
@@ -135,6 +96,7 @@ inline static CGFloat RCTBaseSizeForDynamicTypeRamp(const DynamicTypeRamp &dynam
|
|
|
135
96
|
inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const TextAttributes &textAttributes)
|
|
136
97
|
{
|
|
137
98
|
if (textAttributes.allowFontScaling.value_or(true)) {
|
|
99
|
+
CGFloat fontSizeMultiplier = !isnan(textAttributes.fontSizeMultiplier) ? textAttributes.fontSizeMultiplier : 1.0;
|
|
138
100
|
if (textAttributes.dynamicTypeRamp.has_value()) {
|
|
139
101
|
DynamicTypeRamp dynamicTypeRamp = textAttributes.dynamicTypeRamp.value();
|
|
140
102
|
UIFontMetrics *fontMetrics =
|
|
@@ -142,10 +104,11 @@ inline static CGFloat RCTEffectiveFontSizeMultiplierFromTextAttributes(const Tex
|
|
|
142
104
|
// Using a specific font size reduces rounding errors from -scaledValueForValue:
|
|
143
105
|
CGFloat requestedSize =
|
|
144
106
|
isnan(textAttributes.fontSize) ? RCTBaseSizeForDynamicTypeRamp(dynamicTypeRamp) : textAttributes.fontSize;
|
|
145
|
-
|
|
146
|
-
} else {
|
|
147
|
-
return textAttributes.fontSizeMultiplier;
|
|
107
|
+
fontSizeMultiplier = [fontMetrics scaledValueForValue:requestedSize] / requestedSize;
|
|
148
108
|
}
|
|
109
|
+
CGFloat maxFontSizeMultiplier =
|
|
110
|
+
!isnan(textAttributes.maxFontSizeMultiplier) ? textAttributes.maxFontSizeMultiplier : 0.0;
|
|
111
|
+
return maxFontSizeMultiplier >= 1.0 ? fminf(maxFontSizeMultiplier, fontSizeMultiplier) : fontSizeMultiplier;
|
|
149
112
|
} else {
|
|
150
113
|
return 1.0;
|
|
151
114
|
}
|
|
@@ -403,10 +366,8 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
|
|
403
366
|
{
|
|
404
367
|
auto nsAttributedStringFragment = RCTNSAttributedStringFragmentFromFragment(fragment, placeholderImage);
|
|
405
368
|
|
|
406
|
-
#if !TARGET_OS_MACCATALYST
|
|
407
369
|
if (fragment.parentShadowView.componentHandle) {
|
|
408
|
-
|
|
409
|
-
eventEmitterWrapper.eventEmitter = fragment.parentShadowView.eventEmitter;
|
|
370
|
+
auto eventEmitterWrapper = RCTWrapEventEmitter(fragment.parentShadowView.eventEmitter);
|
|
410
371
|
|
|
411
372
|
NSDictionary<NSAttributedStringKey, id> *additionalTextAttributes =
|
|
412
373
|
@{RCTAttributedStringEventEmitterKey : eventEmitterWrapper};
|
|
@@ -414,7 +375,6 @@ static NSMutableAttributedString *RCTNSAttributedStringFragmentWithAttributesFro
|
|
|
414
375
|
[nsAttributedStringFragment addAttributes:additionalTextAttributes
|
|
415
376
|
range:NSMakeRange(0, nsAttributedStringFragment.length)];
|
|
416
377
|
}
|
|
417
|
-
#endif
|
|
418
378
|
|
|
419
379
|
return nsAttributedStringFragment;
|
|
420
380
|
}
|
|
@@ -280,11 +280,10 @@ static NSLineBreakMode RCTNSLineBreakModeFromEllipsizeMode(EllipsizeMode ellipsi
|
|
|
280
280
|
// after (fraction == 1.0) the last character, then the attribute is valid.
|
|
281
281
|
if (textStorage.length > 0 && (fraction > 0 || characterIndex > 0) &&
|
|
282
282
|
(fraction < 1 || characterIndex < textStorage.length - 1)) {
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return eventEmitterWrapper.eventEmitter;
|
|
283
|
+
NSData *eventEmitterWrapper = (NSData *)[textStorage attribute:RCTAttributedStringEventEmitterKey
|
|
284
|
+
atIndex:characterIndex
|
|
285
|
+
effectiveRange:NULL];
|
|
286
|
+
return RCTUnwrapEventEmitter(eventEmitterWrapper);
|
|
288
287
|
}
|
|
289
288
|
|
|
290
289
|
return nil;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.77.
|
|
3
|
+
"version": "0.77.2",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -108,13 +108,13 @@
|
|
|
108
108
|
},
|
|
109
109
|
"dependencies": {
|
|
110
110
|
"@jest/create-cache-key-function": "^29.6.3",
|
|
111
|
-
"@react-native/assets-registry": "0.77.
|
|
112
|
-
"@react-native/codegen": "0.77.
|
|
113
|
-
"@react-native/community-cli-plugin": "0.77.
|
|
114
|
-
"@react-native/gradle-plugin": "0.77.
|
|
115
|
-
"@react-native/js-polyfills": "0.77.
|
|
116
|
-
"@react-native/normalize-colors": "0.77.
|
|
117
|
-
"@react-native/virtualized-lists": "0.77.
|
|
111
|
+
"@react-native/assets-registry": "0.77.2",
|
|
112
|
+
"@react-native/codegen": "0.77.2",
|
|
113
|
+
"@react-native/community-cli-plugin": "0.77.2",
|
|
114
|
+
"@react-native/gradle-plugin": "0.77.2",
|
|
115
|
+
"@react-native/js-polyfills": "0.77.2",
|
|
116
|
+
"@react-native/normalize-colors": "0.77.2",
|
|
117
|
+
"@react-native/virtualized-lists": "0.77.2",
|
|
118
118
|
"abort-controller": "^3.0.0",
|
|
119
119
|
"anser": "^1.4.9",
|
|
120
120
|
"ansi-regex": "^5.0.0",
|
|
@@ -130,8 +130,8 @@
|
|
|
130
130
|
"jest-environment-node": "^29.6.3",
|
|
131
131
|
"jsc-android": "^250231.0.0",
|
|
132
132
|
"memoize-one": "^5.0.0",
|
|
133
|
-
"metro-runtime": "^0.81.
|
|
134
|
-
"metro-source-map": "^0.81.
|
|
133
|
+
"metro-runtime": "^0.81.3",
|
|
134
|
+
"metro-source-map": "^0.81.3",
|
|
135
135
|
"nullthrows": "^1.1.1",
|
|
136
136
|
"pretty-format": "^29.7.0",
|
|
137
137
|
"promise": "^8.3.0",
|
package/react-native.config.js
CHANGED
|
@@ -44,27 +44,11 @@ try {
|
|
|
44
44
|
|
|
45
45
|
const commands = [];
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
commands.push(bundleCommand, startCommand);
|
|
53
|
-
} catch (e) {
|
|
54
|
-
const known =
|
|
55
|
-
e.code === 'MODULE_NOT_FOUND' &&
|
|
56
|
-
e.message.includes('@react-native-community/cli-server-api');
|
|
57
|
-
|
|
58
|
-
if (!known) {
|
|
59
|
-
throw e;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (verbose) {
|
|
63
|
-
console.warn(
|
|
64
|
-
'@react-native-community/cli-server-api not found, the react-native.config.js may be unusable.',
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
47
|
+
const {
|
|
48
|
+
bundleCommand,
|
|
49
|
+
startCommand,
|
|
50
|
+
} = require('@react-native/community-cli-plugin');
|
|
51
|
+
commands.push(bundleCommand, startCommand);
|
|
68
52
|
|
|
69
53
|
const codegenCommand = {
|
|
70
54
|
name: 'codegen',
|
|
@@ -84,12 +68,18 @@ const codegenCommand = {
|
|
|
84
68
|
name: '--outputPath <path>',
|
|
85
69
|
description: 'Path where generated artifacts will be output to.',
|
|
86
70
|
},
|
|
71
|
+
{
|
|
72
|
+
name: '--source <string>',
|
|
73
|
+
description: 'Whether the script is invoked from an `app` or a `library`',
|
|
74
|
+
default: 'app',
|
|
75
|
+
},
|
|
87
76
|
],
|
|
88
77
|
func: (argv, config, args) =>
|
|
89
78
|
require('./scripts/codegen/generate-artifacts-executor').execute(
|
|
90
79
|
args.path,
|
|
91
80
|
args.platform,
|
|
92
81
|
args.outputPath,
|
|
82
|
+
args.source,
|
|
93
83
|
),
|
|
94
84
|
};
|
|
95
85
|
|
|
@@ -899,11 +899,12 @@ function generateFBReactNativeSpecIOS(projectRoot /*: string */) /*: void*/ {
|
|
|
899
899
|
* @parameter projectRoot: the directory with the app source code, where the package.json lives.
|
|
900
900
|
* @parameter baseOutputPath: the base output path for the CodeGen.
|
|
901
901
|
* @parameter targetPlatform: the target platform. Supported values: 'android', 'ios', 'all'.
|
|
902
|
+
* @parameter source: the source that is invoking codegen. Supported values: 'app', 'library'.
|
|
902
903
|
* @throws If it can't find a config file for react-native.
|
|
903
904
|
* @throws If it can't find a CodeGen configuration in the file.
|
|
904
905
|
* @throws If it can't find a cli for the CodeGen.
|
|
905
906
|
*/
|
|
906
|
-
function execute(projectRoot, targetPlatform, baseOutputPath) {
|
|
907
|
+
function execute(projectRoot, targetPlatform, baseOutputPath, source) {
|
|
907
908
|
try {
|
|
908
909
|
codegenLog(`Analyzing ${path.join(projectRoot, 'package.json')}`);
|
|
909
910
|
|
|
@@ -951,9 +952,12 @@ function execute(projectRoot, targetPlatform, baseOutputPath) {
|
|
|
951
952
|
platform,
|
|
952
953
|
);
|
|
953
954
|
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
955
|
+
if (source === 'app') {
|
|
956
|
+
// These components are only required by apps, not by libraries
|
|
957
|
+
generateRCTThirdPartyComponents(libraries, outputPath);
|
|
958
|
+
generateCustomURLHandlers(libraries, outputPath);
|
|
959
|
+
generateAppDependencyProvider(outputPath);
|
|
960
|
+
}
|
|
957
961
|
|
|
958
962
|
cleanupEmptyFilesAndFolders(outputPath);
|
|
959
963
|
}
|
|
@@ -25,7 +25,12 @@ const argv = yargs
|
|
|
25
25
|
alias: 'outputPath',
|
|
26
26
|
description: 'Path where generated artifacts will be output to.',
|
|
27
27
|
})
|
|
28
|
+
.option('s', {
|
|
29
|
+
alias: 'source',
|
|
30
|
+
description: 'Whether the script is invoked from an `app` or a `library`',
|
|
31
|
+
default: 'app',
|
|
32
|
+
})
|
|
28
33
|
.usage('Usage: $0 -p [path to app] -t [target platform] -o [output path]')
|
|
29
34
|
.demandOption(['p', 't']).argv;
|
|
30
35
|
|
|
31
|
-
executor.execute(argv.path, argv.targetPlatform, argv.outputPath);
|
|
36
|
+
executor.execute(argv.path, argv.targetPlatform, argv.outputPath, argv.source);
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|