plotline-engage 5.6.2 → 5.6.4

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.
@@ -40,6 +40,6 @@ repositories {
40
40
 
41
41
  dependencies {
42
42
  implementation 'com.facebook.react:react-native:+'
43
- implementation 'com.gitlab.plotline:plotline-android-sdk:5.2.0'
43
+ implementation 'com.gitlab.plotline:plotline-android-sdk:5.2.1'
44
44
  }
45
45
 
package/ios/RNPlotline.m CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  #import "RNPlotline.h"
3
2
  #import <Plotline/Plotline-Swift.h>
4
3
  #import <React/RCTEventEmitter.h>
@@ -9,15 +8,37 @@
9
8
  return @[@"PlotlineEvents",@"PlotlineRedirect"];
10
9
  }
11
10
 
11
+ // Central handler for any NSException caught at the RN bridge boundary.
12
+ // Any uncaught NSException from a void RCT_EXPORT_METHOD is converted to a JS error by
13
+ // React Native ON the TurboModule background queue (convertNSExceptionToJSError), which
14
+ // touches the single-threaded Hermes runtime off the JS thread and corrupts its heap
15
+ // (PLO-4202). We catch here to stop that cascade.
16
+ // NOTE: NSLog-only for now (device-visible, not production telemetry). Routing caught
17
+ // bridge exceptions to production telemetry is a tracked follow-up on PLO-4202.
18
+ + (void)logAndReportException:(NSException *)exception forMethod:(NSString *)method
19
+ {
20
+ // Self-guarded: this runs inside @catch blocks, so it must never throw - an exception
21
+ // escaping here would re-enter RN's off-thread error conversion, the exact bug we fixed.
22
+ @try {
23
+ NSString *reason = exception.reason ?: @"unknown";
24
+ NSString *message = [NSString stringWithFormat:@"[Plotline] %@ failed: %@ (%@)", method, reason, exception.name];
25
+ NSLog(@"%@", message);
26
+ } @catch (NSException *ignored) {}
27
+ }
28
+
12
29
  RCT_EXPORT_METHOD(init:(NSString *)apiKey userId:(NSString *)userId endpoint:(NSString *)endpoint)
