expo 51.0.27 → 51.0.29

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.
@@ -33,7 +33,7 @@ def getRNVersion() {
33
33
  ensureDependeciesWereEvaluated(project)
34
34
 
35
35
  group = 'host.exp.exponent'
36
- version = '51.0.27'
36
+ version = '51.0.29'
37
37
 
38
38
  buildscript {
39
39
  // Simple helper that allows the root project to override versions declared by this library.
@@ -46,7 +46,7 @@ android {
46
46
  namespace "expo.core"
47
47
  defaultConfig {
48
48
  versionCode 1
49
- versionName "51.0.27"
49
+ versionName "51.0.29"
50
50
  consumerProguardFiles("proguard-rules.pro")
51
51
  }
52
52
  testOptions {
@@ -15,6 +15,8 @@ export declare abstract class DevToolsPluginClient {
15
15
  private readonly wsStore;
16
16
  protected isClosed: boolean;
17
17
  protected retries: number;
18
+ private readonly useTransportationNext;
19
+ private readonly messageFramePacker;
18
20
  constructor(connectionInfo: ConnectionInfo, options?: DevToolsPluginClientOptions | undefined);
19
21
  /**
20
22
  * Initialize the connection.
@@ -31,6 +33,8 @@ export declare abstract class DevToolsPluginClient {
31
33
  * @param params any extra payload.
32
34
  */
33
35
  sendMessage(method: string, params: any): void;
36
+ private sendMessageImplLegacy;
37
+ private sendMessageImplTransportationNext;
34
38
  /**
35
39
  * Subscribe to a message from the other end of DevTools.
36
40
  * @param method Subscribe to a message with a method name.
@@ -52,6 +56,8 @@ export declare abstract class DevToolsPluginClient {
52
56
  */
53
57
  protected connectAsync(): Promise<WebSocket>;
54
58
  protected handleMessage: (event: WebSocketMessageEvent) => void;
59
+ private handleMessageImplLegacy;
60
+ private handleMessageImplTransportationNext;
55
61
  /**
56
62
  * Get the WebSocket backing store. Exposed for testing.
57
63
  * @hidden
@@ -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,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,OAAO,KAAK,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAIpF,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAE1D;;;GAGG;AACH,8BAAsB,oBAAoB;aAUtB,cAAc,EAAE,cAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAV3B,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;gBAGJ,cAAc,EAAE,cAAc,EAC7B,OAAO,CAAC,yCAA6B;IAKxD;;;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;IAwB5C,SAAS,CAAC,aAAa,UAAW,qBAAqB,KAAG,IAAI,CAiB5D;IAEF;;;OAGG;IACI,wBAAwB,IAAI,qBAAqB;CAGzD"}
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;AAG5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,KAAK,EAAE,cAAc,EAAE,2BAA2B,EAAE,MAAM,kBAAkB,CAAC;AAIpF,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAO1D;;;GAGG;AACH,8BAAsB,oBAAoB;aAYtB,cAAc,EAAE,cAAc;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;IAZ3B,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;IACtB,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA0D;gBAG3E,cAAc,EAAE,cAAc,EAC7B,OAAO,CAAC,yCAA6B;IAOxD;;;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;IAY9C,OAAO,CAAC,qBAAqB;YAaf,iCAAiC;IAa/C;;;;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;IAyB5C,SAAS,CAAC,aAAa,UAAW,qBAAqB,UAMrD;IAEF,OAAO,CAAC,uBAAuB,CAiB7B;IAEF,OAAO,CAAC,mCAAmC,CAmBzC;IAEF;;;OAGG;IACI,wBAAwB,IAAI,qBAAqB;CAGzD"}
@@ -1,6 +1,8 @@
1
1
  import { EventEmitter } from 'fbemitter';
2
+ import { MessageFramePacker } from './MessageFramePacker';
2
3
  import { WebSocketBackingStore } from './WebSocketBackingStore';
3
4
  import { WebSocketWithReconnect } from './WebSocketWithReconnect';
5
+ import { blobToArrayBufferAsync } from './blobUtils';
4
6
  import * as logger from './logger';
5
7
  // This version should be synced with the one in the **createMessageSocketEndpoint.ts** in @react-native-community/cli-server-api
6
8
  export const MESSAGE_PROTOCOL_VERSION = 2;
@@ -17,10 +19,14 @@ export class DevToolsPluginClient {
17
19
  wsStore = DevToolsPluginClient.defaultWSStore;
18
20
  isClosed = false;
19
21
  retries = 0;
22
+ useTransportationNext;
23
+ messageFramePacker;
20
24
  constructor(connectionInfo, options) {
21
25
  this.connectionInfo = connectionInfo;
22
26
  this.options = options;
23
27
  this.wsStore = connectionInfo.wsStore || DevToolsPluginClient.defaultWSStore;
28
+ this.useTransportationNext = options?.useTransportationNext ?? false;
29
+ this.messageFramePacker = this.useTransportationNext ? new MessageFramePacker() : null;
24
30
  }
25
31
  /**
26
32
  * Initialize the connection.
@@ -56,6 +62,14 @@ export class DevToolsPluginClient {
56
62
  logger.warn('Unable to send message in a disconnected state.');
57
63
  return;
58
64
  }
65
+ if (this.useTransportationNext) {
66
+ this.sendMessageImplTransportationNext(method, params);
67
+ }
68
+ else {
69
+ this.sendMessageImplLegacy(method, params);
70
+ }
71
+ }
72
+ sendMessageImplLegacy(method, params) {
59
73
  const payload = {
60
74
  version: MESSAGE_PROTOCOL_VERSION,
61
75
  pluginName: this.connectionInfo.pluginName,
@@ -67,6 +81,18 @@ export class DevToolsPluginClient {
67
81
  };
68
82
  this.wsStore.ws?.send(JSON.stringify(payload));
69
83
  }
84
+ async sendMessageImplTransportationNext(method, params) {
85
+ if (this.messageFramePacker == null) {
86
+ logger.warn('MessageFramePacker is not initialized');
87
+ return;
88
+ }
89
+ const messageKey = {
90
+ pluginName: this.connectionInfo.pluginName,
91
+ method,
92
+ };
93
+ const packedData = await this.messageFramePacker.pack({ messageKey, payload: params });
94
+ this.wsStore.ws?.send(packedData);
95
+ }
70
96
  /**
71
97
  * Subscribe to a message from the other end of DevTools.
72
98
  * @param method Subscribe to a message with a method name.
@@ -94,7 +120,8 @@ export class DevToolsPluginClient {
94
120
  */
95
121
  connectAsync() {
96
122
  return new Promise((resolve, reject) => {
97
- const ws = new WebSocketWithReconnect(`ws://${this.connectionInfo.devServer}/message`, {
123
+ const endpoint = this.useTransportationNext ? 'expo-dev-plugins/broadcast' : 'message';
124
+ const ws = new WebSocketWithReconnect(`ws://${this.connectionInfo.devServer}/${endpoint}`, {
98
125
  binaryType: this.options?.websocketBinaryType,
99
126
  onError: (e) => {
100
127
  if (e instanceof Error) {
@@ -117,6 +144,14 @@ export class DevToolsPluginClient {
117
144
  });
118
145
  }
119
146
  handleMessage = (event) => {
147
+ if (this.useTransportationNext) {
148
+ this.handleMessageImplTransportationNext(event);
149
+ }
150
+ else {
151
+ this.handleMessageImplLegacy(event);
152
+ }
153
+ };
154
+ handleMessageImplLegacy = (event) => {
120
155
  let payload;
121
156
  try {
122
157
  payload = JSON.parse(event.data);
@@ -133,6 +168,28 @@ export class DevToolsPluginClient {
133
168
  }
134
169
  this.eventEmitter.emit(payload.params.method, payload.params.params);
135
170
  };
171
+ handleMessageImplTransportationNext = async (event) => {
172
+ if (this.messageFramePacker == null) {
173
+ logger.warn('MessageFramePacker is not initialized');
174
+ return;
175
+ }
176
+ let buffer;
177
+ if (event.data instanceof ArrayBuffer) {
178
+ buffer = event.data;
179
+ }
180
+ else if (event.data instanceof Blob) {
181
+ buffer = await blobToArrayBufferAsync(event.data);
182
+ }
183
+ else {
184
+ logger.warn('Unsupported received data type in handleMessageImplTransportationNext');
185
+ return;
186
+ }
187
+ const { messageKey, payload } = await this.messageFramePacker.unpack(buffer);
188
+ if (messageKey.pluginName && messageKey.pluginName !== this.connectionInfo.pluginName) {
189
+ return;
190
+ }
191
+ this.eventEmitter.emit(messageKey.method, payload);
192
+ };
136
193
  /**
137
194
  * Get the WebSocket backing store. Exposed for testing.
138
195
  * @hidden
@@ -1 +1 @@
1
- {"version":3,"file":"DevToolsPluginClient.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter, EventSubscription } from 'fbemitter';\n\nimport { WebSocketBackingStore } from './WebSocketBackingStore';\nimport { WebSocketWithReconnect } from './WebSocketWithReconnect';\nimport type { ConnectionInfo, DevToolsPluginClientOptions } 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(\n public readonly connectionInfo: ConnectionInfo,\n private readonly options?: DevToolsPluginClientOptions\n ) {\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 binaryType: this.options?.websocketBinaryType,\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"]}
1
+ {"version":3,"file":"DevToolsPluginClient.js","sourceRoot":"","sources":["../../src/devtools/DevToolsPluginClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { EventEmitter, EventSubscription } from 'fbemitter';\n\nimport { MessageFramePacker } from './MessageFramePacker';\nimport { WebSocketBackingStore } from './WebSocketBackingStore';\nimport { WebSocketWithReconnect } from './WebSocketWithReconnect';\nimport { blobToArrayBufferAsync } from './blobUtils';\nimport type { ConnectionInfo, DevToolsPluginClientOptions } 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\ninterface MessageFramePackerMessageKey {\n pluginName: string;\n method: string;\n}\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 private readonly useTransportationNext: boolean;\n private readonly messageFramePacker: MessageFramePacker<MessageFramePackerMessageKey> | null;\n\n public constructor(\n public readonly connectionInfo: ConnectionInfo,\n private readonly options?: DevToolsPluginClientOptions\n ) {\n this.wsStore = connectionInfo.wsStore || DevToolsPluginClient.defaultWSStore;\n this.useTransportationNext = options?.useTransportationNext ?? false;\n this.messageFramePacker = this.useTransportationNext ? new MessageFramePacker() : null;\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 if (this.useTransportationNext) {\n this.sendMessageImplTransportationNext(method, params);\n } else {\n this.sendMessageImplLegacy(method, params);\n }\n }\n\n private sendMessageImplLegacy(method: string, params: any) {\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 private async sendMessageImplTransportationNext(method: string, params: any) {\n if (this.messageFramePacker == null) {\n logger.warn('MessageFramePacker is not initialized');\n return;\n }\n const messageKey: MessageFramePackerMessageKey = {\n pluginName: this.connectionInfo.pluginName,\n method,\n };\n const packedData = await this.messageFramePacker.pack({ messageKey, payload: params });\n this.wsStore.ws?.send(packedData);\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 endpoint = this.useTransportationNext ? 'expo-dev-plugins/broadcast' : 'message';\n const ws = new WebSocketWithReconnect(`ws://${this.connectionInfo.devServer}/${endpoint}`, {\n binaryType: this.options?.websocketBinaryType,\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) => {\n if (this.useTransportationNext) {\n this.handleMessageImplTransportationNext(event);\n } else {\n this.handleMessageImplLegacy(event);\n }\n };\n\n private handleMessageImplLegacy = (event: WebSocketMessageEvent) => {\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 private handleMessageImplTransportationNext = async (event: WebSocketMessageEvent) => {\n if (this.messageFramePacker == null) {\n logger.warn('MessageFramePacker is not initialized');\n return;\n }\n let buffer: ArrayBuffer;\n if (event.data instanceof ArrayBuffer) {\n buffer = event.data;\n } else if (event.data instanceof Blob) {\n buffer = await blobToArrayBufferAsync(event.data);\n } else {\n logger.warn('Unsupported received data type in handleMessageImplTransportationNext');\n return;\n }\n const { messageKey, payload } = await this.messageFramePacker.unpack(buffer);\n if (messageKey.pluginName && messageKey.pluginName !== this.connectionInfo.pluginName) {\n return;\n }\n this.eventEmitter.emit(messageKey.method, payload);\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"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * A message frame packer that serializes a messageKey and a payload into a binary format.
3
+ *
4
+ * +------------------+-------------------+----------------------------+--------------------------+
5
+ * | 4 bytes (Uint32) | Variable length | 1 byte (Uint8) | Variable length |
6
+ * | MessageKeyLength | MessageKey (JSON) | PayloadTypeIndicator (enum)| Payload (binary data) |
7
+ * +------------------+-------------------+----------------------------+--------------------------+
8
+ *
9
+ * MessageFrame Format:
10
+ *
11
+ * 1. MessageKeyLength (4 bytes):
12
+ * - A 4-byte unsigned integer indicating the length of the MessageKey JSON string.
13
+ *
14
+ * 2. MessageKey (Variable length):
15
+ * - The JSON string representing the message key, encoded as UTF-8.
16
+ *
17
+ * 3. PayloadTypeIndicator (1 byte):
18
+ * - A single byte enum value representing the type of the payload (e.g., Uint8Array, String, Object, ArrayBuffer, Blob).
19
+ *
20
+ * 4. Payload (Variable length):
21
+ * - The actual payload data, which can vary in type and length depending on the PayloadType.
22
+ *
23
+ */
24
+ type MessageKeyTypeBase = string | object;
25
+ type PayloadType = Uint8Array | string | number | null | undefined | object | ArrayBuffer | Blob;
26
+ interface MessageFrame<T extends MessageKeyTypeBase> {
27
+ messageKey: T;
28
+ payload?: PayloadType;
29
+ }
30
+ export declare class MessageFramePacker<T extends MessageKeyTypeBase> {
31
+ private textEncoder;
32
+ private textDecoder;
33
+ pack({ messageKey, payload }: MessageFrame<T>): Promise<Uint8Array>;
34
+ unpack(packedData: ArrayBuffer): Promise<MessageFrame<T>>;
35
+ private payloadToUint8Array;
36
+ private deserializePayload;
37
+ private static getPayloadTypeIndicator;
38
+ }
39
+ export {};
40
+ //# sourceMappingURL=MessageFramePacker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageFramePacker.d.ts","sourceRoot":"","sources":["../../src/devtools/MessageFramePacker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,KAAK,kBAAkB,GAAG,MAAM,GAAG,MAAM,CAAC;AAC1C,KAAK,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;AAajG,UAAU,YAAY,CAAC,CAAC,SAAS,kBAAkB;IACjD,UAAU,EAAE,CAAC,CAAC;IACd,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AAED,qBAAa,kBAAkB,CAAC,CAAC,SAAS,kBAAkB;IAC1D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAqB;IAE3B,IAAI,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC;IA2BnE,MAAM,CAAC,UAAU,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAqBxD,mBAAmB;YAuBnB,kBAAkB;IAqChC,OAAO,CAAC,MAAM,CAAC,uBAAuB;CAqBvC"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * A message frame packer that serializes a messageKey and a payload into a binary format.
3
+ *
4
+ * +------------------+-------------------+----------------------------+--------------------------+
5
+ * | 4 bytes (Uint32) | Variable length | 1 byte (Uint8) | Variable length |
6
+ * | MessageKeyLength | MessageKey (JSON) | PayloadTypeIndicator (enum)| Payload (binary data) |
7
+ * +------------------+-------------------+----------------------------+--------------------------+
8
+ *
9
+ * MessageFrame Format:
10
+ *
11
+ * 1. MessageKeyLength (4 bytes):
12
+ * - A 4-byte unsigned integer indicating the length of the MessageKey JSON string.
13
+ *
14
+ * 2. MessageKey (Variable length):
15
+ * - The JSON string representing the message key, encoded as UTF-8.
16
+ *
17
+ * 3. PayloadTypeIndicator (1 byte):
18
+ * - A single byte enum value representing the type of the payload (e.g., Uint8Array, String, Object, ArrayBuffer, Blob).
19
+ *
20
+ * 4. Payload (Variable length):
21
+ * - The actual payload data, which can vary in type and length depending on the PayloadType.
22
+ *
23
+ */
24
+ import { blobToArrayBufferAsync } from './blobUtils';
25
+ var PayloadTypeIndicator;
26
+ (function (PayloadTypeIndicator) {
27
+ PayloadTypeIndicator[PayloadTypeIndicator["Uint8Array"] = 1] = "Uint8Array";
28
+ PayloadTypeIndicator[PayloadTypeIndicator["String"] = 2] = "String";
29
+ PayloadTypeIndicator[PayloadTypeIndicator["Number"] = 3] = "Number";
30
+ PayloadTypeIndicator[PayloadTypeIndicator["Null"] = 4] = "Null";
31
+ PayloadTypeIndicator[PayloadTypeIndicator["Undefined"] = 5] = "Undefined";
32
+ PayloadTypeIndicator[PayloadTypeIndicator["Object"] = 6] = "Object";
33
+ PayloadTypeIndicator[PayloadTypeIndicator["ArrayBuffer"] = 7] = "ArrayBuffer";
34
+ PayloadTypeIndicator[PayloadTypeIndicator["Blob"] = 8] = "Blob";
35
+ })(PayloadTypeIndicator || (PayloadTypeIndicator = {}));
36
+ export class MessageFramePacker {
37
+ textEncoder = new TextEncoder();
38
+ textDecoder = new TextDecoder();
39
+ async pack({ messageKey, payload }) {
40
+ const messageKeyString = JSON.stringify(messageKey);
41
+ const messageKeyBytes = this.textEncoder.encode(messageKeyString);
42
+ const messageKeyLength = messageKeyBytes.length;
43
+ const payloadBinary = await this.payloadToUint8Array(payload);
44
+ const totalLength = 4 + messageKeyLength + 1 + payloadBinary.byteLength;
45
+ const buffer = new ArrayBuffer(totalLength);
46
+ const packedArray = new Uint8Array(buffer);
47
+ // [0] messageKeyLength (4 bytes)
48
+ const messageKeyLengthView = new DataView(buffer, 0, 4);
49
+ messageKeyLengthView.setUint32(0, messageKeyLength, false);
50
+ // [1] messageKey (variable length)
51
+ packedArray.set(messageKeyBytes, 4);
52
+ // [2] payloadTypeIndicator (1 byte)
53
+ const payloadTypeView = new DataView(buffer, 4 + messageKeyLength, 1);
54
+ payloadTypeView.setUint8(0, MessageFramePacker.getPayloadTypeIndicator(payload));
55
+ // [3] payload (variable length)
56
+ packedArray.set(payloadBinary, 4 + messageKeyLength + 1);
57
+ return packedArray;
58
+ }
59
+ async unpack(packedData) {
60
+ // [0] messageKeyLength (4 bytes)
61
+ const messageKeyLengthView = new DataView(packedData, 0, 4);
62
+ const messageKeyLength = messageKeyLengthView.getUint32(0, false);
63
+ // [1] messageKey (variable length)
64
+ const messageKeyBytes = packedData.slice(4, 4 + messageKeyLength);
65
+ const messageKeyString = this.textDecoder.decode(messageKeyBytes);
66
+ const messageKey = JSON.parse(messageKeyString);
67
+ // [2] payloadTypeIndicator (1 byte)
68
+ const payloadTypeView = new DataView(packedData, 4 + messageKeyLength, 1);
69
+ const payloadType = payloadTypeView.getUint8(0);
70
+ // [3] payload (variable length)
71
+ const payloadBinary = packedData.slice(4 + messageKeyLength + 1);
72
+ const payload = await this.deserializePayload(payloadBinary, payloadType);
73
+ return { messageKey, payload };
74
+ }
75
+ async payloadToUint8Array(payload) {
76
+ if (payload instanceof Uint8Array) {
77
+ return payload;
78
+ }
79
+ else if (typeof payload === 'string') {
80
+ return this.textEncoder.encode(payload);
81
+ }
82
+ else if (typeof payload === 'number') {
83
+ const buffer = new ArrayBuffer(8);
84
+ const view = new DataView(buffer);
85
+ view.setFloat64(0, payload, false);
86
+ return new Uint8Array(buffer);
87
+ }
88
+ else if (payload === null) {
89
+ return new Uint8Array(0);
90
+ }
91
+ else if (payload === undefined) {
92
+ return new Uint8Array(0);
93
+ }
94
+ else if (payload instanceof ArrayBuffer) {
95
+ return new Uint8Array(payload);
96
+ }
97
+ else if (payload instanceof Blob) {
98
+ return new Uint8Array(await blobToArrayBufferAsync(payload));
99
+ }
100
+ else {
101
+ return this.textEncoder.encode(JSON.stringify(payload));
102
+ }
103
+ }
104
+ async deserializePayload(payloadBinary, payloadTypeIndicator) {
105
+ switch (payloadTypeIndicator) {
106
+ case PayloadTypeIndicator.Uint8Array: {
107
+ return new Uint8Array(payloadBinary);
108
+ }
109
+ case PayloadTypeIndicator.String: {
110
+ return this.textDecoder.decode(payloadBinary);
111
+ }
112
+ case PayloadTypeIndicator.Number: {
113
+ const view = new DataView(payloadBinary);
114
+ return view.getFloat64(0, false);
115
+ }
116
+ case PayloadTypeIndicator.Null: {
117
+ return null;
118
+ }
119
+ case PayloadTypeIndicator.Undefined: {
120
+ return undefined;
121
+ }
122
+ case PayloadTypeIndicator.Object: {
123
+ const jsonString = this.textDecoder.decode(payloadBinary);
124
+ return JSON.parse(jsonString);
125
+ }
126
+ case PayloadTypeIndicator.ArrayBuffer: {
127
+ return payloadBinary;
128
+ }
129
+ case PayloadTypeIndicator.Blob: {
130
+ // @ts-ignore: We only test ArrayBuffer -> Blob on Node.js runtime
131
+ return new Blob([payloadBinary]);
132
+ }
133
+ default:
134
+ throw new Error('Unsupported payload type');
135
+ }
136
+ }
137
+ static getPayloadTypeIndicator(payload) {
138
+ if (payload instanceof Uint8Array) {
139
+ return PayloadTypeIndicator.Uint8Array;
140
+ }
141
+ else if (typeof payload === 'string') {
142
+ return PayloadTypeIndicator.String;
143
+ }
144
+ else if (typeof payload === 'number') {
145
+ return PayloadTypeIndicator.Number;
146
+ }
147
+ else if (payload === null) {
148
+ return PayloadTypeIndicator.Null;
149
+ }
150
+ else if (payload === undefined) {
151
+ return PayloadTypeIndicator.Undefined;
152
+ }
153
+ else if (payload instanceof ArrayBuffer) {
154
+ return PayloadTypeIndicator.ArrayBuffer;
155
+ }
156
+ else if (payload instanceof Blob) {
157
+ return PayloadTypeIndicator.Blob;
158
+ }
159
+ else if (typeof payload === 'object') {
160
+ return PayloadTypeIndicator.Object;
161
+ }
162
+ else {
163
+ throw new Error('Unsupported payload type');
164
+ }
165
+ }
166
+ }
167
+ //# sourceMappingURL=MessageFramePacker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageFramePacker.js","sourceRoot":"","sources":["../../src/devtools/MessageFramePacker.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * A message frame packer that serializes a messageKey and a payload into a binary format.\n *\n * +------------------+-------------------+----------------------------+--------------------------+\n * | 4 bytes (Uint32) | Variable length | 1 byte (Uint8) | Variable length |\n * | MessageKeyLength | MessageKey (JSON) | PayloadTypeIndicator (enum)| Payload (binary data) |\n * +------------------+-------------------+----------------------------+--------------------------+\n *\n * MessageFrame Format:\n *\n * 1. MessageKeyLength (4 bytes):\n * - A 4-byte unsigned integer indicating the length of the MessageKey JSON string.\n *\n * 2. MessageKey (Variable length):\n * - The JSON string representing the message key, encoded as UTF-8.\n *\n * 3. PayloadTypeIndicator (1 byte):\n * - A single byte enum value representing the type of the payload (e.g., Uint8Array, String, Object, ArrayBuffer, Blob).\n *\n * 4. Payload (Variable length):\n * - The actual payload data, which can vary in type and length depending on the PayloadType.\n *\n */\n\nimport { blobToArrayBufferAsync } from './blobUtils';\n\ntype MessageKeyTypeBase = string | object;\ntype PayloadType = Uint8Array | string | number | null | undefined | object | ArrayBuffer | Blob;\n\nenum PayloadTypeIndicator {\n Uint8Array = 1,\n String = 2,\n Number = 3,\n Null = 4,\n Undefined = 5,\n Object = 6,\n ArrayBuffer = 7,\n Blob = 8,\n}\n\ninterface MessageFrame<T extends MessageKeyTypeBase> {\n messageKey: T;\n payload?: PayloadType;\n}\n\nexport class MessageFramePacker<T extends MessageKeyTypeBase> {\n private textEncoder = new TextEncoder();\n private textDecoder = new TextDecoder();\n\n public async pack({ messageKey, payload }: MessageFrame<T>): Promise<Uint8Array> {\n const messageKeyString = JSON.stringify(messageKey);\n const messageKeyBytes = this.textEncoder.encode(messageKeyString);\n const messageKeyLength = messageKeyBytes.length;\n const payloadBinary = await this.payloadToUint8Array(payload);\n\n const totalLength = 4 + messageKeyLength + 1 + payloadBinary.byteLength;\n const buffer = new ArrayBuffer(totalLength);\n const packedArray = new Uint8Array(buffer);\n\n // [0] messageKeyLength (4 bytes)\n const messageKeyLengthView = new DataView(buffer, 0, 4);\n messageKeyLengthView.setUint32(0, messageKeyLength, false);\n\n // [1] messageKey (variable length)\n packedArray.set(messageKeyBytes, 4);\n\n // [2] payloadTypeIndicator (1 byte)\n const payloadTypeView = new DataView(buffer, 4 + messageKeyLength, 1);\n payloadTypeView.setUint8(0, MessageFramePacker.getPayloadTypeIndicator(payload));\n\n // [3] payload (variable length)\n packedArray.set(payloadBinary, 4 + messageKeyLength + 1);\n\n return packedArray;\n }\n\n public async unpack(packedData: ArrayBuffer): Promise<MessageFrame<T>> {\n // [0] messageKeyLength (4 bytes)\n const messageKeyLengthView = new DataView(packedData, 0, 4);\n const messageKeyLength = messageKeyLengthView.getUint32(0, false);\n\n // [1] messageKey (variable length)\n const messageKeyBytes = packedData.slice(4, 4 + messageKeyLength);\n const messageKeyString = this.textDecoder.decode(messageKeyBytes);\n const messageKey = JSON.parse(messageKeyString);\n\n // [2] payloadTypeIndicator (1 byte)\n const payloadTypeView = new DataView(packedData, 4 + messageKeyLength, 1);\n const payloadType = payloadTypeView.getUint8(0);\n\n // [3] payload (variable length)\n const payloadBinary = packedData.slice(4 + messageKeyLength + 1);\n const payload = await this.deserializePayload(payloadBinary, payloadType);\n\n return { messageKey, payload };\n }\n\n private async payloadToUint8Array(payload: PayloadType): Promise<Uint8Array> {\n if (payload instanceof Uint8Array) {\n return payload;\n } else if (typeof payload === 'string') {\n return this.textEncoder.encode(payload);\n } else if (typeof payload === 'number') {\n const buffer = new ArrayBuffer(8);\n const view = new DataView(buffer);\n view.setFloat64(0, payload, false);\n return new Uint8Array(buffer);\n } else if (payload === null) {\n return new Uint8Array(0);\n } else if (payload === undefined) {\n return new Uint8Array(0);\n } else if (payload instanceof ArrayBuffer) {\n return new Uint8Array(payload);\n } else if (payload instanceof Blob) {\n return new Uint8Array(await blobToArrayBufferAsync(payload));\n } else {\n return this.textEncoder.encode(JSON.stringify(payload));\n }\n }\n\n private async deserializePayload(\n payloadBinary: ArrayBuffer,\n payloadTypeIndicator: PayloadTypeIndicator\n ): Promise<PayloadType> {\n switch (payloadTypeIndicator) {\n case PayloadTypeIndicator.Uint8Array: {\n return new Uint8Array(payloadBinary);\n }\n case PayloadTypeIndicator.String: {\n return this.textDecoder.decode(payloadBinary);\n }\n case PayloadTypeIndicator.Number: {\n const view = new DataView(payloadBinary);\n return view.getFloat64(0, false);\n }\n case PayloadTypeIndicator.Null: {\n return null;\n }\n case PayloadTypeIndicator.Undefined: {\n return undefined;\n }\n case PayloadTypeIndicator.Object: {\n const jsonString = this.textDecoder.decode(payloadBinary);\n return JSON.parse(jsonString);\n }\n case PayloadTypeIndicator.ArrayBuffer: {\n return payloadBinary;\n }\n case PayloadTypeIndicator.Blob: {\n // @ts-ignore: We only test ArrayBuffer -> Blob on Node.js runtime\n return new Blob([payloadBinary]);\n }\n default:\n throw new Error('Unsupported payload type');\n }\n }\n\n private static getPayloadTypeIndicator(payload: PayloadType): PayloadTypeIndicator {\n if (payload instanceof Uint8Array) {\n return PayloadTypeIndicator.Uint8Array;\n } else if (typeof payload === 'string') {\n return PayloadTypeIndicator.String;\n } else if (typeof payload === 'number') {\n return PayloadTypeIndicator.Number;\n } else if (payload === null) {\n return PayloadTypeIndicator.Null;\n } else if (payload === undefined) {\n return PayloadTypeIndicator.Undefined;\n } else if (payload instanceof ArrayBuffer) {\n return PayloadTypeIndicator.ArrayBuffer;\n } else if (payload instanceof Blob) {\n return PayloadTypeIndicator.Blob;\n } else if (typeof payload === 'object') {\n return PayloadTypeIndicator.Object;\n } else {\n throw new Error('Unsupported payload type');\n }\n }\n}\n"]}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Converts a Blob to an ArrayBuffer.
3
+ */
4
+ export declare function blobToArrayBufferAsync(blob: Blob): Promise<ArrayBuffer>;
5
+ /**
6
+ * Converts a Blob to an ArrayBuffer using the FileReader API.
7
+ */
8
+ export declare function legacyBlobToArrayBufferAsync(blob: Blob): Promise<ArrayBuffer>;
9
+ //# sourceMappingURL=blobUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blobUtils.d.ts","sourceRoot":"","sources":["../../src/devtools/blobUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAKvE;AAED;;GAEG;AACH,wBAAsB,4BAA4B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CASnF"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Converts a Blob to an ArrayBuffer.
3
+ */
4
+ export function blobToArrayBufferAsync(blob) {
5
+ if (typeof blob.arrayBuffer === 'function') {
6
+ return blob.arrayBuffer();
7
+ }
8
+ return legacyBlobToArrayBufferAsync(blob);
9
+ }
10
+ /**
11
+ * Converts a Blob to an ArrayBuffer using the FileReader API.
12
+ */
13
+ export async function legacyBlobToArrayBufferAsync(blob) {
14
+ return new Promise((resolve, reject) => {
15
+ const reader = new FileReader();
16
+ reader.onload = () => {
17
+ resolve(reader.result);
18
+ };
19
+ reader.onerror = reject;
20
+ reader.readAsArrayBuffer(blob);
21
+ });
22
+ }
23
+ //# sourceMappingURL=blobUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blobUtils.js","sourceRoot":"","sources":["../../src/devtools/blobUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAU;IAC/C,IAAI,OAAO,IAAI,CAAC,WAAW,KAAK,UAAU,EAAE;QAC1C,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;KAC3B;IACD,OAAO,4BAA4B,CAAC,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAAC,IAAU;IAC3D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;YACnB,OAAO,CAAC,MAAM,CAAC,MAAqB,CAAC,CAAC;QACxC,CAAC,CAAC;QACF,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC;QACxB,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["/**\n * Converts a Blob to an ArrayBuffer.\n */\nexport function blobToArrayBufferAsync(blob: Blob): Promise<ArrayBuffer> {\n if (typeof blob.arrayBuffer === 'function') {\n return blob.arrayBuffer();\n }\n return legacyBlobToArrayBufferAsync(blob);\n}\n\n/**\n * Converts a Blob to an ArrayBuffer using the FileReader API.\n */\nexport async function legacyBlobToArrayBufferAsync(blob: Blob): Promise<ArrayBuffer> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n resolve(reader.result as ArrayBuffer);\n };\n reader.onerror = reject;\n reader.readAsArrayBuffer(blob);\n });\n}\n"]}
@@ -32,5 +32,9 @@ export interface DevToolsPluginClientOptions {
32
32
  * The underlying WebSocket [`binaryType`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType).
33
33
  */
34
34
  websocketBinaryType?: 'arraybuffer' | 'blob';
35
+ /**
36
+ * Whether to use the new transportation protocol.
37
+ */
38
+ useTransportationNext?: boolean;
35
39
  }
36
40
  //# sourceMappingURL=devtools.types.d.ts.map
@@ -1 +1 @@
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;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,mBAAmB,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;CAC9C"}
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;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,mBAAmB,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAE7C;;OAEG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC"}
@@ -1 +1 @@
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\n/**\n * Options for the devtools plugin client.\n */\nexport interface DevToolsPluginClientOptions {\n /**\n * The underlying WebSocket [`binaryType`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType).\n */\n websocketBinaryType?: 'arraybuffer' | 'blob';\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\n/**\n * Options for the devtools plugin client.\n */\nexport interface DevToolsPluginClientOptions {\n /**\n * The underlying WebSocket [`binaryType`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/binaryType).\n */\n websocketBinaryType?: 'arraybuffer' | 'blob';\n\n /**\n * Whether to use the new transportation protocol.\n */\n useTransportationNext?: boolean;\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  {
2
- "@expo/metro-runtime": "~3.2.1",
2
+ "@expo/metro-runtime": "~3.2.3",
3
3
  "@expo/vector-icons": "^14.0.2",
4
4
  "@react-native-async-storage/async-storage": "1.23.1",
5
5
  "@react-native-community/datetimepicker": "8.0.1",
@@ -32,7 +32,7 @@
32
32
  "expo-constants": "~16.0.2",
33
33
  "expo-contacts": "~13.0.5",
34
34
  "expo-crypto": "~13.0.2",
35
- "expo-dev-client": "~4.0.22",
35
+ "expo-dev-client": "~4.0.23",
36
36
  "expo-device": "~6.0.2",
37
37
  "expo-document-picker": "~12.0.2",
38
38
  "expo-face-detector": "~12.7.1",
@@ -41,7 +41,7 @@
41
41
  "expo-gl": "~14.0.2",
42
42
  "expo-google-app-auth": "~8.3.0",
43
43
  "expo-haptics": "~13.0.1",
44
- "expo-image": "~1.12.13",
44
+ "expo-image": "~1.12.14",
45
45
  "expo-image-loader": "~4.7.0",
46
46
  "expo-image-manipulator": "~12.0.5",
47
47
  "expo-image-picker": "~15.0.7",
@@ -62,7 +62,7 @@
62
62
  "expo-notifications": "~0.28.15",
63
63
  "expo-print": "~13.0.1",
64
64
  "expo-random": "~14.0.1",
65
- "expo-router": "~3.5.21",
65
+ "expo-router": "~3.5.23",
66
66
  "expo-screen-capture": "~6.0.1",
67
67
  "expo-screen-orientation": "~7.0.5",
68
68
  "expo-secure-store": "~13.0.2",
@@ -81,7 +81,7 @@
81
81
  "expo-updates": "~0.25.22",
82
82
  "expo-video-thumbnails": "~8.0.0",
83
83
  "expo-web-browser": "~13.0.3",
84
- "jest-expo": "~51.0.3",
84
+ "jest-expo": "~51.0.4",
85
85
  "lottie-react-native": "6.7.0",
86
86
  "react": "18.2.0",
87
87
  "react-dom": "18.2.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo",
3
- "version": "51.0.27",
3
+ "version": "51.0.29",
4
4
  "description": "The Expo SDK",
5
5
  "main": "build/Expo.js",
6
6
  "module": "build/Expo.js",
@@ -60,7 +60,7 @@
60
60
  "homepage": "https://github.com/expo/expo/tree/main/packages/expo",
61
61
  "dependencies": {
62
62
  "@babel/runtime": "^7.20.0",
63
- "@expo/cli": "0.18.28",
63
+ "@expo/cli": "0.18.29",
64
64
  "@expo/config": "9.0.3",
65
65
  "@expo/config-plugins": "8.0.8",
66
66
  "@expo/metro-config": "0.18.11",
@@ -70,7 +70,7 @@
70
70
  "expo-file-system": "~17.0.1",
71
71
  "expo-font": "~12.0.9",
72
72
  "expo-keep-awake": "~13.0.2",
73
- "expo-modules-autolinking": "1.11.1",
73
+ "expo-modules-autolinking": "1.11.2",
74
74
  "expo-modules-core": "1.12.21",
75
75
  "fbemitter": "^3.0.0",
76
76
  "whatwg-url-without-unicode": "8.0.0-3"
@@ -83,5 +83,5 @@
83
83
  "react-dom": "18.2.0",
84
84
  "react-native": "0.74.5"
85
85
  },
86
- "gitHead": "07bfec459aad07ff4c792d0fd5fdca853a55dbd0"
86
+ "gitHead": "3366305d10c4daa579ef445f870d8bc5c0cd11df"
87
87
  }