javonet-nodejs-sdk 2.5.20 → 2.6.1

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.
@@ -28,19 +28,31 @@ var import_ExceptionType = require("../ExceptionType.cjs");
28
28
  class ExceptionSerializer {
29
29
  static serializeException(exception, command) {
30
30
  let exceptionCommand = new import_Command.Command(import_RuntimeName.RuntimeName.Nodejs, import_CommandType.CommandType.Exception, []);
31
- exceptionCommand = exceptionCommand.addArgToPayload(this.getExceptionCode(exception));
32
- exceptionCommand = exceptionCommand.addArgToPayload(command.toString());
33
- exceptionCommand = exceptionCommand.addArgToPayload(exception.name);
34
- exceptionCommand = exceptionCommand.addArgToPayload(exception.message);
35
31
  let stackClasses = [];
36
32
  let stackMethods = [];
37
33
  let stackLines = [];
38
34
  let stackFiles = [];
39
- this.serializeStackTrace(exception, stackClasses, stackMethods, stackLines, stackFiles);
40
- exceptionCommand = exceptionCommand.addArgToPayload(stackClasses.join("|"));
41
- exceptionCommand = exceptionCommand.addArgToPayload(stackMethods.join("|"));
42
- exceptionCommand = exceptionCommand.addArgToPayload(stackLines.join("|"));
43
- exceptionCommand = exceptionCommand.addArgToPayload(stackFiles.join("|"));
35
+ try {
36
+ this.serializeStackTrace(exception, stackClasses, stackMethods, stackLines, stackFiles);
37
+ exceptionCommand = exceptionCommand.addArgToPayload(this.getExceptionCode(exception));
38
+ exceptionCommand = exceptionCommand.addArgToPayload(command ? command.toString() : "Command is null");
39
+ exceptionCommand = exceptionCommand.addArgToPayload(exception.name);
40
+ exceptionCommand = exceptionCommand.addArgToPayload(exception.message);
41
+ exceptionCommand = exceptionCommand.addArgToPayload(stackClasses.join("|"));
42
+ exceptionCommand = exceptionCommand.addArgToPayload(stackMethods.join("|"));
43
+ exceptionCommand = exceptionCommand.addArgToPayload(stackLines.join("|"));
44
+ exceptionCommand = exceptionCommand.addArgToPayload(stackFiles.join("|"));
45
+ } catch (e) {
46
+ exceptionCommand = new import_Command.Command(import_RuntimeName.RuntimeName.Nodejs, import_CommandType.CommandType.Exception, []);
47
+ exceptionCommand = exceptionCommand.addArgToPayload(this.getExceptionCode(e));
48
+ exceptionCommand = exceptionCommand.addArgToPayload(command ? command.toString() : "Command is null");
49
+ exceptionCommand = exceptionCommand.addArgToPayload("Node.js Exception Serialization Error");
50
+ exceptionCommand = exceptionCommand.addArgToPayload(e.message);
51
+ exceptionCommand = exceptionCommand.addArgToPayload("ExceptionSerializer");
52
+ exceptionCommand = exceptionCommand.addArgToPayload("serializeException");
53
+ exceptionCommand = exceptionCommand.addArgToPayload("unknown");
54
+ exceptionCommand = exceptionCommand.addArgToPayload("ExceptionSerializer.js");
55
+ }
44
56
  return exceptionCommand;
45
57
  }
46
58
  static getExceptionCode(exception) {
@@ -56,22 +68,35 @@ class ExceptionSerializer {
56
68
  }
57
69
  }
58
70
  static serializeStackTrace(exception, stackClasses, stackMethods, stackLines, stackFiles) {
71
+ if (!exception || typeof exception.stack !== "string") {
72
+ return;
73
+ }
59
74
  const stackTrace = exception.stack.split("\n").slice(1);
60
- for (let i = 0; i < stackTrace.length; i++) {
61
- const parts = stackTrace[i].trim().match(/at\s(.*)\s\((.*):(\d+):(\d+)\)/);
75
+ for (const line of stackTrace) {
76
+ const trimmedLine = line.trim();
77
+ if (trimmedLine.includes("Javonet.Node.js")) {
78
+ continue;
79
+ }
80
+ let parts = trimmedLine.match(/at\s+(.*?)\s+\((.*?):(\d+):\d+\)/);
62
81
  if (parts) {
63
- stackClasses.push(parts[1]);
64
- stackMethods.push("unknown");
65
- stackLines.push(parts[3]);
66
- stackFiles.push(parts[2]);
67
- } else {
68
- const parts2 = stackTrace[i].trim().match(/at\s(.*):(\d+):(\d+)/);
69
- if (parts2) {
82
+ const classAndMethod = parts[1].split(".");
83
+ if (classAndMethod.length > 1) {
84
+ stackClasses.push(classAndMethod[0]);
85
+ stackMethods.push(classAndMethod.slice(1).join("."));
86
+ } else {
70
87
  stackClasses.push("unknown");
71
- stackMethods.push("unknown");
72
- stackLines.push(parts2[2]);
73
- stackFiles.push(parts2[1]);
88
+ stackMethods.push(parts[1]);
74
89
  }
90
+ stackFiles.push(parts[2]);
91
+ stackLines.push(parts[3]);
92
+ continue;
93
+ }
94
+ parts = trimmedLine.match(/at\s+(.*?):(\d+):\d+/);
95
+ if (parts) {
96
+ stackClasses.push("unknown");
97
+ stackMethods.push("unknown");
98
+ stackFiles.push(parts[1]);
99
+ stackLines.push(parts[2]);
75
100
  }
76
101
  }
77
102
  }
@@ -100,8 +100,8 @@ class Handler {
100
100
  }
101
101
  let response = handlers[command.commandType].handleCommand(command)
102
102
  return this.parseCommand(response, command.runtimeName)
103
- } catch (error) {
104
- return ExceptionSerializer.serializeException(error, command)
103
+ } catch (e) {
104
+ return ExceptionSerializer.serializeException(e, command)
105
105
  }
106
106
  }
107
107
 
@@ -1,10 +1,10 @@
1
1
  // @ts-check
2
2
  import { ReferencesCache } from '../referenceCache/ReferencesCache.js'
3
3
  import { AbstractHandler } from './AbstractHandler.js'
4
+ import { CommandType } from '../../utils/CommandType.js'
5
+ import { RuntimeName } from '../../utils/RuntimeName.js'
6
+ import { Command } from '../../utils/Command.js'
4
7
 
5
- /**
6
- * @typedef {import('../../utils/Command.js').Command} Command
7
- */
8
8
 
9
9
  class ResolveReferenceHandler extends AbstractHandler {
10
10
  constructor() {
@@ -16,7 +16,12 @@ class ResolveReferenceHandler extends AbstractHandler {
16
16
  * @returns {any}
17
17
  */
18
18
  process(command) {
19
- return ReferencesCache.getInstance().resolveReference(command.payload[0])
19
+ if (command.runtimeName === RuntimeName.Nodejs) {
20
+ return ReferencesCache.getInstance().resolveReference(command.payload[0])
21
+ }
22
+ else {
23
+ return new Command(command.runtimeName, CommandType.Reference, command.payload[0])
24
+ }
20
25
  }
21
26
  }
22
27
 
@@ -29,7 +29,16 @@ const requireDynamic = getRequire(import.meta.url)
29
29
 
30
30
  export class Interpreter {
31
31
  /** @type {Handler | null} */
32
- handler = null
32
+ _handler = null
33
+
34
+ /** @type {Handler} */
35
+ get handler() {
36
+ if (!this._handler) {
37
+ this._handler = new Handler(this)
38
+ }
39
+ return this._handler
40
+ }
41
+
33
42
  /**
34
43
  *
35
44
  * @param {Command} command
@@ -38,57 +47,42 @@ export class Interpreter {
38
47
  */
39
48
  async executeAsync(command, connectionData) {
40
49
  try {
41
- if (!this.handler) {
42
- this.handler = new Handler(this)
43
- }
44
50
  let messageByteArray = new CommandSerializer().serialize(command, connectionData)
45
51
  /** @type {Int8Array | undefined} */
46
52
  let responseByteArray = undefined
47
53
 
48
- if (
49
- command.runtimeName === RuntimeName.Nodejs &&
50
- connectionData.connectionType === ConnectionType.IN_MEMORY
51
- ) {
52
- if (isNodejsRuntime()) {
53
- // lazy receiver loading
54
+ if (connectionData.connectionType === ConnectionType.WEB_SOCKET) {
55
+ const _response = await _TransmitterWebsocket?.sendCommand(messageByteArray, connectionData)
56
+ if (_response) {
57
+ const command = new CommandDeserializer(_response).deserialize()
58
+ return command
59
+ } else {
60
+ throw new Error('Response not received from TransmitterWebsocket')
61
+ }
62
+ } else {
63
+ if (!isNodejsRuntime()) {
64
+ throw new Error('InMemory is only allowed in Nodejs runtime')
65
+ }
66
+
67
+ if (command.runtimeName === RuntimeName.Nodejs) {
54
68
  if (!_Receiver) {
55
69
  const { Receiver } = requireDynamic('../receiver/Receiver.js')
56
70
  _Receiver = Receiver
57
71
  }
58
- responseByteArray = _Receiver?.sendCommand(messageByteArray)
72
+ responseByteArray = await _Receiver?.sendCommand(messageByteArray)
59
73
  } else {
60
- throw new Error('Node.js runtime not found')
61
- }
62
- } else if (connectionData.connectionType === ConnectionType.WEB_SOCKET) {
63
- try {
64
- const _response = await _TransmitterWebsocket?.sendCommand(
65
- messageByteArray,
66
- connectionData
67
- )
68
- if (_response) {
69
- const command = new CommandDeserializer(_response).deserialize()
70
- return command
71
- } else {
72
- throw new Error('Response not received from TransmitterWebsocket')
73
- }
74
- } catch (error) {
75
- throw error
76
- }
77
- } else {
78
- if (isNodejsRuntime()) {
79
- // lazy transmitter loading
80
74
  if (!_Transmitter) {
81
75
  const { Transmitter } = requireDynamic('../transmitter/Transmitter.js')
82
76
  _Transmitter = Transmitter
83
77
  }
84
78
  responseByteArray = await _Transmitter?.sendCommand(messageByteArray)
85
- } else {
86
- throw new Error('Allowed only to run in nodejs runtime')
87
79
  }
88
80
  }
81
+
89
82
  if (!responseByteArray) {
90
83
  throw new Error('No response received from Transmitter')
91
84
  }
85
+
92
86
  return new CommandDeserializer(responseByteArray).deserialize()
93
87
  } catch (error) {
94
88
  throw error
@@ -103,60 +97,37 @@ export class Interpreter {
103
97
  */
104
98
  execute(command, connectionData) {
105
99
  try {
106
- if (!this.handler) {
107
- this.handler = new Handler(this)
108
- }
109
100
  let messageByteArray = new CommandSerializer().serialize(command, connectionData)
110
101
  /** @type {Int8Array | undefined} */
111
102
  let responseByteArray = undefined
112
103
 
113
- if (
114
- command.runtimeName === RuntimeName.Nodejs &&
115
- connectionData.connectionType === ConnectionType.IN_MEMORY
116
- ) {
117
- if (isNodejsRuntime()) {
118
- // lazy receiver loading
104
+ if (connectionData.connectionType === ConnectionType.WEB_SOCKET) {
105
+ throw new Error('Not supported')
106
+ }
107
+ if (connectionData.connectionType === ConnectionType.IN_MEMORY) {
108
+ if (!isNodejsRuntime()) {
109
+ throw new Error('InMemory is only allowed in Nodejs runtime')
110
+ }
111
+
112
+ if (command.runtimeName === RuntimeName.Nodejs) {
119
113
  if (!_Receiver) {
120
114
  const { Receiver } = requireDynamic('../receiver/Receiver.js')
121
115
  _Receiver = Receiver
122
116
  }
123
117
  responseByteArray = _Receiver?.sendCommand(messageByteArray)
124
- }
125
- } else if (connectionData.connectionType === ConnectionType.WEB_SOCKET) {
126
- // lazy transmitter websocket loading
127
- const promise = _TransmitterWebsocket?.sendCommand(messageByteArray, connectionData)
128
-
129
- if (!promise) {
130
- throw new Error('TransmitterWebsocket not found')
131
- }
132
-
133
- return promise
134
- .then((_response) => {
135
- if (_response) {
136
- const command = new CommandDeserializer(_response).deserialize()
137
- return command
138
- } else {
139
- throw new Error('Response not received from TransmitterWebsocket')
140
- }
141
- })
142
- .catch((error) => {
143
- throw error
144
- })
145
- } else {
146
- if (isNodejsRuntime()) {
118
+ } else {
147
119
  if (!_Transmitter) {
148
120
  const { Transmitter } = requireDynamic('../transmitter/Transmitter.js')
149
121
  _Transmitter = Transmitter
150
122
  }
151
-
152
123
  responseByteArray = _Transmitter?.sendCommand(messageByteArray)
153
- } else {
154
- throw new Error('Allowed only to run in nodejs runtime')
155
124
  }
156
125
  }
126
+
157
127
  if (!responseByteArray) {
158
128
  throw new Error('No response received from Transmitter')
159
129
  }
130
+
160
131
  return new CommandDeserializer(responseByteArray).deserialize()
161
132
  } catch (error) {
162
133
  throw error
@@ -170,9 +141,6 @@ export class Interpreter {
170
141
  */
171
142
  process(messageByteArray) {
172
143
  try {
173
- if (!this.handler) {
174
- this.handler = new Handler(this)
175
- }
176
144
  const receivedCommand = new CommandDeserializer(messageByteArray).deserialize()
177
145
  return this.handler?.handleCommand(receivedCommand)
178
146
  } catch (error) {
@@ -3,30 +3,38 @@ import { Interpreter } from '../interpreter/Interpreter.js'
3
3
  import { CommandSerializer } from '../protocol/CommandSerializer.js'
4
4
  import { getRequire } from '../../utils/Runtime.js'
5
5
  import { InMemoryConnectionData } from '../../utils/connectionData/InMemoryConnectionData.js'
6
-
7
- /** @type {typeof import('../../utils/RuntimeLogger.js').RuntimeLogger | null} */
8
- let _RuntimeLogger = null
9
-
10
- const requireDynamic = getRequire(import.meta.url)
6
+ import { ExceptionSerializer } from '../../utils/exception/ExceptionSerializer.js'
7
+ import { Command } from '../../utils/Command.js'
8
+ import { CommandType } from '../../utils/CommandType.js'
9
+ import { RuntimeName } from '../../utils/RuntimeName.js'
10
+ import { RuntimeLogger } from '../../utils/RuntimeLogger.js'
11
11
 
12
12
  export class Receiver {
13
13
  static connectionData = new InMemoryConnectionData()
14
14
  Receiver() {
15
- if (!_RuntimeLogger) {
16
- const { RuntimeLogger } = requireDynamic('../../utils/RuntimeLogger.js')
17
- _RuntimeLogger = RuntimeLogger
18
- }
19
- _RuntimeLogger?.printRuntimeInfo()
15
+
16
+ }
17
+
18
+ static getRuntimeInfo() {
19
+ return RuntimeLogger.getRuntimeInfo()
20
20
  }
21
21
 
22
22
  /**
23
23
  * @param {Int8Array} messageByteArray
24
24
  */
25
25
  static sendCommand(messageByteArray) {
26
- return new CommandSerializer().serialize(
27
- new Interpreter().process(messageByteArray),
28
- this.connectionData
29
- )
26
+ try {
27
+ return new CommandSerializer().serialize(
28
+ new Interpreter().process(messageByteArray),
29
+ this.connectionData
30
+ )
31
+ } catch (error) {
32
+ const exceptionCommand = ExceptionSerializer.serializeException(
33
+ error,
34
+ new Command(RuntimeName.Nodejs, CommandType.Exception, [])
35
+ )
36
+ return new CommandSerializer().serialize(exceptionCommand, this.connectionData)
37
+ }
30
38
  }
31
39
 
32
40
  /**
@@ -36,6 +36,12 @@ let WebSocket = null
36
36
  /** @type {Record<string, wsClient>} */
37
37
  export const clients = {}
38
38
 
39
+ /** @type {Record<string, Array<{resolve: Function, reject: Function, messageArray: Int8Array}>>} */
40
+ export const messageQueue = {}
41
+
42
+ /** @type {Record<string, boolean>} */
43
+ export const processingQueues = {}
44
+
39
45
  /**
40
46
  * WebSocketClient class that handles WebSocket connection, message sending, and automatic disconnection.
41
47
  */
@@ -61,16 +67,65 @@ class WebSocketClient {
61
67
  }
62
68
 
63
69
  /**
64
- * Sends messageArray through websocket connection
70
+ * Sends messageArray through websocket connection with guaranteed order preservation
65
71
  * @async
66
72
  * @param {Int8Array} messageArray
67
73
  * @returns {Promise<Int8Array>}
68
74
  */
69
75
  send(messageArray) {
76
+ return new Promise((resolve, reject) => {
77
+ if (!messageQueue[this.url]) {
78
+ messageQueue[this.url] = []
79
+ }
80
+ messageQueue[this.url].push({ resolve, reject, messageArray })
81
+
82
+ this._processMessage()
83
+ })
84
+ }
85
+
86
+ /**
87
+ * Processes message queue sequentially to maintain order
88
+ * @private
89
+ * @async
90
+ */
91
+ async _processMessage() {
92
+ if (processingQueues[this.url]) {
93
+ return
94
+ }
95
+ processingQueues[this.url] = true
96
+
97
+ try {
98
+ while (messageQueue[this.url] && messageQueue[this.url].length > 0) {
99
+ const item = messageQueue[this.url].shift()
100
+ if (!item) break
101
+
102
+ const { resolve, reject, messageArray } = item
103
+
104
+ try {
105
+ const response = await this._send(messageArray)
106
+ resolve(response)
107
+ } catch (error) {
108
+ reject(error)
109
+ }
110
+ }
111
+ } finally {
112
+ processingQueues[this.url] = false
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Sends a single message through websocket connection
118
+ * @private
119
+ * @async
120
+ * @param {Int8Array} messageArray
121
+ * @returns {Promise<Int8Array>}
122
+ */
123
+ _send(messageArray) {
70
124
  return new Promise((resolve, reject) => {
71
125
  const client = this.instance
72
- if (client) {
126
+ if (client && this.isConnected) {
73
127
  client.send(/** @type {any} */ (messageArray))
128
+
74
129
  const messageHandler = (/** @type {any} */ message) => {
75
130
  resolve(message)
76
131
  if (this.isDisconnectedAfterMessage) {
@@ -81,16 +136,16 @@ class WebSocketClient {
81
136
  client.on(WebSocketStateEvent.MESSAGE, messageHandler)
82
137
  } else {
83
138
  this._connect()
84
- .then((ws) => {
85
- ws.send(/** @type {any} */ (messageArray))
139
+ .then((client) => {
140
+ client.send(/** @type {any} */ (messageArray))
86
141
  const messageHandler = (/** @type {any} */ message) => {
87
142
  resolve(message)
88
143
  if (this.isDisconnectedAfterMessage) {
89
144
  this.disconnect()
90
145
  }
91
- ws.removeListener(WebSocketStateEvent.MESSAGE, messageHandler)
146
+ client.removeListener(WebSocketStateEvent.MESSAGE, messageHandler)
92
147
  }
93
- ws.on(WebSocketStateEvent.MESSAGE, messageHandler)
148
+ client.on(WebSocketStateEvent.MESSAGE, messageHandler)
94
149
  })
95
150
  .catch(reject)
96
151
  }
@@ -98,13 +153,24 @@ class WebSocketClient {
98
153
  }
99
154
 
100
155
  /**
101
- * Disconnects the WebSocket by terminating the connection.
156
+ * Disconnects the WebSocket by terminating the connection and cleans up queues.
102
157
  */
103
158
  disconnect() {
104
159
  if (this.instance) {
105
160
  this.instance.close()
106
161
  delete clients[this.url]
107
162
  }
163
+
164
+ // Clean up message queue and processing state
165
+ if (messageQueue[this.url]) {
166
+ // Reject any pending messages
167
+ messageQueue[this.url].forEach(({ reject }) => {
168
+ reject(new Error('WebSocket disconnected'))
169
+ })
170
+ delete messageQueue[this.url]
171
+ }
172
+
173
+ delete processingQueues[this.url]
108
174
  }
109
175
 
110
176
  /**
@@ -25,6 +25,12 @@ if (isBrowserRuntime()) {
25
25
  /** @type {Record<string, WebSocket>} */
26
26
  export const clients = {}
27
27
 
28
+ /** @type {Record<string, Array<{resolve: Function, reject: Function, messageArray: Int8Array}>>} */
29
+ export const messageQueue = {}
30
+
31
+ /** @type {Record<string, boolean>} */
32
+ export const processingQueues = {}
33
+
28
34
  /**
29
35
  * WebSocketClient class that handles WebSocket connection, message sending, and automatic disconnection.
30
36
  */
@@ -51,12 +57,59 @@ class WebSocketClientBrowser {
51
57
  }
52
58
 
53
59
  /**
54
- * Sends messageArray through websocket connection
60
+ * Sends messageArray through websocket connection with guaranteed order preservation
55
61
  * @async
56
62
  * @param {Int8Array} messageArray
57
63
  * @returns {Promise<Int8Array>}
58
64
  */
59
65
  send(messageArray) {
66
+ return new Promise((resolve, reject) => {
67
+ if (!messageQueue[this.url]) {
68
+ messageQueue[this.url] = []
69
+ }
70
+ messageQueue[this.url].push({ resolve, reject, messageArray })
71
+
72
+ this._processMessage()
73
+ })
74
+ }
75
+
76
+ /**
77
+ * Processes message queue sequentially to maintain order
78
+ * @private
79
+ * @async
80
+ */
81
+ async _processMessage() {
82
+ if (processingQueues[this.url]) {
83
+ return
84
+ }
85
+ processingQueues[this.url] = true
86
+
87
+ try {
88
+ while (messageQueue[this.url] && messageQueue[this.url].length > 0) {
89
+ const item = messageQueue[this.url].shift()
90
+ if (!item) break
91
+
92
+ const { resolve, reject, messageArray } = item
93
+ try {
94
+ const response = await this._sendSingle(messageArray)
95
+ resolve(response)
96
+ } catch (error) {
97
+ reject(error)
98
+ }
99
+ }
100
+ } finally {
101
+ processingQueues[this.url] = false
102
+ }
103
+ }
104
+
105
+ /**
106
+ * Sends a single message through websocket connection
107
+ * @private
108
+ * @async
109
+ * @param {Int8Array} messageArray
110
+ * @returns {Promise<Int8Array>}
111
+ */
112
+ _sendSingle(messageArray) {
60
113
  return new Promise((resolve, reject) => {
61
114
  const client = this.instance
62
115
  if (client && this.isConnected) {
@@ -72,7 +125,7 @@ class WebSocketClientBrowser {
72
125
  }
73
126
 
74
127
  /**
75
- * Disconnects the WebSocket by terminating the connection.
128
+ * Disconnects the WebSocket by terminating the connection and cleans up queues.
76
129
  */
77
130
  disconnect() {
78
131
  const client = this.instance
@@ -80,6 +133,14 @@ class WebSocketClientBrowser {
80
133
  client.close()
81
134
  delete clients[this.url]
82
135
  }
136
+
137
+ if (messageQueue[this.url]) {
138
+ messageQueue[this.url].forEach(({ reject }) => {
139
+ reject(new Error('WebSocket disconnected'))
140
+ })
141
+ delete messageQueue[this.url]
142
+ }
143
+ delete processingQueues[this.url]
83
144
  }
84
145
 
85
146
  /**
@@ -122,7 +122,9 @@ class InvocationContext {
122
122
  throw new Error('currentCommand is undefined in Invocation Context execute method')
123
123
  }
124
124
 
125
- this.#interpreter = new Interpreter()
125
+ if (!this.#interpreter) {
126
+ this.#interpreter = new Interpreter()
127
+ }
126
128
  //@ts-expect-error
127
129
  this.#responseCommand = this.#interpreter.execute(this.#currentCommand, this.#connectionData)
128
130
 
@@ -137,6 +139,7 @@ class InvocationContext {
137
139
  this.#isExecuted = true
138
140
  return this
139
141
  }
142
+
140
143
  return new InvocationContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true)
141
144
  }
142
145
 
@@ -531,7 +534,9 @@ class InvocationWsContext extends InvocationContext {
531
534
  throw new Error('currentCommand is undefined in Invocation Context execute method')
532
535
  }
533
536
 
534
- this.#interpreter = new Interpreter()
537
+ if (!this.#interpreter) {
538
+ this.#interpreter = new Interpreter()
539
+ }
535
540
  this.#responseCommand = await this.#interpreter.executeAsync(
536
541
  this.#currentCommand,
537
542
  this.#connectionData
@@ -548,6 +553,7 @@ class InvocationWsContext extends InvocationContext {
548
553
  this.#isExecuted = true
549
554
  return this
550
555
  }
556
+
551
557
  return new InvocationWsContext(this.#runtimeName, this.#connectionData, this.#responseCommand, true)
552
558
  }
553
559
  }
@@ -42,4 +42,7 @@ export const CommandType = /** @type {const} */ ({
42
42
  PassDelegate: 39,
43
43
  InvokeDelegate: 40,
44
44
  ConvertType: 41,
45
+ AddEventListener: 42,
46
+ PluginWrapper: 43,
47
+ GetAsyncOperationResult: 44,
45
48
  })