expo 57.0.13 → 57.0.14
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/android/build.gradle +2 -2
- package/build/dom/dom-entry.d.ts.map +1 -1
- package/build/dom/injection.d.ts +1 -0
- package/build/dom/injection.d.ts.map +1 -1
- package/build/dom/marshal.d.ts +1 -0
- package/build/dom/marshal.d.ts.map +1 -1
- package/build/dom/webview-wrapper.d.ts.map +1 -1
- package/bundledNativeModules.json +22 -22
- package/package.json +11 -11
- package/src/dom/__tests__/dom-ready-test.native.ts +125 -0
- package/src/dom/dom-entry.tsx +3 -1
- package/src/dom/injection.ts +1 -0
- package/src/dom/marshal.tsx +5 -1
- package/src/dom/webview-wrapper.tsx +7 -0
- package/template.tgz +0 -0
package/android/build.gradle
CHANGED
|
@@ -10,7 +10,7 @@ buildscript {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
group = 'host.exp.exponent'
|
|
13
|
-
version = '57.0.
|
|
13
|
+
version = '57.0.14'
|
|
14
14
|
|
|
15
15
|
expoModule {
|
|
16
16
|
// We can't prebuild the module because it depends on the generated files.
|
|
@@ -21,7 +21,7 @@ android {
|
|
|
21
21
|
namespace "expo.core"
|
|
22
22
|
defaultConfig {
|
|
23
23
|
versionCode 1
|
|
24
|
-
versionName "57.0.
|
|
24
|
+
versionName "57.0.14"
|
|
25
25
|
consumerProguardFiles("proguard-rules.pro")
|
|
26
26
|
}
|
|
27
27
|
testOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom-entry.d.ts","sourceRoot":"","sources":["../../src/dom/dom-entry.tsx"],"names":[],"mappings":"AACA,OAAO,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACtC;AA8CD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,GAAG,
|
|
1
|
+
{"version":3,"file":"dom-entry.d.ts","sourceRoot":"","sources":["../../src/dom/dom-entry.tsx"],"names":[],"mappings":"AACA,OAAO,qBAAqB,CAAC;AAI7B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;CACtC;AA8CD,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,GAAG,QAqElD"}
|
package/build/dom/injection.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const NATIVE_ACTION_RESULT = "$$native_action_result";
|
|
|
4
4
|
export declare const DOM_EVENT = "$$dom_event";
|
|
5
5
|
export declare const MATCH_CONTENTS_EVENT = "$$match_contents_event";
|
|
6
6
|
export declare const REGISTER_DOM_IMPERATIVE_HANDLE_PROPS = "$$register_dom_imperative_handle_props";
|
|
7
|
+
export declare const DOM_READY = "$$dom_ready";
|
|
7
8
|
export declare const getInjectEventScript: <T extends BridgeMessage<any>>(detail: T) => string;
|
|
8
9
|
export declare function getInjectBodySizeObserverScript(): string;
|
|
9
10
|
//# sourceMappingURL=injection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../../src/dom/injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAC/C,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,SAAS,gBAAgB,CAAC;AACvC,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,oCAAoC,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"injection.d.ts","sourceRoot":"","sources":["../../src/dom/injection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,aAAa,oBAAoB,CAAC;AAC/C,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,SAAS,gBAAgB,CAAC;AACvC,eAAO,MAAM,oBAAoB,2BAA2B,CAAC;AAC7D,eAAO,MAAM,oCAAoC,2CAA2C,CAAC;AAC7F,eAAO,MAAM,SAAS,gBAAgB,CAAC;AAEvC,eAAO,MAAM,oBAAoB,GAAI,CAAC,SAAS,aAAa,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,WAO3E,CAAC;AAEF,wBAAgB,+BAA+B,WAsC9C"}
|
package/build/dom/marshal.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { BridgeMessage, JSONValue } from './dom.types';
|
|
2
2
|
export declare const addEventListener: <TData extends JSONValue>(onSubscribe: (message: BridgeMessage<TData>) => void) => (() => void);
|
|
3
|
+
export declare const notifyDOMReady: () => void;
|
|
3
4
|
export declare function getActionsObject(): Record<string, (...args: any[]) => void | Promise<any>>;
|
|
4
5
|
//# sourceMappingURL=marshal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marshal.d.ts","sourceRoot":"","sources":["../../src/dom/marshal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAgB5D,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,SAAS,EACtD,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,IAAI,KACnD,CAAC,MAAM,IAAI,CAab,CAAC;AAsCF,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAuC1F"}
|
|
1
|
+
{"version":3,"file":"marshal.d.ts","sourceRoot":"","sources":["../../src/dom/marshal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAgB5D,eAAO,MAAM,gBAAgB,GAAI,KAAK,SAAS,SAAS,EACtD,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC,KAAK,IAAI,KACnD,CAAC,MAAM,IAAI,CAab,CAAC;AAEF,eAAO,MAAM,cAAc,YAE1B,CAAC;AAsCF,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAuC1F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webview-wrapper.d.ts","sourceRoot":"","sources":["../../src/dom/webview-wrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"webview-wrapper.d.ts","sourceRoot":"","sources":["../../src/dom/webview-wrapper.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAa7D,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAG5C,KAAK,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;AAElF,UAAU,KAAK;IACb,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,GAAG,CAAC,EAAE,gBAAgB,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CAC7B;AAED,QAAA,MAAM,UAAU,mFAiNd,CAAC;AAiBH,wBAAgB,cAAc,CAC5B,iBAAiB,EAAE,OAAO,GACzB,KAAK,CAAC,yBAAyB,CAAC,eAAe,CAAC,CASlD;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"@expo/dom-webview": "~57.0.1",
|
|
3
|
-
"@expo/fingerprint": "~0.20.
|
|
4
|
-
"@expo/metro-runtime": "~57.0.
|
|
3
|
+
"@expo/fingerprint": "~0.20.8",
|
|
4
|
+
"@expo/metro-runtime": "~57.0.11",
|
|
5
5
|
"@expo/vector-icons": "^15.0.2",
|
|
6
6
|
"@expo/ui": "~57.0.11",
|
|
7
7
|
"@react-native-async-storage/async-storage": "2.2.0",
|
|
@@ -17,32 +17,32 @@
|
|
|
17
17
|
"expo-analytics-amplitude": "~11.3.0",
|
|
18
18
|
"expo-app-auth": "~11.1.0",
|
|
19
19
|
"expo-app-loader-provider": "~8.0.0",
|
|
20
|
-
"expo-app-metrics": "~57.0.
|
|
20
|
+
"expo-app-metrics": "~57.0.12",
|
|
21
21
|
"expo-apple-authentication": "~57.0.1",
|
|
22
22
|
"expo-application": "~57.0.2",
|
|
23
|
-
"expo-asset": "~57.0.
|
|
23
|
+
"expo-asset": "~57.0.12",
|
|
24
24
|
"expo-audio": "~57.0.3",
|
|
25
25
|
"expo-auth-session": "~57.0.7",
|
|
26
|
-
"expo-background-fetch": "~57.0.
|
|
27
|
-
"expo-background-task": "~57.0.
|
|
26
|
+
"expo-background-fetch": "~57.0.11",
|
|
27
|
+
"expo-background-task": "~57.0.11",
|
|
28
28
|
"expo-battery": "~57.0.2",
|
|
29
29
|
"expo-blur": "~57.0.2",
|
|
30
30
|
"expo-brightness": "~57.0.1",
|
|
31
|
-
"expo-brownfield": "~57.0.
|
|
32
|
-
"expo-build-properties": "~57.0.
|
|
31
|
+
"expo-brownfield": "~57.0.12",
|
|
32
|
+
"expo-build-properties": "~57.0.12",
|
|
33
33
|
"expo-calendar": "~57.0.2",
|
|
34
34
|
"expo-camera": "~57.0.3",
|
|
35
35
|
"expo-cellular": "~57.0.1",
|
|
36
36
|
"expo-checkbox": "~57.0.0",
|
|
37
37
|
"expo-clipboard": "~57.0.1",
|
|
38
|
-
"expo-constants": "~57.0.
|
|
38
|
+
"expo-constants": "~57.0.12",
|
|
39
39
|
"expo-contacts": "~57.0.4",
|
|
40
40
|
"expo-crypto": "~57.0.1",
|
|
41
|
-
"expo-dev-client": "~57.0.
|
|
41
|
+
"expo-dev-client": "~57.0.13",
|
|
42
42
|
"expo-device": "~57.0.1",
|
|
43
43
|
"expo-document-picker": "~57.0.1",
|
|
44
44
|
"expo-eas-client": "~57.0.1",
|
|
45
|
-
"expo-file-system": "~57.0.
|
|
45
|
+
"expo-file-system": "~57.0.4",
|
|
46
46
|
"expo-font": "~57.0.1",
|
|
47
47
|
"expo-gl": "~57.0.2",
|
|
48
48
|
"expo-glass-effect": "~57.0.1",
|
|
@@ -50,16 +50,16 @@
|
|
|
50
50
|
"expo-haptics": "~57.0.1",
|
|
51
51
|
"expo-image": "~57.0.3",
|
|
52
52
|
"expo-image-loader": "~57.0.1",
|
|
53
|
-
"expo-image-manipulator": "~57.0.
|
|
54
|
-
"expo-image-picker": "~57.0.
|
|
53
|
+
"expo-image-manipulator": "~57.0.11",
|
|
54
|
+
"expo-image-picker": "~57.0.11",
|
|
55
55
|
"expo-intent-launcher": "~57.0.1",
|
|
56
|
-
"expo-insights": "~57.0.
|
|
56
|
+
"expo-insights": "~57.0.11",
|
|
57
57
|
"expo-keep-awake": "~57.0.1",
|
|
58
58
|
"expo-linear-gradient": "~57.0.1",
|
|
59
59
|
"expo-linking": "~57.0.6",
|
|
60
60
|
"expo-local-authentication": "~57.0.2",
|
|
61
61
|
"expo-localization": "~57.0.1",
|
|
62
|
-
"expo-location": "~57.0.
|
|
62
|
+
"expo-location": "~57.0.11",
|
|
63
63
|
"expo-mail-composer": "~57.0.1",
|
|
64
64
|
"expo-manifests": "~57.0.1",
|
|
65
65
|
"expo-maps": "~57.0.1",
|
|
@@ -70,28 +70,28 @@
|
|
|
70
70
|
"expo-modules-core": "~57.0.11",
|
|
71
71
|
"expo-navigation-bar": "~57.0.2",
|
|
72
72
|
"expo-network": "~57.0.1",
|
|
73
|
-
"expo-notifications": "~57.0.
|
|
74
|
-
"expo-observe": "~57.0.
|
|
73
|
+
"expo-notifications": "~57.0.12",
|
|
74
|
+
"expo-observe": "~57.0.14",
|
|
75
75
|
"expo-print": "~57.0.1",
|
|
76
76
|
"expo-live-photo": "~57.0.1",
|
|
77
|
-
"expo-router": "~57.0.
|
|
77
|
+
"expo-router": "~57.0.14",
|
|
78
78
|
"expo-screen-capture": "~57.0.2",
|
|
79
79
|
"expo-screen-orientation": "~57.0.1",
|
|
80
80
|
"expo-secure-store": "~57.0.1",
|
|
81
81
|
"expo-sensors": "~57.0.2",
|
|
82
82
|
"expo-server": "~57.0.3",
|
|
83
|
-
"expo-sharing": "~57.0.
|
|
83
|
+
"expo-sharing": "~57.0.13",
|
|
84
84
|
"expo-sms": "~57.0.1",
|
|
85
85
|
"expo-speech": "~57.0.1",
|
|
86
|
-
"expo-splash-screen": "~57.0.
|
|
86
|
+
"expo-splash-screen": "~57.0.7",
|
|
87
87
|
"expo-sqlite": "~57.0.1",
|
|
88
88
|
"expo-status-bar": "~57.0.1",
|
|
89
89
|
"expo-store-review": "~57.0.2",
|
|
90
90
|
"expo-symbols": "~57.0.2",
|
|
91
91
|
"expo-system-ui": "~57.0.2",
|
|
92
|
-
"expo-task-manager": "~57.0.
|
|
92
|
+
"expo-task-manager": "~57.0.11",
|
|
93
93
|
"expo-tracking-transparency": "~57.0.1",
|
|
94
|
-
"expo-updates": "~57.0.
|
|
94
|
+
"expo-updates": "~57.0.15",
|
|
95
95
|
"expo-video-thumbnails": "~57.0.1",
|
|
96
96
|
"expo-video": "~57.0.2",
|
|
97
97
|
"expo-web-browser": "~57.0.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo",
|
|
3
|
-
"version": "57.0.
|
|
3
|
+
"version": "57.0.14",
|
|
4
4
|
"description": "The Expo SDK",
|
|
5
5
|
"main": "src/Expo.ts",
|
|
6
6
|
"module": "src/Expo.ts",
|
|
@@ -68,21 +68,21 @@
|
|
|
68
68
|
"homepage": "https://github.com/expo/expo/tree/main/packages/expo",
|
|
69
69
|
"dependencies": {
|
|
70
70
|
"@babel/runtime": "^7.20.0",
|
|
71
|
-
"@expo/cli": "^57.0.
|
|
72
|
-
"@expo/config": "~57.0.
|
|
71
|
+
"@expo/cli": "^57.0.16",
|
|
72
|
+
"@expo/config": "~57.0.8",
|
|
73
73
|
"@expo/config-plugins": "~57.0.8",
|
|
74
74
|
"@expo/devtools": "~57.0.1",
|
|
75
75
|
"@expo/dom-webview": "~57.0.1",
|
|
76
|
-
"@expo/fingerprint": "^0.20.
|
|
76
|
+
"@expo/fingerprint": "^0.20.8",
|
|
77
77
|
"@expo/local-build-cache-provider": "^57.0.6",
|
|
78
|
-
"@expo/log-box": "^57.0.
|
|
78
|
+
"@expo/log-box": "^57.0.3",
|
|
79
79
|
"@expo/metro": "~56.0.0",
|
|
80
80
|
"@expo/metro-config": "~57.0.8",
|
|
81
81
|
"@ungap/structured-clone": "^1.3.0",
|
|
82
82
|
"babel-preset-expo": "~57.0.7",
|
|
83
|
-
"expo-asset": "~57.0.
|
|
84
|
-
"expo-constants": "~57.0.
|
|
85
|
-
"expo-file-system": "~57.0.
|
|
83
|
+
"expo-asset": "~57.0.12",
|
|
84
|
+
"expo-constants": "~57.0.12",
|
|
85
|
+
"expo-file-system": "~57.0.4",
|
|
86
86
|
"expo-font": "~57.0.1",
|
|
87
87
|
"expo-keep-awake": "~57.0.1",
|
|
88
88
|
"expo-modules-autolinking": "~57.0.10",
|
|
@@ -101,8 +101,8 @@
|
|
|
101
101
|
"rimraf": "^6.1.2",
|
|
102
102
|
"web-streams-polyfill": "^3.3.2",
|
|
103
103
|
"@expo/dom-webview": "57.0.1",
|
|
104
|
-
"
|
|
105
|
-
"expo-
|
|
104
|
+
"expo-updates": "57.0.15",
|
|
105
|
+
"@expo/metro-runtime": "57.0.11"
|
|
106
106
|
},
|
|
107
107
|
"peerDependencies": {
|
|
108
108
|
"@expo/dom-webview": "*",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"scripts/resolveAppEntry.js"
|
|
140
140
|
]
|
|
141
141
|
},
|
|
142
|
-
"gitHead": "
|
|
142
|
+
"gitHead": "391d762fa5059cebf63ef2381da93994ce97fc63",
|
|
143
143
|
"scripts": {
|
|
144
144
|
"build": "tsc",
|
|
145
145
|
"clean": "rimraf build",
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// `.native.ts` on purpose.
|
|
2
|
+
// The node project makes `marshal`'s DOM side a no-op, and jsdom has no
|
|
3
|
+
// `MessageChannel` for `react-dom/server`.
|
|
4
|
+
import type { BridgeMessage } from '../dom.types';
|
|
5
|
+
|
|
6
|
+
describe('notifyDOMReady', () => {
|
|
7
|
+
const postMessage = jest.fn();
|
|
8
|
+
const hasWebViewBridge = jest.fn();
|
|
9
|
+
let hasGlobalWindow = false;
|
|
10
|
+
|
|
11
|
+
beforeEach(() => {
|
|
12
|
+
// `marshal` reads the environment at module scope, so set it up before requiring it.
|
|
13
|
+
jest.resetModules();
|
|
14
|
+
jest.doMock('../webview-bridge', () => ({
|
|
15
|
+
hasWebViewBridge,
|
|
16
|
+
getWebViewBridge: () => ({ postMessage, injectedObjectJson: () => '{}' }),
|
|
17
|
+
}));
|
|
18
|
+
hasGlobalWindow = typeof globalThis.window !== 'undefined';
|
|
19
|
+
globalThis.window ??= {} as Window & typeof globalThis;
|
|
20
|
+
globalThis.window.$$EXPO_INITIAL_PROPS = { names: [], props: {} };
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
delete globalThis.window.$$EXPO_INITIAL_PROPS;
|
|
25
|
+
// The next suite renders in node and expects no `window`.
|
|
26
|
+
if (!hasGlobalWindow) {
|
|
27
|
+
delete (globalThis as any).window;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('should post a $$dom_ready message to the native side', () => {
|
|
32
|
+
hasWebViewBridge.mockReturnValue(true);
|
|
33
|
+
const { notifyDOMReady } = require('../marshal');
|
|
34
|
+
|
|
35
|
+
notifyDOMReady();
|
|
36
|
+
|
|
37
|
+
expect(postMessage).toHaveBeenCalledWith(JSON.stringify({ type: '$$dom_ready', data: null }));
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should do nothing outside of a DOM component webview', () => {
|
|
41
|
+
hasWebViewBridge.mockReturnValue(false);
|
|
42
|
+
const { notifyDOMReady } = require('../marshal');
|
|
43
|
+
|
|
44
|
+
notifyDOMReady();
|
|
45
|
+
|
|
46
|
+
expect(postMessage).not.toHaveBeenCalled();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
describe('$$dom_ready', () => {
|
|
51
|
+
beforeEach(() => {
|
|
52
|
+
jest.resetModules();
|
|
53
|
+
jest.doMock('../../utils/getDevServer', () => ({
|
|
54
|
+
__esModule: true,
|
|
55
|
+
default: () => ({ url: 'http://localhost:8081' }),
|
|
56
|
+
}));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// `react-dom/server` is the only renderer here, so this mounts without effects.
|
|
60
|
+
// Enough for these tests, since `onMessage` is wired up during render.
|
|
61
|
+
function renderRawWebView(props: Record<string, unknown>) {
|
|
62
|
+
const injectJavaScript = jest.fn();
|
|
63
|
+
let webViewProps: Record<string, any> = {};
|
|
64
|
+
jest.doMock('@expo/dom-webview', () => ({
|
|
65
|
+
WebView: (stubProps: any) => {
|
|
66
|
+
webViewProps = stubProps;
|
|
67
|
+
// `ref` arrives as a plain prop, and the wrapper injects scripts through it.
|
|
68
|
+
stubProps.ref.current = { injectJavaScript };
|
|
69
|
+
return null;
|
|
70
|
+
},
|
|
71
|
+
}));
|
|
72
|
+
const React = require('react');
|
|
73
|
+
const { renderToStaticMarkup } = require('react-dom/server');
|
|
74
|
+
const RawWebView = require('../webview-wrapper').default;
|
|
75
|
+
|
|
76
|
+
renderToStaticMarkup(React.createElement(RawWebView, { filePath: 'index.tsx', ...props }));
|
|
77
|
+
|
|
78
|
+
return { injectJavaScript, webViewProps };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function readInjectedEvent(script: string): BridgeMessage<any> {
|
|
82
|
+
const [, payload] = script.match(/new CustomEvent\("\$\$dom_event",([\s\S]*)\)\);/) ?? [];
|
|
83
|
+
if (payload == null) {
|
|
84
|
+
throw new Error(`Expected a script injecting a DOM event, got: ${script}`);
|
|
85
|
+
}
|
|
86
|
+
return JSON.parse(payload).detail;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function domReadyEvent() {
|
|
90
|
+
return { nativeEvent: { data: JSON.stringify({ type: '$$dom_ready', data: null }) } };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
it('should be answered with the marshalled props', () => {
|
|
94
|
+
const { injectJavaScript, webViewProps } = renderRawWebView({
|
|
95
|
+
title: 'updated',
|
|
96
|
+
onAction: () => {},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
webViewProps.onMessage(domReadyEvent());
|
|
100
|
+
|
|
101
|
+
expect(injectJavaScript).toHaveBeenCalledTimes(1);
|
|
102
|
+
expect(readInjectedEvent(injectJavaScript.mock.calls[0][0])).toEqual({
|
|
103
|
+
type: '$$props',
|
|
104
|
+
data: { names: ['onAction'], props: { title: 'updated' } },
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('should be answered every time, since the webview can reload', () => {
|
|
109
|
+
const { injectJavaScript, webViewProps } = renderRawWebView({ title: 'updated' });
|
|
110
|
+
|
|
111
|
+
webViewProps.onMessage(domReadyEvent());
|
|
112
|
+
webViewProps.onMessage(domReadyEvent());
|
|
113
|
+
|
|
114
|
+
expect(injectJavaScript).toHaveBeenCalledTimes(2);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('should not reach the `onMessage` handler of the component', () => {
|
|
118
|
+
const onMessage = jest.fn();
|
|
119
|
+
const { webViewProps } = renderRawWebView({ dom: { onMessage } });
|
|
120
|
+
|
|
121
|
+
webViewProps.onMessage(domReadyEvent());
|
|
122
|
+
|
|
123
|
+
expect(onMessage).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
});
|
package/src/dom/dom-entry.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import '@expo/metro-runtime';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
|
|
6
6
|
import type { JSONValue } from './dom.types';
|
|
7
|
-
import { addEventListener, getActionsObject } from './marshal';
|
|
7
|
+
import { addEventListener, getActionsObject, notifyDOMReady } from './marshal';
|
|
8
8
|
import registerRootComponent from '../launch/registerRootComponent';
|
|
9
9
|
|
|
10
10
|
export interface MarshalledProps {
|
|
@@ -82,6 +82,8 @@ export function registerDOMComponent(AppModule: any) {
|
|
|
82
82
|
setProps(msg.data as MarshalledProps);
|
|
83
83
|
}
|
|
84
84
|
});
|
|
85
|
+
// Must stay after `addEventListener`: props emitted before it existed were dropped.
|
|
86
|
+
notifyDOMReady();
|
|
85
87
|
return () => {
|
|
86
88
|
remove();
|
|
87
89
|
};
|
package/src/dom/injection.ts
CHANGED
|
@@ -5,6 +5,7 @@ export const NATIVE_ACTION_RESULT = '$$native_action_result';
|
|
|
5
5
|
export const DOM_EVENT = '$$dom_event';
|
|
6
6
|
export const MATCH_CONTENTS_EVENT = '$$match_contents_event';
|
|
7
7
|
export const REGISTER_DOM_IMPERATIVE_HANDLE_PROPS = '$$register_dom_imperative_handle_props';
|
|
8
|
+
export const DOM_READY = '$$dom_ready';
|
|
8
9
|
|
|
9
10
|
export const getInjectEventScript = <T extends BridgeMessage<any>>(detail: T) => {
|
|
10
11
|
return `;(function() {
|
package/src/dom/marshal.tsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BridgeMessage, JSONValue } from './dom.types';
|
|
2
|
-
import { DOM_EVENT, NATIVE_ACTION, NATIVE_ACTION_RESULT } from './injection';
|
|
2
|
+
import { DOM_EVENT, DOM_READY, NATIVE_ACTION, NATIVE_ACTION_RESULT } from './injection';
|
|
3
3
|
import { getWebViewBridge, hasWebViewBridge } from './webview-bridge';
|
|
4
4
|
|
|
5
5
|
const IS_DOM =
|
|
@@ -31,6 +31,10 @@ export const addEventListener = <TData extends JSONValue>(
|
|
|
31
31
|
};
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
export const notifyDOMReady = () => {
|
|
35
|
+
emit({ type: DOM_READY, data: null });
|
|
36
|
+
};
|
|
37
|
+
|
|
34
38
|
function invokeNativeAction(actionId: string, args: any[]): Promise<any> {
|
|
35
39
|
if (!IS_DOM) {
|
|
36
40
|
throw new Error('Cannot invoke native actions outside of a webview');
|
|
@@ -11,6 +11,7 @@ import type { DOMPropsInternal } from './dom-internal.types';
|
|
|
11
11
|
import type { BridgeMessage, WebViewProps, WebViewRef } from './dom.types';
|
|
12
12
|
import { _emitGlobalEvent } from './global-events';
|
|
13
13
|
import {
|
|
14
|
+
DOM_READY,
|
|
14
15
|
getInjectBodySizeObserverScript,
|
|
15
16
|
getInjectEventScript,
|
|
16
17
|
MATCH_CONTENTS_EVENT,
|
|
@@ -177,6 +178,12 @@ const RawWebView = React.forwardRef<object, Props>((props, ref) => {
|
|
|
177
178
|
return;
|
|
178
179
|
}
|
|
179
180
|
|
|
181
|
+
if (type === DOM_READY) {
|
|
182
|
+
// Re-send the props the DOM side missed while the WebView was loading.
|
|
183
|
+
emit({ type: '$$props', data: smartActions });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
if (type === REGISTER_DOM_IMPERATIVE_HANDLE_PROPS) {
|
|
181
188
|
domImperativeHandlePropsRef.current = data;
|
|
182
189
|
return;
|
package/template.tgz
CHANGED
|
Binary file
|