13
30
  {
14
- [Plotline setPlotlineFrameworkWithFramework:@"REACT_NATIVE"];
15
- if (endpoint != nil) {
16
- [Plotline initializeWithApiKey:apiKey userId:userId endpoint:endpoint];
17
- } else {
18
- [Plotline initializeWithApiKey:apiKey userId:userId];
31
+ @try {
32
+ [Plotline setPlotlineFrameworkWithFramework:@"REACT_NATIVE"];
33
+ if (endpoint != nil) {
34
+ [Plotline initializeWithApiKey:apiKey userId:userId endpoint:endpoint];
35
+ } else {
36
+ [Plotline initializeWithApiKey:apiKey userId:userId];
37
+ }
38
+ [self registerPlotlineListeners];
39
+ } @catch (NSException *exception) {
40
+ [RNPlotline logAndReportException:exception forMethod:@"init"];
19
41
  }
20
- [self registerPlotlineListeners];
21
42
  }
22
43
 
23
44
  - (void)registerPlotlineListeners
@@ -36,87 +57,151 @@ RCT_EXPORT_METHOD(init:(NSString *)apiKey userId:(NSString *)userId endpoint:(NS
36
57
 
37
58
  RCT_EXPORT_METHOD(initAnonymousUser:(NSString *)apiKey deviceId:(NSString *)deviceId)
38
59
  {
39
- [Plotline setPlotlineFrameworkWithFramework:@"REACT_NATIVE"];
40
- [Plotline initializeAnonymousUserWithApiKey:apiKey deviceId:deviceId ?: @""];
41
- [self registerPlotlineListeners];
60
+ @try {
61
+ [Plotline setPlotlineFrameworkWithFramework:@"REACT_NATIVE"];
62
+ [Plotline initializeAnonymousUserWithApiKey:apiKey deviceId:deviceId ?: @""];
63
+ [self registerPlotlineListeners];
64
+ } @catch (NSException *exception) {
65
+ [RNPlotline logAndReportException:exception forMethod:@"initAnonymousUser"];
66
+ }
42
67
  }
43
68
 
44
69
  RCT_EXPORT_METHOD(track:(NSString *)eventName properties: (NSDictionary *) properties)
45
70
  {
46
- if(properties != nil) {
47
- [Plotline trackWithEventName:eventName properties:properties];
48
- } else {
49
- [Plotline trackWithEventName:eventName];
71
+ @try {
72
+ if(properties != nil) {
73
+ [Plotline trackWithEventName:eventName properties:properties];
74
+ } else {
75
+ [Plotline trackWithEventName:eventName];
76
+ }
77
+ } @catch (NSException *exception) {
78
+ [RNPlotline logAndReportException:exception forMethod:@"track"];
50
79
  }
51
80
  }
52
81
 
53
82
  RCT_EXPORT_METHOD(showStory:(NSString *)storyId slideId: (NSString *)slideId)
54
83
  {
55
- [Plotline showStoryWithStoryId:storyId slideId:slideId];
84
+ @try {
85
+ [Plotline showStoryWithStoryId:storyId slideId:slideId];
86
+ } @catch (NSException *exception) {
87
+ [RNPlotline logAndReportException:exception forMethod:@"showStory"];
88
+ }
56
89
  }
57
90
 
58
91
  RCT_EXPORT_METHOD(setLocale:(NSString *)locale)
59
92
  {
60
- [Plotline setLocaleWithLocale:locale];
93
+ @try {
94
+ [Plotline setLocaleWithLocale:locale];
95
+ } @catch (NSException *exception) {
96
+ [RNPlotline logAndReportException:exception forMethod:@"setLocale"];
97
+ }
61
98
  }
62
99
 
63
100
  RCT_EXPORT_METHOD(identify:(NSDictionary *)attribute)
64
101
  {
65
- [Plotline identifyWithAttributes:attribute];
102
+ @try {
103
+ [Plotline identifyWithAttributes:attribute];
104
+ } @catch (NSException *exception) {
105
+ [RNPlotline logAndReportException:exception forMethod:@"identify"];
106
+ }
66
107
  }
67
108
 
68
109
  RCT_EXPORT_METHOD(showMockStudy)
69
110
  {
70
- [Plotline showMockStudy];
111
+ @try {
112
+ [Plotline showMockStudy];
113
+ } @catch (NSException *exception) {
114
+ [RNPlotline logAndReportException:exception forMethod:@"showMockStudy"];
115
+ }
71
116
  }
72
117
 
73
118
  RCT_EXPORT_METHOD(setColor:(NSDictionary *)colors)
74
119
  {
75
- [Plotline setColorWithColors:colors];
120
+ @try {
121
+ [Plotline setColorWithColors:colors];
122
+ } @catch (NSException *exception) {
123
+ [RNPlotline logAndReportException:exception forMethod:@"setColor"];
124
+ }
76
125
  }
77
126
 
78
127
  RCT_EXPORT_METHOD(setShouldDisablePlotline:(nonnull NSNumber *)shouldDisablePlotline)
79
128
  {
129
+ @try {
80
130
  BOOL boolValue = [shouldDisablePlotline boolValue];
81
131
  [Plotline setShouldDisablePlotlineWithShouldDisablePlotline:boolValue];
132
+ } @catch (NSException *exception) {
133
+ [RNPlotline logAndReportException:exception forMethod:@"setShouldDisablePlotline"];
134
+ }
82
135
  }
83
136
 
84
137
  RCT_EXPORT_METHOD(setShouldEnableScrollDelegates:(nonnull NSNumber *)shouldEnableScrollDelegates)
85
138
  {
139
+ @try {
86
140
  BOOL boolValue = [shouldEnableScrollDelegates boolValue];
87
141
  [Plotline setShouldEnableScrollDelegatesWithShouldEnableScrollDelegates:boolValue];
142
+ } @catch (NSException *exception) {
143
+ [RNPlotline logAndReportException:exception forMethod:@"setShouldEnableScrollDelegates"];
144
+ }
88
145
  }
89
146
 
90
147
  RCT_EXPORT_METHOD(debug)
91
148
  {
92
- [Plotline debugWithShouldDebug:true];
149
+ @try {
150
+ [Plotline debugWithShouldDebug:true];
151
+ } @catch (NSException *exception) {
152
+ [RNPlotline logAndReportException:exception forMethod:@"debug"];
153
+ }
93
154
  }
94
155
 
95
156
  RCT_EXPORT_METHOD(notifyScroll)
96
157
  {
97
- [Plotline notifyScroll];
158
+ @try {
159
+ [Plotline notifyScroll];
160
+ } @catch (NSException *exception) {
161
+ [RNPlotline logAndReportException:exception forMethod:@"notifyScroll"];
162
+ }
98
163
  }
99
164
 
100
165
  RCT_EXPORT_METHOD(trackPage:(NSString *)pageName)
101
166
  {
102
- [Plotline trackPageWithPageName:pageName];
167
+ @try {
168
+ [Plotline trackPageWithPageName:pageName];
169
+ } @catch (NSException *exception) {
170
+ [RNPlotline logAndReportException:exception forMethod:@"trackPage"];
171
+ }
103
172
  }
104
173
 
105
174
  RCT_EXPORT_METHOD(logout)
106
175
  {
107
- [Plotline logout];
176
+ @try {
177
+ [Plotline logout];
178
+ } @catch (NSException *exception) {
179
+ [RNPlotline logAndReportException:exception forMethod:@"logout"];
180
+ }
108
181
  }
109
182
 
110
183
  RCT_EXPORT_METHOD(setToken:(NSString *)token)
111
184
  {
112
- NSMutableData *deviceTokenData = [NSMutableData data];
113
- for (int i = 0; i < token.length; i += 2) {
114
- NSString *hexByte = [token substringWithRange:NSMakeRange(i, 2)];
115
- unsigned int byte;
116
- [[NSScanner scannerWithString:hexByte] scanHexInt:&byte];
117
- [deviceTokenData appendBytes:&byte length:1];
185
+ @try {
186
+ // APNs device tokens are an even-length hex string; anything else (e.g. an FCM
187
+ // token passed on iOS) previously crashed the hex-decode below (PLO-4202) - skip it.
188
+ NSCharacterSet *nonHex = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdefABCDEF"] invertedSet];
189
+ if (token.length == 0 || token.length % 2 != 0 ||
190
+ [token rangeOfCharacterFromSet:nonHex].location != NSNotFound) {
191
+ NSLog(@"[Plotline] setToken: not an APNs hex token (length=%lu); skipping", (unsigned long)token.length);
192
+ return;
193
+ }
194
+ NSMutableData *deviceTokenData = [NSMutableData data];
195
+ for (NSUInteger i = 0; i + 2 <= token.length; i += 2) {
196
+ unsigned int byte = 0;
197
+ [[NSScanner scannerWithString:[token substringWithRange:NSMakeRange(i, 2)]] scanHexInt:&byte];
198
+ unsigned char byteValue = (unsigned char)byte;
199
+ [deviceTokenData appendBytes:&byteValue length:1];
200
+ }
201
+ [PlotlinePush setPushTokenWithDeviceToken:deviceTokenData];
202
+ } @catch (NSException *exception) {
203
+ [RNPlotline logAndReportException:exception forMethod:@"setToken"];
118
204
  }
119
- [PlotlinePush setPushTokenWithDeviceToken:deviceTokenData];
120
205
  }
121
206
 
122
207
 
@@ -126,11 +211,21 @@ RCT_EXPORT_METHOD(isFeatureEnabled:(NSString *)key
126
211
  rejecter:(RCTPromiseRejectBlock)reject)
127
212
  {
128
213
  @try {
214
+ // NOTE: the @try below guards ONLY the registration of the listener. The listener block
215
+ // itself runs asynchronously (when feature flags load), on the SDK's callback thread, so
216
+ // any exception thrown by isFeatureEnabledWithKey: inside it is NOT covered by this outer
217
+ // @try - it would escape as an uncaught NSException (PLO-4202). Guard the block body too.
129
218
  [Plotline setOnFeatureFlagsLoadedListenerWithFeatureFlagsLoadedListener:^{
130
- BOOL result = [Plotline isFeatureEnabledWithKey:key];
131
- resolve(@(result));
219
+ @try {
220
+ BOOL result = [Plotline isFeatureEnabledWithKey:key];
221
+ resolve(@(result));
222
+ } @catch (NSException *exception) {
223
+ [RNPlotline logAndReportException:exception forMethod:@"isFeatureEnabled"];
224
+ reject(@"error", exception.reason, nil);
225
+ }
132
226
  }];
133
227
  } @catch (NSException *exception) {
228
+ [RNPlotline logAndReportException:exception forMethod:@"isFeatureEnabled"];
134
229
  reject(@"error", exception.reason, nil); // Handle errors
135
230
  }
136
231
  }
@@ -142,10 +237,16 @@ RCT_EXPORT_METHOD(getFeatureFlag:(NSString *)key
142
237
  {
143
238
  @try {
144
239
  [Plotline setOnFeatureFlagsLoadedListenerWithFeatureFlagsLoadedListener:^{
145
- NSString *result = [Plotline getFeatureFlagWithKey:key];
146
- resolve(result);
240
+ @try {
241
+ NSString *result = [Plotline getFeatureFlagWithKey:key];
242
+ resolve(result);
243
+ } @catch (NSException *exception) {
244
+ [RNPlotline logAndReportException:exception forMethod:@"getFeatureFlag"];
245
+ reject(@"error", exception.reason, nil);
246
+ }
147
247
  }];
148
248
  } @catch (NSException *exception) {
249
+ [RNPlotline logAndReportException:exception forMethod:@"getFeatureFlag"];
149
250
  reject(@"error", exception.reason, nil); // Handle errors
150
251
  }
151
252
  }
@@ -157,10 +258,16 @@ RCT_EXPORT_METHOD(getFeatureFlagPayload:(NSString *)key
157
258
  {
158
259
  @try {
159
260
  [Plotline setOnFeatureFlagsLoadedListenerWithFeatureFlagsLoadedListener:^{
160
- NSString *result = [Plotline getFeatureFlagPayloadWithKey:key];
161
- resolve(result);
261
+ @try {
262
+ NSString *result = [Plotline getFeatureFlagPayloadWithKey:key];
263
+ resolve(result);
264
+ } @catch (NSException *exception) {
265
+ [RNPlotline logAndReportException:exception forMethod:@"getFeatureFlagPayload"];
266
+ reject(@"error", exception.reason, nil);
267
+ }
162
268
  }];
163
269
  } @catch (NSException *exception) {
270
+ [RNPlotline logAndReportException:exception forMethod:@"getFeatureFlagPayload"];
164
271
  reject(@"error", exception.reason, nil); // Handle errors
165
272
  }
166
273
  }
@@ -168,4 +275,3 @@ RCT_EXPORT_METHOD(getFeatureFlagPayload:(NSString *)key
168
275
  RCT_EXPORT_MODULE();
169
276
 
170
277
  @end
171
-
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "plotline-engage",
3
- "version": "5.6.2",
3
+ "version": "5.6.4",
4
4
  "description": "React Native plugin for Plotline",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"