expo-modules-core 1.2.0 β†’ 1.2.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/CHANGELOG.md CHANGED
@@ -10,6 +10,19 @@
10
10
 
11
11
  ### πŸ’‘ Others
12
12
 
13
+ ## 1.2.2 β€” 2023-02-14
14
+
15
+ ### πŸ› Bug fixes
16
+
17
+ - [iOS] Fixed convertible implementation for `URL` type to support unencoded UTF8 urls and file paths. ([#21139](https://github.com/expo/expo/pull/21139) by [@tsapeta](https://github.com/tsapeta))
18
+ - Fixed AppDelegateSubscriber broken when running on iOS dynamic framework or static framework mode. ([#21206](https://github.com/expo/expo/pull/21206) by [@kudo](https://github.com/kudo))
19
+
20
+ ## 1.2.1 β€” 2023-02-09
21
+
22
+ ### πŸ› Bug fixes
23
+
24
+ - Fix crash when reloading app while expo-av video is playing. ([#21118](https://github.com/expo/expo/pull/21118) by [@janicduplessis](https://github.com/janicduplessis))
25
+
13
26
  ## 1.2.0 β€” 2023-02-03
14
27
 
15
28
  ### πŸŽ‰ New features
package/README.md CHANGED
@@ -1,4 +1,11 @@
1
- # expo-modules-core
1
+ <p>
2
+ <a href="https://docs.expo.dev/modules/">
3
+ <img
4
+ src="../../.github/resources/expo-modules-core.svg"
5
+ alt="expo-modules-core"
6
+ height="64" />
7
+ </a>
8
+ </p>
2
9
 
3
10
  The core of Expo Modules architecture.
4
11
 
@@ -4,7 +4,7 @@ class KotlinExpoModulesCorePlugin implements Plugin<Project> {
4
4
  project.ext.kotlinVersion = {
5
5
  project.rootProject.ext.has("kotlinVersion")
6
6
  ? project.rootProject.ext.get("kotlinVersion")
7
- : "1.6.10"
7
+ : "1.8.10"
8
8
  }
9
9
  }
10
10
  }
@@ -6,7 +6,7 @@ apply plugin: 'maven-publish'
6
6
  apply plugin: "de.undercouch.download"
7
7
 
8
8
  group = 'host.exp.exponent'
9
- version = '1.2.0'
9
+ version = '1.2.2'
10
10
 
11
11
  buildscript {
12
12
  def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
@@ -25,7 +25,7 @@ buildscript {
25
25
  if (ext.has("kotlinVersion")) {
26
26
  ext.kotlinVersion()
27
27
  } else {
28
- ext.safeExtGet("kotlinVersion", "1.6.10")
28
+ ext.safeExtGet("kotlinVersion", "1.8.10")
29
29
  }
30
30
  }
31
31
 
@@ -173,7 +173,7 @@ android {
173
173
  targetSdkVersion safeExtGet("targetSdkVersion", 33)
174
174
  consumerProguardFiles 'proguard-rules.pro'
175
175
  versionCode 1
176
- versionName "1.2.0"
176
+ versionName "1.2.2"
177
177
  buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled.toString()
178
178
 
179
179
  testInstrumentationRunner "expo.modules.TestRunner"
@@ -42,7 +42,7 @@
42
42
  return _expoAppDelegate;
43
43
  }
44
44
 
45
- #if __has_include(<React-RCTAppDelegate/RCTAppDelegate.h>)
45
+ #if __has_include(<React-RCTAppDelegate/RCTAppDelegate.h>) || __has_include(<React_RCTAppDelegate/RCTAppDelegate.h>)
46
46
 
47
47
  - (UIView *)findRootView:(UIApplication *)application
48
48
  {
@@ -13,11 +13,10 @@ import CoreGraphics
13
13
 
14
14
  extension URL: Convertible {
15
15
  public static func convert(from value: Any?) throws -> Self {
16
- if let uri = value as? String, let url = URL(string: uri) {
17
- // `URL(string:)` is an optional init but it doesn't imply it's a valid URL,
18
- // so here we don't check for the correctness of the URL.
19
- // If it has no scheme, we assume it was the file path.
20
- return url.scheme != nil ? url : URL(fileURLWithPath: uri)
16
+ if let value = value as? String, let encodedValue = percentEncodeUrlString(value), let url = URL(string: encodedValue) {
17
+ // If it has no scheme, we assume it was the file path which needs to be recreated to be recognized as the file url.
18
+ // Notice that it uses the decoded value as the file path doesn't have to be percent-encoded.
19
+ return url.scheme != nil ? url : URL(fileURLWithPath: value)
21
20
  }
22
21
  throw Conversions.ConvertingException<URL>(value)
23
22
  }
@@ -26,3 +26,21 @@ internal func toNSError(_ error: Error) -> NSError {
26
26
  }
27
27
  return error as NSError
28
28
  }
29
+
30
+ /**
31
+ Makes sure the url string is percent encoded. If the given string is already encoded, it's decoded first.
32
+ Note that it encodes only characters that are not allowed in the url query and '#' that indicates the fragment part.
33
+ */
34
+ internal func percentEncodeUrlString(_ url: String) -> String? {
35
+ // The value may come unencoded or already encoded, so first we try to decode it.
36
+ // `removingPercentEncoding` returns nil when the string contains an invalid percent-encoded sequence,
37
+ // but that usually means the value came unencoded, so it falls back to the given string.
38
+ let decodedString = url.removingPercentEncoding ?? url
39
+
40
+ // A `CharacterSet` with all query-allowed characters and the hash which is not allowed in the query,
41
+ // but it must stay unencoded to indicate the start of the url fragment part.
42
+ let allowedCharactersSet = CharacterSet.urlQueryAllowed.union(CharacterSet(charactersIn: "#"))
43
+
44
+ // Do the percent encoding, but note that it may still return nil when it's not possible to encode for some reason.
45
+ return decodedString.addingPercentEncoding(withAllowedCharacters: allowedCharactersSet)
46
+ }
@@ -76,7 +76,7 @@ private func createEventSetter(eventName: String, bridge: RCTBridge?) -> RCTProp
76
76
  installEventDispatcher(forEvent: eventName, onView: target) { [weak target] (body: [String: Any]) in
77
77
  if let target = target {
78
78
  let componentEvent = RCTComponentEvent(name: eventName, viewTag: target.reactTag, body: body)
79
- bridge?.eventDispatcher().send(componentEvent)
79
+ bridge?.eventDispatcher()?.send(componentEvent)
80
80
  }
81
81
  }
82
82
  }
@@ -16,6 +16,62 @@ class ConvertiblesSpec: ExpoSpec {
16
16
  expect(url.absoluteString) == remoteUrlString
17
17
  }
18
18
 
19
+ it("converts from url with unencoded query") {
20
+ let query = "param=πŸ₯“"
21
+ let urlString = "https://expo.dev/?\(query)"
22
+ let url = try URL.convert(from: urlString)
23
+
24
+ if #available(iOS 16.0, *) {
25
+ expect(url.query(percentEncoded: true)) == "param=%F0%9F%A5%93"
26
+ expect(url.query(percentEncoded: false)) == query
27
+ }
28
+ expect(url.query) == "param=%F0%9F%A5%93"
29
+ expect(url.absoluteString) == "https://expo.dev/?param=%F0%9F%A5%93"
30
+ expect(url.absoluteString.removingPercentEncoding) == urlString
31
+ }
32
+
33
+ it("converts from url with encoded query") {
34
+ let query = "param=%F0%9F%A5%93"
35
+ let urlString = "https://expo.dev/?\(query)"
36
+ let url = try URL.convert(from: urlString)
37
+
38
+ if #available(iOS 16.0, *) {
39
+ expect(url.query(percentEncoded: true)) == query
40
+ expect(url.query(percentEncoded: false)) == "param=πŸ₯“"
41
+ }
42
+ expect(url.query) == query
43
+ expect(url.absoluteString) == urlString
44
+ expect(url.absoluteString.removingPercentEncoding) == "https://expo.dev/?param=πŸ₯“"
45
+ }
46
+
47
+ it("converts from url containing percent character") {
48
+ // The percent character alone requires percent-encoding to `%25`.
49
+ let query = "param=%"
50
+ let urlString = "https://expo.dev/?\(query)"
51
+ let url = try URL.convert(from: urlString)
52
+
53
+ if #available(iOS 16.0, *) {
54
+ expect(url.query(percentEncoded: true)) == "param=%25"
55
+ expect(url.query(percentEncoded: false)) == query
56
+ }
57
+ expect(url.query) == "param=%25"
58
+ expect(url.absoluteString) == "https://expo.dev/?param=%25"
59
+ expect(url.absoluteString.removingPercentEncoding) == urlString
60
+ }
61
+
62
+ it("converts from url containing the anchor") {
63
+ // The hash is not allowed in the query (requires percent-encoding),
64
+ // but we want it to be recognized as the beginning of the fragment,
65
+ // thus it cannot be percent-encoded.
66
+ let query = "param=#expo"
67
+ let urlString = "https://expo.dev/?\(query)"
68
+ let url = try URL.convert(from: urlString)
69
+
70
+ expect(url.query) == "param="
71
+ expect(url.fragment) == "expo"
72
+ expect(url.absoluteString) == urlString
73
+ }
74
+
19
75
  it("converts from file url") {
20
76
  let fileUrlString = "file:///expo/tmp"
21
77
  let url = try URL.convert(from: fileUrlString)
@@ -29,11 +85,30 @@ class ConvertiblesSpec: ExpoSpec {
29
85
  let filePath = "/expo/image.png"
30
86
  let url = try URL.convert(from: filePath)
31
87
 
88
+ expect(url.scheme) == "file"
32
89
  expect(url.path) == filePath
33
90
  expect(url.absoluteString) == "file://\(filePath)"
34
91
  expect(url.isFileURL) == true
35
92
  }
36
93
 
94
+ it("converts from file path with UTF8 characters") {
95
+ let filePath = "/中文ÅÄÖąÓśĆñ.gif"
96
+ let url = try URL.convert(from: filePath)
97
+
98
+ expect(url.scheme) == "file"
99
+ expect(url.path) == filePath
100
+ expect(url.isFileURL) == true
101
+ }
102
+
103
+ it("converts from file path containing percent character") {
104
+ let filePath = "/%.png"
105
+ let url = try URL.convert(from: filePath)
106
+
107
+ expect(url.scheme) == "file"
108
+ expect(url.path) == filePath
109
+ expect(url.isFileURL) == true
110
+ }
111
+
37
112
  it("throws when no string") {
38
113
  expect { try URL.convert(from: 29.5) }.to(
39
114
  throwError(errorType: Conversions.ConvertingException<URL>.self)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-modules-core",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "The core of Expo Modules architecture",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -42,5 +42,5 @@
42
42
  "@testing-library/react-hooks": "^7.0.1",
43
43
  "expo-module-scripts": "^3.0.0"
44
44
  },
45
- "gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
45
+ "gitHead": "c8107d57eabaedff5d53bc8036d062db12a473c8"
46
46
  }