expo 50.0.13 → 50.0.15

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.
Files changed (31) hide show
  1. package/android/build.gradle +2 -2
  2. package/android/src/reactNativeHostWrapper/expo/modules/ReactNativeHostWrapper.kt +5 -0
  3. package/build/devtools/DevToolsPluginClient.d.ts +18 -4
  4. package/build/devtools/DevToolsPluginClient.d.ts.map +1 -1
  5. package/build/devtools/DevToolsPluginClient.js +91 -0
  6. package/build/devtools/DevToolsPluginClient.js.map +1 -1
  7. package/build/devtools/DevToolsPluginClientImplApp.d.ts +0 -27
  8. package/build/devtools/DevToolsPluginClientImplApp.d.ts.map +1 -1
  9. package/build/devtools/DevToolsPluginClientImplApp.js +2 -75
  10. package/build/devtools/DevToolsPluginClientImplApp.js.map +1 -1
  11. package/build/devtools/DevToolsPluginClientImplBrowser.d.ts +0 -16
  12. package/build/devtools/DevToolsPluginClientImplBrowser.d.ts.map +1 -1
  13. package/build/devtools/DevToolsPluginClientImplBrowser.js +2 -57
  14. package/build/devtools/DevToolsPluginClientImplBrowser.js.map +1 -1
  15. package/build/devtools/WebSocketBackingStore.d.ts +10 -0
  16. package/build/devtools/WebSocketBackingStore.d.ts.map +1 -0
  17. package/build/devtools/WebSocketBackingStore.js +13 -0
  18. package/build/devtools/WebSocketBackingStore.js.map +1 -0
  19. package/build/devtools/WebSocketWithReconnect.d.ts +75 -0
  20. package/build/devtools/WebSocketWithReconnect.d.ts.map +1 -0
  21. package/build/devtools/WebSocketWithReconnect.js +204 -0
  22. package/build/devtools/WebSocketWithReconnect.js.map +1 -0
  23. package/build/devtools/devtools.types.d.ts +7 -0
  24. package/build/devtools/devtools.types.d.ts.map +1 -1
  25. package/build/devtools/devtools.types.js.map +1 -1
  26. package/build/devtools/logger.d.ts +1 -0
  27. package/build/devtools/logger.d.ts.map +1 -1
  28. package/build/devtools/logger.js +5 -0
  29. package/build/devtools/logger.js.map +1 -1
  30. package/bundledNativeModules.json +5 -5
  31. package/package.json +4 -4
@@ -44,7 +44,7 @@ def getRNVersion() {
44
44
  ensureDependeciesWereEvaluated(project)
45
45
 
46
46
  group = 'host.exp.exponent'
47
- version = '50.0.13'
47
+ version = '50.0.15'
48
48
 
49
49
  buildscript {
50
50
  // Simple helper that allows the root project to override versions declared by this library.
@@ -124,7 +124,7 @@ android {
124
124
  namespace "expo.core"
125
125
  defaultConfig {
126
126
  versionCode 1
127
- versionName "50.0.13"
127
+ versionName "50.0.15"
128
128
  consumerProguardFiles("proguard-rules.pro")
129
129
  }
130
130
  testOptions {
@@ -1,6 +1,7 @@
1
1
  package expo.modules
2
2
 
3
3
  import android.app.Application
4
+ import com.facebook.react.JSEngineResolutionAlgorithm
4
5
  import com.facebook.react.ReactNativeHost
5
6
  import com.facebook.react.ReactPackageTurboModuleManagerDelegate
6
7
  import com.facebook.react.common.SurfaceDelegateFactory
@@ -23,6 +24,10 @@ class ReactNativeHostWrapper(
23
24
  return invokeDelegateMethod("getReactPackageTurboModuleManagerDelegateBuilder")
24
25
  }
25
26
 
27
+ override fun getJSEngineResolutionAlgorithm(): JSEngineResolutionAlgorithm? {
28
+ return invokeDelegateMethod("getJSEngineResolutionAlgorithm")
29
+ }
30
+
26
31
  override fun getShouldRequireActivity(): Boolean {
27
32
  return host.shouldRequireActivity
28
33
  }
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter, EventSubscription } from 'fbemitter';
2
+ import { WebSocketBackingStore } from './WebSocketBackingStore';
2
3
  import type { ConnectionInfo } from './devtools.types';
3
4
  export declare const MESSAGE_PROTOCOL_VERSION = 2;
4
5
  export declare const DevToolsPluginMethod = "Expo:DevToolsPlugin";
@@ -9,22 +10,26 @@ export declare const DevToolsPluginMethod = "Expo:DevToolsPlugin";
9
10
  export declare abstract class DevToolsPluginClient {
10
11
  readonly connectionInfo: ConnectionInfo;
11
12
  protected eventEmitter: EventEmitter;
13
+ private static defaultWSStore;
14
+ private readonly wsStore;
15
+ protected isClosed: boolean;
16
+ protected retries: number;
12
17
  constructor(connectionInfo: ConnectionInfo);
13
18
  /**
14
19
  * Initialize the connection.
15
20
  * @hidden
16
21
  */
17
- abstract initAsync(): Promise<void>;
22
+ initAsync(): Promise<void>;
18
23
  /**
19
24
  * Close the connection.
20
25
  */
21
- abstract closeAsync(): Promise<void>;
26
+ closeAsync(): Promise<void>;
22
27
  /**
23
28
  * Send a message to the other end of DevTools.
24
29
  * @param method A method name.
25
30
  * @param params any extra payload.
26
31
  */
27
- abstract sendMessage(method: string, params: any): void;
32
+ sendMessage(method: string, params: any): void;
28
33
  /**
29
34
  * Subscribe to a message from the other end of DevTools.
30
35
  * @param method Subscribe to a message with a method name.
@@ -40,7 +45,16 @@ export declare abstract class DevToolsPluginClient {
40
45
  /**
41
46
  * Returns whether the client is connected to the server.
42
47
  */
43
- abstract isConnected(): boolean;
48
+ isConnected(): boolean;
49
+ /**
50
+ * The method to create the WebSocket connection.
51
+ */
52
+ protected connectAsync(): Promise<WebSocket>;
44
53
  protected handleMessage: (event: WebSocketMessageEvent) => void;
54
+ /**
55
+ * Get the WebSocket backing store. Exposed for testing.
56
+ * @hidden
57
+ */
58
+ getWebSocketBackingStore(): WebSocketBackingStore;
45
59
  }
46
60
  //# sourceMappingURL=DevToolsPluginClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClient.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAE1D;;;GAGG;AACH,8BAAsB,oBAAoB;aAGL,cAAc,EAAE,cAAc;IAFjE,SAAS,CAAC,YAAY,EAAE,YAAY,CAAsB;gBAEvB,cAAc,EAAE,cAAc;IAEjE;;;OAGG;aACa,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAE1C;;OAEG;aACa,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3C;;;;OAIG;aACa,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;IAE9D;;;;OAIG;IACI,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,iBAAiB;IAI7F;;;;OAIG;IACI,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIpF;;OAEG;aACa,WAAW,IAAI,OAAO;IAEtC,SAAS,CAAC,aAAa,UAAW,qBAAqB,KAAG,IAAI,CAiB5D;CACH"}
1
+ {"version":3,"file":"DevToolsPluginClient.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAIvD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAE1D;;;GAGG;AACH,8BAAsB,oBAAoB;aASL,cAAc,EAAE,cAAc;IARjE,SAAS,CAAC,YAAY,EAAE,YAAY,CAAsB;IAE1D,OAAO,CAAC,MAAM,CAAC,cAAc,CAAsD;IACnF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8D;IAEtF,SAAS,CAAC,QAAQ,UAAS;IAC3B,SAAS,CAAC,OAAO,SAAK;gBAEa,cAAc,EAAE,cAAc;IAIjE;;;OAGG;IACU,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAQvC;;OAEG;IACU,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAWxC;;;;OAIG;IACI,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG;IAkB9C;;;;OAIG;IACI,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,iBAAiB;IAI7F;;;;OAIG;IACI,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,GAAG,IAAI;IAIpF;;OAEG;IACI,WAAW,IAAI,OAAO;IAI7B;;OAEG;IACH,SAAS,CAAC,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAuB5C,SAAS,CAAC,aAAa,UAAW,qBAAqB,KAAG,IAAI,CAiB5D;IAEF;;;OAGG;IACI,wBAAwB,IAAI,qBAAqB;CAGzD"}
@@ -1,4 +1,6 @@
1
1
  import { EventEmitter } from 'fbemitter';
2
+ import { WebSocketBackingStore } from './WebSocketBackingStore';
3
+ import { WebSocketWithReconnect } from './WebSocketWithReconnect';
2
4
  import * as logger from './logger';
3
5
  // This version should be synced with the one in the **createMessageSocketEndpoint.ts** in @react-native-community/cli-server-api
4
6
  export const MESSAGE_PROTOCOL_VERSION = 2;
@@ -10,8 +12,58 @@ export const DevToolsPluginMethod = 'Expo:DevToolsPlugin';
10
12
  export class DevToolsPluginClient {
11
13
  connectionInfo;
12
14
  eventEmitter = new EventEmitter();
15
+ static defaultWSStore = new WebSocketBackingStore();
16
+ wsStore = DevToolsPluginClient.defaultWSStore;
17
+ isClosed = false;
18
+ retries = 0;
13
19
  constructor(connectionInfo) {
14
20
  this.connectionInfo = connectionInfo;
21
+ this.wsStore = connectionInfo.wsStore || DevToolsPluginClient.defaultWSStore;
22
+ }
23
+ /**
24
+ * Initialize the connection.
25
+ * @hidden
26
+ */
27
+ async initAsync() {
28
+ if (this.wsStore.ws == null) {
29
+ this.wsStore.ws = await this.connectAsync();
30
+ }
31
+ this.wsStore.refCount += 1;
32
+ this.wsStore.ws.addEventListener('message', this.handleMessage);
33
+ }
34
+ /**
35
+ * Close the connection.
36
+ */
37
+ async closeAsync() {
38
+ this.isClosed = true;
39
+ this.wsStore.ws?.removeEventListener('message', this.handleMessage);
40
+ this.wsStore.refCount -= 1;
41
+ if (this.wsStore.refCount < 1) {
42
+ this.wsStore.ws?.close();
43
+ this.wsStore.ws = null;
44
+ }
45
+ this.eventEmitter.removeAllListeners();
46
+ }
47
+ /**
48
+ * Send a message to the other end of DevTools.
49
+ * @param method A method name.
50
+ * @param params any extra payload.
51
+ */
52
+ sendMessage(method, params) {
53
+ if (this.wsStore.ws?.readyState === WebSocket.CLOSED) {
54
+ logger.warn('Unable to send message in a disconnected state.');
55
+ return;
56
+ }
57
+ const payload = {
58
+ version: MESSAGE_PROTOCOL_VERSION,
59
+ pluginName: this.connectionInfo.pluginName,
60
+ method: DevToolsPluginMethod,
61
+ params: {
62
+ method,
63
+ params,
64
+ },
65
+ };
66
+ this.wsStore.ws?.send(JSON.stringify(payload));
15
67
  }
16
68
  /**
17
69
  * Subscribe to a message from the other end of DevTools.
@@ -29,6 +81,38 @@ export class DevToolsPluginClient {
29
81
  addMessageListenerOnce(method, listener) {
30
82
  this.eventEmitter.once(method, listener);
31
83
  }
84
+ /**
85
+ * Returns whether the client is connected to the server.
86
+ */
87
+ isConnected() {
88
+ return this.wsStore.ws?.readyState === WebSocket.OPEN;
89
+ }
90
+ /**
91
+ * The method to create the WebSocket connection.
92
+ */
93
+ connectAsync() {
94
+ return new Promise((resolve, reject) => {
95
+ const ws = new WebSocketWithReconnect(`ws://${this.connectionInfo.devServer}/message`, {
96
+ onError: (e) => {
97
+ if (e instanceof Error) {
98
+ console.warn(`Error happened from the WebSocket connection: ${e.message}\n${e.stack}`);
99
+ }
100
+ else {
101
+ console.warn(`Error happened from the WebSocket connection: ${JSON.stringify(e)}`);
102
+ }
103
+ },
104
+ });
105
+ ws.addEventListener('open', () => {
106
+ resolve(ws);
107
+ });
108
+ ws.addEventListener('error', (e) => {
109
+ reject(e);
110
+ });
111
+ ws.addEventListener('close', (e) => {
112
+ logger.info('WebSocket closed', e.code, e.reason);
113
+ });
114
+ });
115
+ }
32
116
  handleMessage = (event) => {
33
117
  let payload;
34
118
  try {
@@ -46,5 +130,12 @@ export class DevToolsPluginClient {
46
130
  }
47
131
  this.eventEmitter.emit(payload.params.method, payload.params.params);
48
132
  };
133
+ /**
134
+ * Get the WebSocket backing store. Exposed for testing.
135
+ * @hidden
136
+ */
137
+ getWebSocketBackingStore() {
138
+ return this.wsStore;
139
+ }
49
140
  }
50
141
  //# sourceMappingURL=DevToolsPluginClient.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClient.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,WAAW,CAAC;AAG5D,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,iIAAiI;AACjI,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAE1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAE1D;;;GAGG;AACH,MAAM,OAAgB,oBAAoB;IAGL;IAFzB,YAAY,GAAiB,IAAI,YAAY,EAAE,CAAC;IAE1D,YAAmC,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;IAAG,CAAC;IAoBrE;;;;OAIG;IACI,kBAAkB,CAAC,MAAc,EAAE,QAA+B;QACvE,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACI,sBAAsB,CAAC,MAAc,EAAE,QAA+B;QAC3E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAOS,aAAa,GAAG,CAAC,KAA4B,EAAQ,EAAE;QAC/D,IAAI,OAAO,CAAC;QACZ,IAAI;YACF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;YACvC,OAAO;SACR;QAED,IAAI,OAAO,CAAC,OAAO,KAAK,wBAAwB,IAAI,OAAO,CAAC,MAAM,KAAK,oBAAoB,EAAE;YAC3F,OAAO;SACR;QACD,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;YAC/E,OAAO;SACR;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvE,CAAC,CAAC;CACH","sourcesContent":["import { EventEmitter, EventSubscription } from 'fbemitter';\n\nimport type { ConnectionInfo } from './devtools.types';\nimport * as logger from './logger';\n\n// This version should be synced with the one in the **createMessageSocketEndpoint.ts** in @react-native-community/cli-server-api\nexport const MESSAGE_PROTOCOL_VERSION = 2;\n\nexport const DevToolsPluginMethod = 'Expo:DevToolsPlugin';\n\n/**\n * This client is for the Expo DevTools Plugins to communicate between the app and the DevTools webpage hosted in a browser.\n * All the code should be both compatible with browsers and React Native.\n */\nexport abstract class DevToolsPluginClient {\n protected eventEmitter: EventEmitter = new EventEmitter();\n\n public constructor(public readonly connectionInfo: ConnectionInfo) {}\n\n /**\n * Initialize the connection.\n * @hidden\n */\n public abstract initAsync(): Promise<void>;\n\n /**\n * Close the connection.\n */\n public abstract closeAsync(): Promise<void>;\n\n /**\n * Send a message to the other end of DevTools.\n * @param method A method name.\n * @param params any extra payload.\n */\n public abstract sendMessage(method: string, params: any): void;\n\n /**\n * Subscribe to a message from the other end of DevTools.\n * @param method Subscribe to a message with a method name.\n * @param listener Listener to be called when a message is received.\n */\n public addMessageListener(method: string, listener: (params: any) => void): EventSubscription {\n return this.eventEmitter.addListener(method, listener);\n }\n\n /**\n * Subscribe to a message from the other end of DevTools just once.\n * @param method Subscribe to a message with a method name.\n * @param listener Listener to be called when a message is received.\n */\n public addMessageListenerOnce(method: string, listener: (params: any) => void): void {\n this.eventEmitter.once(method, listener);\n }\n\n /**\n * Returns whether the client is connected to the server.\n */\n public abstract isConnected(): boolean;\n\n protected handleMessage = (event: WebSocketMessageEvent): void => {\n let payload;\n try {\n payload = JSON.parse(event.data);\n } catch (e) {\n logger.info('Failed to parse JSON', e);\n return;\n }\n\n if (payload.version !== MESSAGE_PROTOCOL_VERSION || payload.method !== DevToolsPluginMethod) {\n return;\n }\n if (payload.pluginName && payload.pluginName !== this.connectionInfo.pluginName) {\n return;\n }\n\n this.eventEmitter.emit(payload.params.method, payload.params.params);\n };\n}\n"]}
1
+ {"version":3,"file":"DevToolsPluginClient.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAqB,MAAM,WAAW,CAAC;AAE5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC,iIAAiI;AACjI,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAE1C,MAAM,CAAC,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAE1D;;;GAGG;AACH,MAAM,OAAgB,oBAAoB;IASL;IARzB,YAAY,GAAiB,IAAI,YAAY,EAAE,CAAC;IAElD,MAAM,CAAC,cAAc,GAA0B,IAAI,qBAAqB,EAAE,CAAC;IAClE,OAAO,GAA0B,oBAAoB,CAAC,cAAc,CAAC;IAE5E,QAAQ,GAAG,KAAK,CAAC;IACjB,OAAO,GAAG,CAAC,CAAC;IAEtB,YAAmC,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;QAC/D,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,OAAO,IAAI,oBAAoB,CAAC,cAAc,CAAC;IAC/E,CAAC;IAED;;;OAGG;IACI,KAAK,CAAC,SAAS;QACpB,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,IAAI,EAAE;YAC3B,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;SAC7C;QACD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAClE,CAAC;IAED;;OAEG;IACI,KAAK,CAAC,UAAU;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG,CAAC,EAAE;YAC7B,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC;SACxB;QACD,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACI,WAAW,CAAC,MAAc,EAAE,MAAW;QAC5C,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,KAAK,SAAS,CAAC,MAAM,EAAE;YACpD,MAAM,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;YAC/D,OAAO;SACR;QAED,MAAM,OAAO,GAAwB;YACnC,OAAO,EAAE,wBAAwB;YACjC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU;YAC1C,MAAM,EAAE,oBAAoB;YAC5B,MAAM,EAAE;gBACN,MAAM;gBACN,MAAM;aACP;SACF,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACI,kBAAkB,CAAC,MAAc,EAAE,QAA+B;QACvE,OAAO,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED;;;;OAIG;IACI,sBAAsB,CAAC,MAAc,EAAE,QAA+B;QAC3E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACI,WAAW;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,CAAC;IACxD,CAAC;IAED;;OAEG;IACO,YAAY;QACpB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,MAAM,EAAE,GAAG,IAAI,sBAAsB,CAAC,QAAQ,IAAI,CAAC,cAAc,CAAC,SAAS,UAAU,EAAE;gBACrF,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE;oBACtB,IAAI,CAAC,YAAY,KAAK,EAAE;wBACtB,OAAO,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;qBACxF;yBAAM;wBACL,OAAO,CAAC,IAAI,CAAC,iDAAiD,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;qBACpF;gBACH,CAAC;aACF,CAAC,CAAC;YACH,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC/B,OAAO,CAAC,EAAE,CAAC,CAAC;YACd,CAAC,CAAC,CAAC;YACH,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;gBACjC,MAAM,CAAC,CAAC,CAAC,CAAC;YACZ,CAAC,CAAC,CAAC;YACH,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAsB,EAAE,EAAE;gBACtD,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;YACpD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;IAES,aAAa,GAAG,CAAC,KAA4B,EAAQ,EAAE;QAC/D,IAAI,OAAO,CAAC;QACZ,IAAI;YACF,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAClC;QAAC,OAAO,CAAC,EAAE;YACV,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC,CAAC,CAAC;YACvC,OAAO;SACR;QAED,IAAI,OAAO,CAAC,OAAO,KAAK,wBAAwB,IAAI,OAAO,CAAC,MAAM,KAAK,oBAAoB,EAAE;YAC3F,OAAO;SACR;QACD,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,UAAU,KAAK,IAAI,CAAC,cAAc,CAAC,UAAU,EAAE;YAC/E,OAAO;SACR;QAED,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvE,CAAC,CAAC;IAEF;;;OAGG;IACI,wBAAwB;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC","sourcesContent":["import { EventEmitter, EventSubscription } from 'fbemitter';\n\nimport { WebSocketBackingStore } from './WebSocketBackingStore';\nimport { WebSocketWithReconnect } from './WebSocketWithReconnect';\nimport type { ConnectionInfo } from './devtools.types';\nimport * as logger from './logger';\n\n// This version should be synced with the one in the **createMessageSocketEndpoint.ts** in @react-native-community/cli-server-api\nexport const MESSAGE_PROTOCOL_VERSION = 2;\n\nexport const DevToolsPluginMethod = 'Expo:DevToolsPlugin';\n\n/**\n * This client is for the Expo DevTools Plugins to communicate between the app and the DevTools webpage hosted in a browser.\n * All the code should be both compatible with browsers and React Native.\n */\nexport abstract class DevToolsPluginClient {\n protected eventEmitter: EventEmitter = new EventEmitter();\n\n private static defaultWSStore: WebSocketBackingStore = new WebSocketBackingStore();\n private readonly wsStore: WebSocketBackingStore = DevToolsPluginClient.defaultWSStore;\n\n protected isClosed = false;\n protected retries = 0;\n\n public constructor(public readonly connectionInfo: ConnectionInfo) {\n this.wsStore = connectionInfo.wsStore || DevToolsPluginClient.defaultWSStore;\n }\n\n /**\n * Initialize the connection.\n * @hidden\n */\n public async initAsync(): Promise<void> {\n if (this.wsStore.ws == null) {\n this.wsStore.ws = await this.connectAsync();\n }\n this.wsStore.refCount += 1;\n this.wsStore.ws.addEventListener('message', this.handleMessage);\n }\n\n /**\n * Close the connection.\n */\n public async closeAsync(): Promise<void> {\n this.isClosed = true;\n this.wsStore.ws?.removeEventListener('message', this.handleMessage);\n this.wsStore.refCount -= 1;\n if (this.wsStore.refCount < 1) {\n this.wsStore.ws?.close();\n this.wsStore.ws = null;\n }\n this.eventEmitter.removeAllListeners();\n }\n\n /**\n * Send a message to the other end of DevTools.\n * @param method A method name.\n * @param params any extra payload.\n */\n public sendMessage(method: string, params: any) {\n if (this.wsStore.ws?.readyState === WebSocket.CLOSED) {\n logger.warn('Unable to send message in a disconnected state.');\n return;\n }\n\n const payload: Record<string, any> = {\n version: MESSAGE_PROTOCOL_VERSION,\n pluginName: this.connectionInfo.pluginName,\n method: DevToolsPluginMethod,\n params: {\n method,\n params,\n },\n };\n this.wsStore.ws?.send(JSON.stringify(payload));\n }\n\n /**\n * Subscribe to a message from the other end of DevTools.\n * @param method Subscribe to a message with a method name.\n * @param listener Listener to be called when a message is received.\n */\n public addMessageListener(method: string, listener: (params: any) => void): EventSubscription {\n return this.eventEmitter.addListener(method, listener);\n }\n\n /**\n * Subscribe to a message from the other end of DevTools just once.\n * @param method Subscribe to a message with a method name.\n * @param listener Listener to be called when a message is received.\n */\n public addMessageListenerOnce(method: string, listener: (params: any) => void): void {\n this.eventEmitter.once(method, listener);\n }\n\n /**\n * Returns whether the client is connected to the server.\n */\n public isConnected(): boolean {\n return this.wsStore.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * The method to create the WebSocket connection.\n */\n protected connectAsync(): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocketWithReconnect(`ws://${this.connectionInfo.devServer}/message`, {\n onError: (e: unknown) => {\n if (e instanceof Error) {\n console.warn(`Error happened from the WebSocket connection: ${e.message}\\n${e.stack}`);\n } else {\n console.warn(`Error happened from the WebSocket connection: ${JSON.stringify(e)}`);\n }\n },\n });\n ws.addEventListener('open', () => {\n resolve(ws);\n });\n ws.addEventListener('error', (e) => {\n reject(e);\n });\n ws.addEventListener('close', (e: WebSocketCloseEvent) => {\n logger.info('WebSocket closed', e.code, e.reason);\n });\n });\n }\n\n protected handleMessage = (event: WebSocketMessageEvent): void => {\n let payload;\n try {\n payload = JSON.parse(event.data);\n } catch (e) {\n logger.info('Failed to parse JSON', e);\n return;\n }\n\n if (payload.version !== MESSAGE_PROTOCOL_VERSION || payload.method !== DevToolsPluginMethod) {\n return;\n }\n if (payload.pluginName && payload.pluginName !== this.connectionInfo.pluginName) {\n return;\n }\n\n this.eventEmitter.emit(payload.params.method, payload.params.params);\n };\n\n /**\n * Get the WebSocket backing store. Exposed for testing.\n * @hidden\n */\n public getWebSocketBackingStore(): WebSocketBackingStore {\n return this.wsStore;\n }\n}\n"]}
@@ -4,38 +4,11 @@ import { DevToolsPluginClient } from './DevToolsPluginClient';
4
4
  */
5
5
  export declare class DevToolsPluginClientImplApp extends DevToolsPluginClient {
6
6
  private browserClientMap;
7
- private static ws;
8
- private static refCount;
9
7
  /**
10
8
  * Initialize the connection.
11
9
  * @hidden
12
10
  */
13
11
  initAsync(): Promise<void>;
14
- /**
15
- * Close the connection.
16
- */
17
- closeAsync(): Promise<void>;
18
- /**
19
- * Send a message to the other end of DevTools.
20
- * @param method A method name.
21
- * @param params any extra payload.
22
- */
23
- sendMessage(method: string, params: any): void;
24
- /**
25
- * Returns whether the client is connected to the server.
26
- */
27
- isConnected(): boolean;
28
- /**
29
- * Get the WebSocket instance. Exposed for testing.
30
- * @hidden
31
- */
32
- static getWebSocket(): WebSocket | null;
33
- /**
34
- * Get the current reference count. Exposed for testing.
35
- * @hidden
36
- */
37
- static getRefCount(): number;
38
- private connectAsync;
39
12
  private addHandshakeHandler;
40
13
  }
41
14
  //# sourceMappingURL=DevToolsPluginClientImplApp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClientImplApp.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplApp.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EAGrB,MAAM,wBAAwB,CAAC;AAIhC;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,oBAAoB;IAEnE,OAAO,CAAC,gBAAgB,CAA8B;IAEtD,OAAO,CAAC,MAAM,CAAC,EAAE,CAA0B;IAC3C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAa;IAEpC;;;OAGG;IACY,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IASzC;;OAEG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAU1C;;;;OAIG;IACM,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI;IAiBvD;;OAEG;IACM,WAAW,IAAI,OAAO;IAI/B;;;OAGG;WACW,YAAY,IAAI,SAAS,GAAG,IAAI;IAI9C;;;OAGG;WACW,WAAW,IAAI,MAAM;YAIrB,YAAY;IAgB1B,OAAO,CAAC,mBAAmB;CAY5B"}
1
+ {"version":3,"file":"DevToolsPluginClientImplApp.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAI9D;;GAEG;AACH,qBAAa,2BAA4B,SAAQ,oBAAoB;IAEnE,OAAO,CAAC,gBAAgB,CAA8B;IAEtD;;;OAGG;IACY,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAKzC,OAAO,CAAC,mBAAmB;CAY5B"}
@@ -1,4 +1,4 @@
1
- import { DevToolsPluginClient, DevToolsPluginMethod, MESSAGE_PROTOCOL_VERSION, } from './DevToolsPluginClient';
1
+ import { DevToolsPluginClient } from './DevToolsPluginClient';
2
2
  import * as logger from './logger';
3
3
  /**
4
4
  * The DevToolsPluginClient for the app -> browser communication.
@@ -6,87 +6,14 @@ import * as logger from './logger';
6
6
  export class DevToolsPluginClientImplApp extends DevToolsPluginClient {
7
7
  // Map of pluginName -> browserClientId
8
8
  browserClientMap = {};
9
- static ws = null;
10
- static refCount = 0;
11
9
  /**
12
10
  * Initialize the connection.
13
11
  * @hidden
14
12
  */
15
13
  async initAsync() {
16
- if (DevToolsPluginClientImplApp.ws == null) {
17
- DevToolsPluginClientImplApp.ws = await this.connectAsync();
18
- }
19
- DevToolsPluginClientImplApp.refCount += 1;
20
- DevToolsPluginClientImplApp.ws.addEventListener('message', this.handleMessage);
14
+ await super.initAsync();
21
15
  this.addHandshakeHandler();
22
16
  }
23
- /**
24
- * Close the connection.
25
- */
26
- async closeAsync() {
27
- this.eventEmitter.removeAllListeners();
28
- DevToolsPluginClientImplApp.ws?.removeEventListener('message', this.handleMessage);
29
- DevToolsPluginClientImplApp.refCount -= 1;
30
- if (DevToolsPluginClientImplApp.refCount < 1) {
31
- DevToolsPluginClientImplApp.ws?.close();
32
- DevToolsPluginClientImplApp.ws = null;
33
- }
34
- }
35
- /**
36
- * Send a message to the other end of DevTools.
37
- * @param method A method name.
38
- * @param params any extra payload.
39
- */
40
- sendMessage(method, params) {
41
- if (!this.isConnected()) {
42
- throw new Error('Unable to send message in a disconnected state.');
43
- }
44
- const payload = {
45
- version: MESSAGE_PROTOCOL_VERSION,
46
- pluginName: this.connectionInfo.pluginName,
47
- method: DevToolsPluginMethod,
48
- params: {
49
- method,
50
- params,
51
- },
52
- };
53
- DevToolsPluginClientImplApp.ws?.send(JSON.stringify(payload));
54
- }
55
- /**
56
- * Returns whether the client is connected to the server.
57
- */
58
- isConnected() {
59
- return DevToolsPluginClientImplApp.ws?.readyState === WebSocket.OPEN;
60
- }
61
- /**
62
- * Get the WebSocket instance. Exposed for testing.
63
- * @hidden
64
- */
65
- static getWebSocket() {
66
- return DevToolsPluginClientImplApp.ws;
67
- }
68
- /**
69
- * Get the current reference count. Exposed for testing.
70
- * @hidden
71
- */
72
- static getRefCount() {
73
- return DevToolsPluginClientImplApp.refCount;
74
- }
75
- async connectAsync() {
76
- return new Promise((resolve, reject) => {
77
- const ws = new WebSocket(`ws://${this.connectionInfo.devServer}/message`);
78
- ws.addEventListener('open', () => {
79
- resolve(ws);
80
- });
81
- ws.addEventListener('error', (e) => {
82
- reject(e);
83
- });
84
- ws.addEventListener('close', (e) => {
85
- logger.info('WebSocket closed', e.code, e.reason);
86
- DevToolsPluginClientImplApp.ws = null;
87
- });
88
- });
89
- }
90
17
  addHandshakeHandler() {
91
18
  this.addMessageListener('handshake', (params) => {
92
19
  const previousBrowserClientId = this.browserClientMap[params.pluginName];
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClientImplApp.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplApp.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DevToolsPluginClient,\n DevToolsPluginMethod,\n MESSAGE_PROTOCOL_VERSION,\n} from './DevToolsPluginClient';\nimport type { HandshakeMessageParams } from './devtools.types';\nimport * as logger from './logger';\n\n/**\n * The DevToolsPluginClient for the app -> browser communication.\n */\nexport class DevToolsPluginClientImplApp extends DevToolsPluginClient {\n // Map of pluginName -> browserClientId\n private browserClientMap: Record<string, string> = {};\n\n private static ws: WebSocket | null = null;\n private static refCount: number = 0;\n\n /**\n * Initialize the connection.\n * @hidden\n */\n override async initAsync(): Promise<void> {\n if (DevToolsPluginClientImplApp.ws == null) {\n DevToolsPluginClientImplApp.ws = await this.connectAsync();\n }\n DevToolsPluginClientImplApp.refCount += 1;\n DevToolsPluginClientImplApp.ws.addEventListener('message', this.handleMessage);\n this.addHandshakeHandler();\n }\n\n /**\n * Close the connection.\n */\n override async closeAsync(): Promise<void> {\n this.eventEmitter.removeAllListeners();\n DevToolsPluginClientImplApp.ws?.removeEventListener('message', this.handleMessage);\n DevToolsPluginClientImplApp.refCount -= 1;\n if (DevToolsPluginClientImplApp.refCount < 1) {\n DevToolsPluginClientImplApp.ws?.close();\n DevToolsPluginClientImplApp.ws = null;\n }\n }\n\n /**\n * Send a message to the other end of DevTools.\n * @param method A method name.\n * @param params any extra payload.\n */\n override sendMessage(method: string, params: any): void {\n if (!this.isConnected()) {\n throw new Error('Unable to send message in a disconnected state.');\n }\n\n const payload: Record<string, any> = {\n version: MESSAGE_PROTOCOL_VERSION,\n pluginName: this.connectionInfo.pluginName,\n method: DevToolsPluginMethod,\n params: {\n method,\n params,\n },\n };\n DevToolsPluginClientImplApp.ws?.send(JSON.stringify(payload));\n }\n\n /**\n * Returns whether the client is connected to the server.\n */\n override isConnected(): boolean {\n return DevToolsPluginClientImplApp.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Get the WebSocket instance. Exposed for testing.\n * @hidden\n */\n public static getWebSocket(): WebSocket | null {\n return DevToolsPluginClientImplApp.ws;\n }\n\n /**\n * Get the current reference count. Exposed for testing.\n * @hidden\n */\n public static getRefCount(): number {\n return DevToolsPluginClientImplApp.refCount;\n }\n\n private async connectAsync(): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(`ws://${this.connectionInfo.devServer}/message`);\n ws.addEventListener('open', () => {\n resolve(ws);\n });\n ws.addEventListener('error', (e) => {\n reject(e);\n });\n ws.addEventListener('close', (e: WebSocketCloseEvent) => {\n logger.info('WebSocket closed', e.code, e.reason);\n DevToolsPluginClientImplApp.ws = null;\n });\n });\n }\n\n private addHandshakeHandler() {\n this.addMessageListener('handshake', (params: HandshakeMessageParams) => {\n const previousBrowserClientId = this.browserClientMap[params.pluginName];\n if (previousBrowserClientId != null && previousBrowserClientId !== params.browserClientId) {\n logger.info(\n `Terminate the previous browser client connection - previousBrowserClientId[${previousBrowserClientId}]`\n );\n this.sendMessage('terminateBrowserClient', { browserClientId: previousBrowserClientId });\n }\n this.browserClientMap[params.pluginName] = params.browserClientId;\n });\n }\n}\n"]}
1
+ {"version":3,"file":"DevToolsPluginClientImplApp.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplApp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC;;GAEG;AACH,MAAM,OAAO,2BAA4B,SAAQ,oBAAoB;IACnE,uCAAuC;IAC/B,gBAAgB,GAA2B,EAAE,CAAC;IAEtD;;;OAGG;IACM,KAAK,CAAC,SAAS;QACtB,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,mBAAmB,EAAE,CAAC;IAC7B,CAAC;IAEO,mBAAmB;QACzB,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,CAAC,MAA8B,EAAE,EAAE;YACtE,MAAM,uBAAuB,GAAG,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,uBAAuB,IAAI,IAAI,IAAI,uBAAuB,KAAK,MAAM,CAAC,eAAe,EAAE;gBACzF,MAAM,CAAC,IAAI,CACT,8EAA8E,uBAAuB,GAAG,CACzG,CAAC;gBACF,IAAI,CAAC,WAAW,CAAC,wBAAwB,EAAE,EAAE,eAAe,EAAE,uBAAuB,EAAE,CAAC,CAAC;aAC1F;YACD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { DevToolsPluginClient } from './DevToolsPluginClient';\nimport type { HandshakeMessageParams } from './devtools.types';\nimport * as logger from './logger';\n\n/**\n * The DevToolsPluginClient for the app -> browser communication.\n */\nexport class DevToolsPluginClientImplApp extends DevToolsPluginClient {\n // Map of pluginName -> browserClientId\n private browserClientMap: Record<string, string> = {};\n\n /**\n * Initialize the connection.\n * @hidden\n */\n override async initAsync(): Promise<void> {\n await super.initAsync();\n this.addHandshakeHandler();\n }\n\n private addHandshakeHandler() {\n this.addMessageListener('handshake', (params: HandshakeMessageParams) => {\n const previousBrowserClientId = this.browserClientMap[params.pluginName];\n if (previousBrowserClientId != null && previousBrowserClientId !== params.browserClientId) {\n logger.info(\n `Terminate the previous browser client connection - previousBrowserClientId[${previousBrowserClientId}]`\n );\n this.sendMessage('terminateBrowserClient', { browserClientId: previousBrowserClientId });\n }\n this.browserClientMap[params.pluginName] = params.browserClientId;\n });\n }\n}\n"]}
@@ -3,28 +3,12 @@ import { DevToolsPluginClient } from './DevToolsPluginClient';
3
3
  * The DevToolsPluginClient for the browser -> app communication.
4
4
  */
5
5
  export declare class DevToolsPluginClientImplBrowser extends DevToolsPluginClient {
6
- private ws;
7
6
  private browserClientId;
8
7
  /**
9
8
  * Initialize the connection.
10
9
  * @hidden
11
10
  */
12
11
  initAsync(): Promise<void>;
13
- /**
14
- * Close the connection.
15
- */
16
- closeAsync(): Promise<void>;
17
- /**
18
- * Send a message to the other end of DevTools.
19
- * @param method A method name.
20
- * @param params any extra payload.
21
- */
22
- sendMessage(method: string, params: any, pluginNamespace?: string): void;
23
- /**
24
- * Returns whether the client is connected to the server.
25
- */
26
- isConnected(): boolean;
27
12
  private startHandshake;
28
- private connectAsync;
29
13
  }
30
14
  //# sourceMappingURL=DevToolsPluginClientImplBrowser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClientImplBrowser.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EAGrB,MAAM,wBAAwB,CAAC;AAGhC;;GAEG;AACH,qBAAa,+BAAgC,SAAQ,oBAAoB;IACvE,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,eAAe,CAAiC;IAExD;;;OAGG;IACY,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IASzC;;OAEG;IACY,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO1C;;;;OAIG;IACM,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI;IAiBjF;;OAEG;IACM,WAAW,IAAI,OAAO;IAI/B,OAAO,CAAC,cAAc;YAcR,YAAY;CAe3B"}
1
+ {"version":3,"file":"DevToolsPluginClientImplBrowser.d.ts","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAG9D;;GAEG;AACH,qBAAa,+BAAgC,SAAQ,oBAAoB;IACvE,OAAO,CAAC,eAAe,CAAiC;IAExD;;;OAGG;IACY,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAKzC,OAAO,CAAC,cAAc;CAavB"}
@@ -1,58 +1,18 @@
1
- import { DevToolsPluginClient, DevToolsPluginMethod, MESSAGE_PROTOCOL_VERSION, } from './DevToolsPluginClient';
1
+ import { DevToolsPluginClient } from './DevToolsPluginClient';
2
2
  import * as logger from './logger';
3
3
  /**
4
4
  * The DevToolsPluginClient for the browser -> app communication.
5
5
  */
6
6
  export class DevToolsPluginClientImplBrowser extends DevToolsPluginClient {
7
- ws = null;
8
7
  browserClientId = Date.now().toString();
9
8
  /**
10
9
  * Initialize the connection.
11
10
  * @hidden
12
11
  */
13
12
  async initAsync() {
14
- if (this.ws == null) {
15
- const ws = await this.connectAsync();
16
- this.ws = ws;
17
- }
18
- this.ws.addEventListener('message', this.handleMessage);
13
+ await super.initAsync();
19
14
  this.startHandshake();
20
15
  }
21
- /**
22
- * Close the connection.
23
- */
24
- async closeAsync() {
25
- this.ws?.removeEventListener('message', this.handleMessage);
26
- this.ws?.close();
27
- this.ws = null;
28
- this.eventEmitter.removeAllListeners();
29
- }
30
- /**
31
- * Send a message to the other end of DevTools.
32
- * @param method A method name.
33
- * @param params any extra payload.
34
- */
35
- sendMessage(method, params, pluginNamespace) {
36
- if (!this.isConnected()) {
37
- throw new Error('Unable to send message in a disconnected state.');
38
- }
39
- const payload = {
40
- version: MESSAGE_PROTOCOL_VERSION,
41
- pluginName: this.connectionInfo.pluginName,
42
- method: DevToolsPluginMethod,
43
- params: {
44
- method,
45
- params,
46
- },
47
- };
48
- this.ws?.send(JSON.stringify(payload));
49
- }
50
- /**
51
- * Returns whether the client is connected to the server.
52
- */
53
- isConnected() {
54
- return this.ws?.readyState === WebSocket.OPEN;
55
- }
56
16
  startHandshake() {
57
17
  this.addMessageListener('terminateBrowserClient', (params) => {
58
18
  if (this.browserClientId !== params.browserClientId) {
@@ -66,20 +26,5 @@ export class DevToolsPluginClientImplBrowser extends DevToolsPluginClient {
66
26
  pluginName: this.connectionInfo.pluginName,
67
27
  });
68
28
  }
69
- async connectAsync() {
70
- return new Promise((resolve, reject) => {
71
- const ws = new WebSocket(`ws://${this.connectionInfo.devServer}/message`);
72
- ws.addEventListener('open', () => {
73
- resolve(ws);
74
- });
75
- ws.addEventListener('error', (e) => {
76
- reject(e);
77
- });
78
- ws.addEventListener('close', (e) => {
79
- logger.info('WebSocket closed', e.code, e.reason);
80
- this.ws = null;
81
- });
82
- });
83
- }
84
29
  }
85
30
  //# sourceMappingURL=DevToolsPluginClientImplBrowser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClientImplBrowser.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplBrowser.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n DevToolsPluginClient,\n DevToolsPluginMethod,\n MESSAGE_PROTOCOL_VERSION,\n} from './DevToolsPluginClient';\nimport * as logger from './logger';\n\n/**\n * The DevToolsPluginClient for the browser -> app communication.\n */\nexport class DevToolsPluginClientImplBrowser extends DevToolsPluginClient {\n private ws: WebSocket | null = null;\n private browserClientId: string = Date.now().toString();\n\n /**\n * Initialize the connection.\n * @hidden\n */\n override async initAsync(): Promise<void> {\n if (this.ws == null) {\n const ws = await this.connectAsync();\n this.ws = ws;\n }\n this.ws.addEventListener('message', this.handleMessage);\n this.startHandshake();\n }\n\n /**\n * Close the connection.\n */\n override async closeAsync(): Promise<void> {\n this.ws?.removeEventListener('message', this.handleMessage);\n this.ws?.close();\n this.ws = null;\n this.eventEmitter.removeAllListeners();\n }\n\n /**\n * Send a message to the other end of DevTools.\n * @param method A method name.\n * @param params any extra payload.\n */\n override sendMessage(method: string, params: any, pluginNamespace?: string): void {\n if (!this.isConnected()) {\n throw new Error('Unable to send message in a disconnected state.');\n }\n\n const payload: Record<string, any> = {\n version: MESSAGE_PROTOCOL_VERSION,\n pluginName: this.connectionInfo.pluginName,\n method: DevToolsPluginMethod,\n params: {\n method,\n params,\n },\n };\n this.ws?.send(JSON.stringify(payload));\n }\n\n /**\n * Returns whether the client is connected to the server.\n */\n override isConnected(): boolean {\n return this.ws?.readyState === WebSocket.OPEN;\n }\n\n private startHandshake() {\n this.addMessageListener('terminateBrowserClient', (params) => {\n if (this.browserClientId !== params.browserClientId) {\n return;\n }\n logger.info('Received terminateBrowserClient messages and terminate the current connection');\n this.closeAsync();\n });\n this.sendMessage('handshake', {\n browserClientId: this.browserClientId,\n pluginName: this.connectionInfo.pluginName,\n });\n }\n\n private async connectAsync(): Promise<WebSocket> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(`ws://${this.connectionInfo.devServer}/message`);\n ws.addEventListener('open', () => {\n resolve(ws);\n });\n ws.addEventListener('error', (e) => {\n reject(e);\n });\n ws.addEventListener('close', (e: WebSocketCloseEvent) => {\n logger.info('WebSocket closed', e.code, e.reason);\n this.ws = null;\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"DevToolsPluginClientImplBrowser.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClientImplBrowser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,MAAM,MAAM,UAAU,CAAC;AAEnC;;GAEG;AACH,MAAM,OAAO,+BAAgC,SAAQ,oBAAoB;IAC/D,eAAe,GAAW,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAExD;;;OAGG;IACM,KAAK,CAAC,SAAS;QACtB,MAAM,KAAK,CAAC,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc;QACpB,IAAI,CAAC,kBAAkB,CAAC,wBAAwB,EAAE,CAAC,MAAM,EAAE,EAAE;YAC3D,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,CAAC,eAAe,EAAE;gBACnD,OAAO;aACR;YACD,MAAM,CAAC,IAAI,CAAC,+EAA+E,CAAC,CAAC;YAC7F,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE;YAC5B,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,UAAU,EAAE,IAAI,CAAC,cAAc,CAAC,UAAU;SAC3C,CAAC,CAAC;IACL,CAAC;CACF","sourcesContent":["import { DevToolsPluginClient } from './DevToolsPluginClient';\nimport * as logger from './logger';\n\n/**\n * The DevToolsPluginClient for the browser -> app communication.\n */\nexport class DevToolsPluginClientImplBrowser extends DevToolsPluginClient {\n private browserClientId: string = Date.now().toString();\n\n /**\n * Initialize the connection.\n * @hidden\n */\n override async initAsync(): Promise<void> {\n await super.initAsync();\n this.startHandshake();\n }\n\n private startHandshake() {\n this.addMessageListener('terminateBrowserClient', (params) => {\n if (this.browserClientId !== params.browserClientId) {\n return;\n }\n logger.info('Received terminateBrowserClient messages and terminate the current connection');\n this.closeAsync();\n });\n this.sendMessage('handshake', {\n browserClientId: this.browserClientId,\n pluginName: this.connectionInfo.pluginName,\n });\n }\n}\n"]}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The backing store for the WebSocket connection and reference count.
3
+ * This is used for connection multiplexing.
4
+ */
5
+ export declare class WebSocketBackingStore {
6
+ ws: WebSocket | null;
7
+ refCount: number;
8
+ constructor(ws?: WebSocket | null, refCount?: number);
9
+ }
10
+ //# sourceMappingURL=WebSocketBackingStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketBackingStore.d.ts","sourceRoot":"","sources":["../../src/devtools/WebSocketBackingStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,qBAAqB;IAEvB,EAAE,EAAE,SAAS,GAAG,IAAI;IACpB,QAAQ,EAAE,MAAM;gBADhB,EAAE,GAAE,SAAS,GAAG,IAAW,EAC3B,QAAQ,GAAE,MAAU;CAE9B"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * The backing store for the WebSocket connection and reference count.
3
+ * This is used for connection multiplexing.
4
+ */
5
+ export class WebSocketBackingStore {
6
+ ws;
7
+ refCount;
8
+ constructor(ws = null, refCount = 0) {
9
+ this.ws = ws;
10
+ this.refCount = refCount;
11
+ }
12
+ }
13
+ //# sourceMappingURL=WebSocketBackingStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketBackingStore.js","sourceRoot":"","sources":["../../src/devtools/WebSocketBackingStore.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAEvB;IACA;IAFT,YACS,KAAuB,IAAI,EAC3B,WAAmB,CAAC;QADpB,OAAE,GAAF,EAAE,CAAyB;QAC3B,aAAQ,GAAR,QAAQ,CAAY;IAC1B,CAAC;CACL","sourcesContent":["/**\n * The backing store for the WebSocket connection and reference count.\n * This is used for connection multiplexing.\n */\nexport class WebSocketBackingStore {\n constructor(\n public ws: WebSocket | null = null,\n public refCount: number = 0\n ) {}\n}\n"]}
@@ -0,0 +1,75 @@
1
+ export interface Options {
2
+ /**
3
+ * Reconnect interval in milliseconds.
4
+ * @default 1500
5
+ */
6
+ retriesInterval?: number;
7
+ /**
8
+ * The maximum number of retries.
9
+ * @default 200
10
+ */
11
+ maxRetries?: number;
12
+ /**
13
+ * The timeout in milliseconds for the WebSocket connecting.
14
+ */
15
+ connectTimeout?: number;
16
+ /**
17
+ * The error handler.
18
+ * @default throwing an error
19
+ */
20
+ onError?: (error: Error) => void;
21
+ /**
22
+ * The callback to be called when the WebSocket is reconnected.
23
+ * @default no-op
24
+ */
25
+ onReconnect?: (reason: string) => void;
26
+ }
27
+ export declare class WebSocketWithReconnect implements WebSocket {
28
+ readonly url: string;
29
+ private readonly retriesInterval;
30
+ private readonly maxRetries;
31
+ private readonly connectTimeout;
32
+ private readonly onError;
33
+ private readonly onReconnect;
34
+ private ws;
35
+ private retries;
36
+ private connectTimeoutHandle;
37
+ private isClosed;
38
+ private sendQueue;
39
+ private lastCloseEvent;
40
+ private readonly emitter;
41
+ private readonly eventSubscriptions;
42
+ constructor(url: string, options?: Options);
43
+ close(code?: number, reason?: string): void;
44
+ addEventListener(event: 'message', listener: (event: WebSocketMessageEvent) => void): void;
45
+ addEventListener(event: 'open', listener: () => void): void;
46
+ addEventListener(event: 'error', listener: (event: WebSocketErrorEvent) => void): void;
47
+ addEventListener(event: 'close', listener: (event: WebSocketCloseEvent) => void): void;
48
+ removeEventListener(event: string, listener: (event: any) => void): void;
49
+ private connect;
50
+ send(data: string | ArrayBufferView | Blob | ArrayBufferLike): void;
51
+ private handleOpen;
52
+ private handleMessage;
53
+ private handleError;
54
+ private handleClose;
55
+ private handleConnectTimeout;
56
+ private clearConnectTimeoutIfNeeded;
57
+ private reconnectIfNeeded;
58
+ private wsClose;
59
+ get readyState(): number;
60
+ readonly CONNECTING = 0;
61
+ readonly OPEN = 1;
62
+ readonly CLOSING = 2;
63
+ readonly CLOSED = 3;
64
+ get binaryType(): BinaryType;
65
+ get bufferedAmount(): number;
66
+ get extensions(): string;
67
+ get protocol(): string;
68
+ ping(): void;
69
+ dispatchEvent(event: Event): boolean;
70
+ set onclose(value: ((e: WebSocketCloseEvent) => any) | null);
71
+ set onerror(value: ((e: Event) => any) | null);
72
+ set onmessage(value: ((e: WebSocketMessageEvent) => any) | null);
73
+ set onopen(value: (() => any) | null);
74
+ }
75
+ //# sourceMappingURL=WebSocketWithReconnect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketWithReconnect.d.ts","sourceRoot":"","sources":["../../src/devtools/WebSocketWithReconnect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,204 @@
1
+ import { EventEmitter } from 'fbemitter';
2
+ export class WebSocketWithReconnect {
3
+ url;
4
+ retriesInterval;
5
+ maxRetries;
6
+ connectTimeout;
7
+ onError;
8
+ onReconnect;
9
+ ws = null;
10
+ retries = 0;
11
+ connectTimeoutHandle = null;
12
+ isClosed = false;
13
+ sendQueue = [];
14
+ lastCloseEvent = null;
15
+ emitter = new EventEmitter();
16
+ eventSubscriptions = [];
17
+ constructor(url, options) {
18
+ this.url = url;
19
+ this.retriesInterval = options?.retriesInterval ?? 1500;
20
+ this.maxRetries = options?.maxRetries ?? 200;
21
+ this.connectTimeout = options?.connectTimeout ?? 5000;
22
+ this.onError =
23
+ options?.onError ??
24
+ ((error) => {
25
+ throw error;
26
+ });
27
+ this.onReconnect = options?.onReconnect ?? (() => { });
28
+ this.connect();
29
+ }
30
+ close(code, reason) {
31
+ this.clearConnectTimeoutIfNeeded();
32
+ this.emitter.emit('close', this.lastCloseEvent ?? {
33
+ code: code ?? 1000,
34
+ reason: reason ?? 'Explicit closing',
35
+ message: 'Explicit closing',
36
+ });
37
+ this.lastCloseEvent = null;
38
+ this.isClosed = true;
39
+ this.emitter.removeAllListeners();
40
+ this.sendQueue = [];
41
+ if (this.ws != null) {
42
+ const ws = this.ws;
43
+ this.ws = null;
44
+ this.wsClose(ws);
45
+ }
46
+ }
47
+ addEventListener(event, listener) {
48
+ this.eventSubscriptions.push(this.emitter.addListener(event, listener));
49
+ }
50
+ removeEventListener(event, listener) {
51
+ const index = this.eventSubscriptions.findIndex((subscription) => subscription.listener === listener);
52
+ if (index >= 0) {
53
+ this.eventSubscriptions[index].remove();
54
+ this.eventSubscriptions.splice(index, 1);
55
+ }
56
+ }
57
+ //#region Internals
58
+ connect() {
59
+ if (this.ws != null) {
60
+ return;
61
+ }
62
+ this.connectTimeoutHandle = setTimeout(this.handleConnectTimeout, this.connectTimeout);
63
+ this.ws = new WebSocket(this.url.toString());
64
+ this.ws.addEventListener('message', this.handleMessage);
65
+ this.ws.addEventListener('open', this.handleOpen);
66
+ // @ts-ignore TypeScript expects (e: Event) => any, but we want (e: WebSocketErrorEvent) => any
67
+ this.ws.addEventListener('error', this.handleError);
68
+ this.ws.addEventListener('close', this.handleClose);
69
+ }
70
+ send(data) {
71
+ if (this.isClosed) {
72
+ this.onError(new Error('Unable to send data: WebSocket is closed'));
73
+ return;
74
+ }
75
+ if (this.retries >= this.maxRetries) {
76
+ this.onError(new Error(`Unable to send data: Exceeded max retries - retries[${this.retries}]`));
77
+ return;
78
+ }
79
+ const ws = this.ws;
80
+ if (ws != null && ws.readyState === WebSocket.OPEN) {
81
+ ws.send(data);
82
+ }
83
+ else {
84
+ this.sendQueue.push(data);
85
+ }
86
+ }
87
+ handleOpen = () => {
88
+ this.clearConnectTimeoutIfNeeded();
89
+ this.lastCloseEvent = null;
90
+ this.emitter.emit('open');
91
+ const sendQueue = this.sendQueue;
92
+ this.sendQueue = [];
93
+ for (const data of sendQueue) {
94
+ this.send(data);
95
+ }
96
+ };
97
+ handleMessage = (event) => {
98
+ this.emitter.emit('message', event);
99
+ };
100
+ handleError = (event) => {
101
+ this.clearConnectTimeoutIfNeeded();
102
+ this.emitter.emit('error', event);
103
+ this.reconnectIfNeeded(`WebSocket error - ${event.message}`);
104
+ };
105
+ handleClose = (event) => {
106
+ this.clearConnectTimeoutIfNeeded();
107
+ this.lastCloseEvent = {
108
+ code: event.code,
109
+ reason: event.reason,
110
+ message: event.message,
111
+ };
112
+ this.reconnectIfNeeded(`WebSocket closed - code[${event.code}] reason[${event.reason}]`);
113
+ };
114
+ handleConnectTimeout = () => {
115
+ this.reconnectIfNeeded('Timeout from connecting to the WebSocket');
116
+ };
117
+ clearConnectTimeoutIfNeeded() {
118
+ if (this.connectTimeoutHandle != null) {
119
+ clearTimeout(this.connectTimeoutHandle);
120
+ this.connectTimeoutHandle = null;
121
+ }
122
+ }
123
+ reconnectIfNeeded(reason) {
124
+ if (this.ws != null) {
125
+ this.wsClose(this.ws);
126
+ this.ws = null;
127
+ }
128
+ if (this.isClosed) {
129
+ return;
130
+ }
131
+ if (this.retries >= this.maxRetries) {
132
+ this.onError(new Error('Exceeded max retries'));
133
+ this.close();
134
+ return;
135
+ }
136
+ setTimeout(() => {
137
+ this.retries += 1;
138
+ this.connect();
139
+ this.onReconnect(reason);
140
+ }, this.retriesInterval);
141
+ }
142
+ wsClose(ws) {
143
+ try {
144
+ ws.removeEventListener('message', this.handleMessage);
145
+ ws.removeEventListener('open', this.handleOpen);
146
+ // @ts-ignore: TypeScript expects (e: Event) => any, but we want (e: WebSocketErrorEvent) => any
147
+ ws.removeEventListener('error', this.handleError);
148
+ ws.removeEventListener('close', this.handleClose);
149
+ ws.close();
150
+ }
151
+ catch { }
152
+ }
153
+ get readyState() {
154
+ // Only return closed if the WebSocket is explicitly closed or exceeds max retries.
155
+ if (this.isClosed) {
156
+ return WebSocket.CLOSED;
157
+ }
158
+ const readyState = this.ws?.readyState;
159
+ if (readyState === WebSocket.CLOSED) {
160
+ return WebSocket.CONNECTING;
161
+ }
162
+ return readyState ?? WebSocket.CONNECTING;
163
+ }
164
+ //#endregion
165
+ //#region WebSocket API proxy
166
+ CONNECTING = 0;
167
+ OPEN = 1;
168
+ CLOSING = 2;
169
+ CLOSED = 3;
170
+ get binaryType() {
171
+ return this.ws?.binaryType ?? 'blob';
172
+ }
173
+ get bufferedAmount() {
174
+ return this.ws?.bufferedAmount ?? 0;
175
+ }
176
+ get extensions() {
177
+ return this.ws?.extensions ?? '';
178
+ }
179
+ get protocol() {
180
+ return this.ws?.protocol ?? '';
181
+ }
182
+ ping() {
183
+ // @ts-expect-error
184
+ return this.ws?.ping();
185
+ }
186
+ dispatchEvent(event) {
187
+ return this.ws?.dispatchEvent(event) ?? false;
188
+ }
189
+ //#endregion
190
+ //#regions Unsupported legacy properties
191
+ set onclose(value) {
192
+ throw new Error('Unsupported legacy property, use addEventListener instead');
193
+ }
194
+ set onerror(value) {
195
+ throw new Error('Unsupported legacy property, use addEventListener instead');
196
+ }
197
+ set onmessage(value) {
198
+ throw new Error('Unsupported legacy property, use addEventListener instead');
199
+ }
200
+ set onopen(value) {
201
+ throw new Error('Unsupported legacy property, use addEventListener instead');
202
+ }
203
+ }
204
+ //# sourceMappingURL=WebSocketWithReconnect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebSocketWithReconnect.js","sourceRoot":"","sources":["../../src/devtools/WebSocketWithReconnect.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter, type EventSubscription } from 'fbemitter';\n\nexport interface Options {\n /**\n * Reconnect interval in milliseconds.\n * @default 1500\n */\n retriesInterval?: number;\n\n /**\n * The maximum number of retries.\n * @default 200\n */\n maxRetries?: number;\n\n /**\n * The timeout in milliseconds for the WebSocket connecting.\n */\n connectTimeout?: number;\n\n /**\n * The error handler.\n * @default throwing an error\n */\n onError?: (error: Error) => void;\n\n /**\n * The callback to be called when the WebSocket is reconnected.\n * @default no-op\n */\n onReconnect?: (reason: string) => void;\n}\n\nexport class WebSocketWithReconnect implements WebSocket {\n private readonly retriesInterval: number;\n private readonly maxRetries: number;\n private readonly connectTimeout: number;\n private readonly onError: (error: Error) => void;\n private readonly onReconnect: (reason: string) => void;\n\n private ws: WebSocket | null = null;\n private retries = 0;\n private connectTimeoutHandle: ReturnType<typeof setTimeout> | null = null;\n private isClosed = false;\n private sendQueue: (string | ArrayBufferView | Blob | ArrayBufferLike)[] = [];\n private lastCloseEvent: { code?: number; reason?: string; message?: string } | null = null;\n\n private readonly emitter = new EventEmitter();\n private readonly eventSubscriptions: EventSubscription[] = [];\n\n constructor(\n public readonly url: string,\n options?: Options\n ) {\n this.retriesInterval = options?.retriesInterval ?? 1500;\n this.maxRetries = options?.maxRetries ?? 200;\n this.connectTimeout = options?.connectTimeout ?? 5000;\n this.onError =\n options?.onError ??\n ((error) => {\n throw error;\n });\n this.onReconnect = options?.onReconnect ?? (() => {});\n\n this.connect();\n }\n\n public close(code?: number, reason?: string) {\n this.clearConnectTimeoutIfNeeded();\n this.emitter.emit(\n 'close',\n this.lastCloseEvent ?? {\n code: code ?? 1000,\n reason: reason ?? 'Explicit closing',\n message: 'Explicit closing',\n }\n );\n this.lastCloseEvent = null;\n this.isClosed = true;\n this.emitter.removeAllListeners();\n this.sendQueue = [];\n if (this.ws != null) {\n const ws = this.ws;\n this.ws = null;\n this.wsClose(ws);\n }\n }\n\n public addEventListener(event: 'message', listener: (event: WebSocketMessageEvent) => void): void;\n public addEventListener(event: 'open', listener: () => void): void;\n public addEventListener(event: 'error', listener: (event: WebSocketErrorEvent) => void): void;\n public addEventListener(event: 'close', listener: (event: WebSocketCloseEvent) => void): void;\n public addEventListener(event: string, listener: (event: any) => void) {\n this.eventSubscriptions.push(this.emitter.addListener(event, listener));\n }\n\n public removeEventListener(event: string, listener: (event: any) => void) {\n const index = this.eventSubscriptions.findIndex(\n (subscription) => subscription.listener === listener\n );\n if (index >= 0) {\n this.eventSubscriptions[index].remove();\n this.eventSubscriptions.splice(index, 1);\n }\n }\n\n //#region Internals\n\n private connect() {\n if (this.ws != null) {\n return;\n }\n this.connectTimeoutHandle = setTimeout(this.handleConnectTimeout, this.connectTimeout);\n\n this.ws = new WebSocket(this.url.toString());\n this.ws.addEventListener('message', this.handleMessage);\n this.ws.addEventListener('open', this.handleOpen);\n // @ts-ignore TypeScript expects (e: Event) => any, but we want (e: WebSocketErrorEvent) => any\n this.ws.addEventListener('error', this.handleError);\n this.ws.addEventListener('close', this.handleClose);\n }\n\n public send(data: string | ArrayBufferView | Blob | ArrayBufferLike): void {\n if (this.isClosed) {\n this.onError(new Error('Unable to send data: WebSocket is closed'));\n return;\n }\n\n if (this.retries >= this.maxRetries) {\n this.onError(\n new Error(`Unable to send data: Exceeded max retries - retries[${this.retries}]`)\n );\n return;\n }\n\n const ws = this.ws;\n if (ws != null && ws.readyState === WebSocket.OPEN) {\n ws.send(data);\n } else {\n this.sendQueue.push(data);\n }\n }\n\n private handleOpen = () => {\n this.clearConnectTimeoutIfNeeded();\n this.lastCloseEvent = null;\n this.emitter.emit('open');\n\n const sendQueue = this.sendQueue;\n this.sendQueue = [];\n for (const data of sendQueue) {\n this.send(data);\n }\n };\n\n private handleMessage = (event: WebSocketMessageEvent) => {\n this.emitter.emit('message', event);\n };\n\n private handleError = (event: WebSocketErrorEvent) => {\n this.clearConnectTimeoutIfNeeded();\n this.emitter.emit('error', event);\n this.reconnectIfNeeded(`WebSocket error - ${event.message}`);\n };\n\n private handleClose = (event: WebSocketCloseEvent) => {\n this.clearConnectTimeoutIfNeeded();\n this.lastCloseEvent = {\n code: event.code,\n reason: event.reason,\n message: event.message,\n };\n this.reconnectIfNeeded(`WebSocket closed - code[${event.code}] reason[${event.reason}]`);\n };\n\n private handleConnectTimeout = () => {\n this.reconnectIfNeeded('Timeout from connecting to the WebSocket');\n };\n\n private clearConnectTimeoutIfNeeded() {\n if (this.connectTimeoutHandle != null) {\n clearTimeout(this.connectTimeoutHandle);\n this.connectTimeoutHandle = null;\n }\n }\n\n private reconnectIfNeeded(reason: string) {\n if (this.ws != null) {\n this.wsClose(this.ws);\n this.ws = null;\n }\n if (this.isClosed) {\n return;\n }\n\n if (this.retries >= this.maxRetries) {\n this.onError(new Error('Exceeded max retries'));\n this.close();\n return;\n }\n\n setTimeout(() => {\n this.retries += 1;\n this.connect();\n this.onReconnect(reason);\n }, this.retriesInterval);\n }\n\n private wsClose(ws: WebSocket) {\n try {\n ws.removeEventListener('message', this.handleMessage);\n ws.removeEventListener('open', this.handleOpen);\n // @ts-ignore: TypeScript expects (e: Event) => any, but we want (e: WebSocketErrorEvent) => any\n ws.removeEventListener('error', this.handleError);\n ws.removeEventListener('close', this.handleClose);\n ws.close();\n } catch {}\n }\n\n public get readyState() {\n // Only return closed if the WebSocket is explicitly closed or exceeds max retries.\n if (this.isClosed) {\n return WebSocket.CLOSED;\n }\n\n const readyState = this.ws?.readyState;\n if (readyState === WebSocket.CLOSED) {\n return WebSocket.CONNECTING;\n }\n return readyState ?? WebSocket.CONNECTING;\n }\n\n //#endregion\n\n //#region WebSocket API proxy\n\n public readonly CONNECTING = 0;\n public readonly OPEN = 1;\n public readonly CLOSING = 2;\n public readonly CLOSED = 3;\n\n public get binaryType() {\n return this.ws?.binaryType ?? 'blob';\n }\n\n public get bufferedAmount() {\n return this.ws?.bufferedAmount ?? 0;\n }\n\n public get extensions() {\n return this.ws?.extensions ?? '';\n }\n\n public get protocol() {\n return this.ws?.protocol ?? '';\n }\n\n public ping(): void {\n // @ts-expect-error\n return this.ws?.ping();\n }\n\n public dispatchEvent(event: Event) {\n return this.ws?.dispatchEvent(event) ?? false;\n }\n\n //#endregion\n\n //#regions Unsupported legacy properties\n\n public set onclose(value: ((e: WebSocketCloseEvent) => any) | null) {\n throw new Error('Unsupported legacy property, use addEventListener instead');\n }\n\n public set onerror(value: ((e: Event) => any) | null) {\n throw new Error('Unsupported legacy property, use addEventListener instead');\n }\n\n public set onmessage(value: ((e: WebSocketMessageEvent) => any) | null) {\n throw new Error('Unsupported legacy property, use addEventListener instead');\n }\n\n public set onopen(value: (() => any) | null) {\n throw new Error('Unsupported legacy property, use addEventListener instead');\n }\n\n //#endregion\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { WebSocketBackingStore } from './WebSocketBackingStore';
1
2
  /**
2
3
  * The connection info for devtools plugins client.
3
4
  */
@@ -8,6 +9,12 @@ export interface ConnectionInfo {
8
9
  devServer: string;
9
10
  /** The plugin name. */
10
11
  pluginName: string;
12
+ /**
13
+ * The backing store for the WebSocket connection. Exposed for testing.
14
+ * If not provided, the default singleton instance will be used.
15
+ * @hidden
16
+ */
17
+ wsStore?: WebSocketBackingStore;
11
18
  }
12
19
  /**
13
20
  * Parameters for the `handshake` message.
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.types.d.ts","sourceRoot":"","sources":["../../src/devtools/devtools.types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EACF,KAAK,GACL,SAAS,CAAC;IAEd,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAElB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB"}
1
+ {"version":3,"file":"devtools.types.d.ts","sourceRoot":"","sources":["../../src/devtools/devtools.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,MAAM,EACF,KAAK,GACL,SAAS,CAAC;IAEd,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAElB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;IACH,OAAO,CAAC,EAAE,qBAAqB,CAAC;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB"}
@@ -1 +1 @@
1
- {"version":3,"file":"devtools.types.js","sourceRoot":"","sources":["../../src/devtools/devtools.types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * The connection info for devtools plugins client.\n */\nexport interface ConnectionInfo {\n /** Indicates the sender towards the devtools plugin. */\n sender:\n | 'app' // client running in the app environment.\n | 'browser'; // client running in the browser environment.\n\n /** Dev server address. */\n devServer: string;\n\n /** The plugin name. */\n pluginName: string;\n}\n\n/**\n * Parameters for the `handshake` message.\n * @hidden\n */\nexport interface HandshakeMessageParams {\n browserClientId: string;\n pluginName: string;\n}\n"]}
1
+ {"version":3,"file":"devtools.types.js","sourceRoot":"","sources":["../../src/devtools/devtools.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { WebSocketBackingStore } from './WebSocketBackingStore';\n\n/**\n * The connection info for devtools plugins client.\n */\nexport interface ConnectionInfo {\n /** Indicates the sender towards the devtools plugin. */\n sender:\n | 'app' // client running in the app environment.\n | 'browser'; // client running in the browser environment.\n\n /** Dev server address. */\n devServer: string;\n\n /** The plugin name. */\n pluginName: string;\n\n /**\n * The backing store for the WebSocket connection. Exposed for testing.\n * If not provided, the default singleton instance will be used.\n * @hidden\n */\n wsStore?: WebSocketBackingStore;\n}\n\n/**\n * Parameters for the `handshake` message.\n * @hidden\n */\nexport interface HandshakeMessageParams {\n browserClientId: string;\n pluginName: string;\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  export declare function log(...params: Parameters<typeof console.log>): void;
2
2
  export declare function debug(...params: Parameters<typeof console.debug>): void;
3
3
  export declare function info(...params: Parameters<typeof console.info>): void;
4
+ export declare function warn(...params: Parameters<typeof console.info>): void;
4
5
  export declare function setEnableLogging(enabled: boolean): void;
5
6
  //# sourceMappingURL=logger.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/devtools/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,GAAG,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,GAAG,CAAC,QAI5D;AAED,wBAAgB,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,KAAK,CAAC,QAIhE;AAED,wBAAgB,IAAI,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,QAI9D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAEhD"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/devtools/logger.ts"],"names":[],"mappings":"AAEA,wBAAgB,GAAG,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,GAAG,CAAC,QAI5D;AAED,wBAAgB,KAAK,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,KAAK,CAAC,QAIhE;AAED,wBAAgB,IAAI,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,QAI9D;AAED,wBAAgB,IAAI,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,QAI9D;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,QAEhD"}
@@ -14,6 +14,11 @@ export function info(...params) {
14
14
  console.info(...params);
15
15
  }
16
16
  }
17
+ export function warn(...params) {
18
+ if (enableLogging) {
19
+ console.warn(...params);
20
+ }
21
+ }
17
22
  export function setEnableLogging(enabled) {
18
23
  enableLogging = enabled;
19
24
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/devtools/logger.ts"],"names":[],"mappings":"AAAA,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,MAAM,UAAU,GAAG,CAAC,GAAG,MAAsC;IAC3D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;KACxB;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAG,MAAwC;IAC/D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;KAC1B;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,MAAuC;IAC7D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;KACzB;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,aAAa,GAAG,OAAO,CAAC;AAC1B,CAAC","sourcesContent":["let enableLogging = false;\n\nexport function log(...params: Parameters<typeof console.log>) {\n if (enableLogging) {\n console.log(...params);\n }\n}\n\nexport function debug(...params: Parameters<typeof console.debug>) {\n if (enableLogging) {\n console.debug(...params);\n }\n}\n\nexport function info(...params: Parameters<typeof console.info>) {\n if (enableLogging) {\n console.info(...params);\n }\n}\n\nexport function setEnableLogging(enabled: boolean) {\n enableLogging = enabled;\n}\n"]}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/devtools/logger.ts"],"names":[],"mappings":"AAAA,IAAI,aAAa,GAAG,KAAK,CAAC;AAE1B,MAAM,UAAU,GAAG,CAAC,GAAG,MAAsC;IAC3D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;KACxB;AACH,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAG,MAAwC;IAC/D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC;KAC1B;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,MAAuC;IAC7D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;KACzB;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAG,MAAuC;IAC7D,IAAI,aAAa,EAAE;QACjB,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;KACzB;AACH,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,aAAa,GAAG,OAAO,CAAC;AAC1B,CAAC","sourcesContent":["let enableLogging = false;\n\nexport function log(...params: Parameters<typeof console.log>) {\n if (enableLogging) {\n console.log(...params);\n }\n}\n\nexport function debug(...params: Parameters<typeof console.debug>) {\n if (enableLogging) {\n console.debug(...params);\n }\n}\n\nexport function info(...params: Parameters<typeof console.info>) {\n if (enableLogging) {\n console.info(...params);\n }\n}\n\nexport function warn(...params: Parameters<typeof console.info>) {\n if (enableLogging) {\n console.warn(...params);\n }\n}\n\nexport function setEnableLogging(enabled: boolean) {\n enableLogging = enabled;\n}\n"]}
@@ -25,14 +25,14 @@
25
25
  "expo-brightness": "~11.8.0",
26
26
  "expo-build-properties": "~0.11.1",
27
27
  "expo-calendar": "~12.2.1",
28
- "expo-camera": "~14.1.1",
28
+ "expo-camera": "~14.1.2",
29
29
  "expo-cellular": "~5.7.1",
30
30
  "expo-checkbox": "~2.7.0",
31
31
  "expo-clipboard": "~5.0.1",
32
32
  "expo-constants": "~15.4.5",
33
33
  "expo-contacts": "~12.8.2",
34
34
  "expo-crypto": "~12.8.1",
35
- "expo-dev-client": "~3.3.10",
35
+ "expo-dev-client": "~3.3.11",
36
36
  "expo-device": "~5.9.3",
37
37
  "expo-document-picker": "~11.10.1",
38
38
  "expo-face-detector": "~12.6.1",
@@ -56,7 +56,7 @@
56
56
  "expo-mail-composer": "~12.7.1",
57
57
  "expo-media-library": "~15.9.1",
58
58
  "expo-module-template": "~10.13.2",
59
- "expo-modules-core": "~1.11.12",
59
+ "expo-modules-core": "~1.11.13",
60
60
  "expo-navigation-bar": "~2.8.1",
61
61
  "expo-network": "~5.8.0",
62
62
  "expo-notifications": "~0.27.6",
@@ -71,7 +71,7 @@
71
71
  "expo-sms": "~11.7.1",
72
72
  "expo-speech": "~11.7.0",
73
73
  "expo-splash-screen": "~0.26.4",
74
- "expo-sqlite": "~13.3.0",
74
+ "expo-sqlite": "~13.4.0",
75
75
  "expo-status-bar": "~1.11.1",
76
76
  "expo-store-review": "~6.8.3",
77
77
  "expo-system-ui": "~2.9.3",
@@ -84,7 +84,7 @@
84
84
  "lottie-react-native": "6.5.1",
85
85
  "react": "18.2.0",
86
86
  "react-dom": "18.2.0",
87
- "react-native": "0.73.5",
87
+ "react-native": "0.73.6",
88
88
  "react-native-web": "~0.19.6",
89
89
  "react-native-gesture-handler": "~2.14.0",
90
90
  "react-native-get-random-values": "~1.8.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo",
3
- "version": "50.0.13",
3
+ "version": "50.0.15",
4
4
  "description": "The Expo SDK",
5
5
  "main": "build/Expo.js",
6
6
  "module": "build/Expo.js",
@@ -71,7 +71,7 @@
71
71
  "expo-font": "~11.10.3",
72
72
  "expo-keep-awake": "~12.8.2",
73
73
  "expo-modules-autolinking": "1.10.3",
74
- "expo-modules-core": "1.11.12",
74
+ "expo-modules-core": "1.11.13",
75
75
  "fbemitter": "^3.0.0",
76
76
  "whatwg-url-without-unicode": "8.0.0-3"
77
77
  },
@@ -81,7 +81,7 @@
81
81
  "expo-module-scripts": "^3.4.1",
82
82
  "react": "18.2.0",
83
83
  "react-dom": "18.2.0",
84
- "react-native": "0.73.5"
84
+ "react-native": "0.73.6"
85
85
  },
86
- "gitHead": "92a8238b975da99998251dadac1a51651a9a1810"
86
+ "gitHead": "2ad93407e82a11504d6cc2412cf3d76858782619"
87
87
  }