@metamask/snaps-controllers 7.0.1 → 8.0.0

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 (141) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/{chunk-XE5IWVNV.js → chunk-4DPX4O3T.js} +17 -6
  3. package/dist/chunk-4DPX4O3T.js.map +1 -0
  4. package/dist/{chunk-BJOQRBH2.mjs → chunk-6QZJC5I2.mjs} +2 -2
  5. package/dist/chunk-6QZJC5I2.mjs.map +1 -0
  6. package/dist/{chunk-2KCUVQFS.mjs → chunk-7DLODFQK.mjs} +2 -2
  7. package/dist/{chunk-Z6SOB3SY.js → chunk-ABKWEVW4.js} +3 -3
  8. package/dist/chunk-ABKWEVW4.js.map +1 -0
  9. package/dist/{chunk-NOLPMHXS.js → chunk-BOFPNIRX.js} +21 -3
  10. package/dist/chunk-BOFPNIRX.js.map +1 -0
  11. package/dist/{chunk-WQYMF7QP.js → chunk-CXT7XBMN.js} +3 -3
  12. package/dist/{chunk-63GNCRER.js → chunk-DQLRXCST.js} +4 -4
  13. package/dist/chunk-DQLRXCST.js.map +1 -0
  14. package/dist/{chunk-YVNRYLOC.js → chunk-DVTMXCTZ.js} +3 -3
  15. package/dist/{chunk-3ZC4LB7T.js → chunk-FOT4VRMQ.js} +3 -3
  16. package/dist/chunk-FOT4VRMQ.js.map +1 -0
  17. package/dist/{chunk-MYWDTEX2.js → chunk-GRBWVPLF.js} +4 -4
  18. package/dist/{chunk-36YC4Z3T.mjs → chunk-GTDDODNP.mjs} +13 -2
  19. package/dist/chunk-GTDDODNP.mjs.map +1 -0
  20. package/dist/{chunk-Q2ON6SMV.js → chunk-GZ3RVSUA.js} +5 -6
  21. package/dist/chunk-GZ3RVSUA.js.map +1 -0
  22. package/dist/{chunk-5MVIYRYL.mjs → chunk-HBNET6MY.mjs} +40 -26
  23. package/dist/chunk-HBNET6MY.mjs.map +1 -0
  24. package/dist/{chunk-SCERVW3B.mjs → chunk-HT7X5NPH.mjs} +2 -2
  25. package/dist/chunk-HT7X5NPH.mjs.map +1 -0
  26. package/dist/{chunk-WVGK5B5P.mjs → chunk-IRVUYBSV.mjs} +70 -41
  27. package/dist/chunk-IRVUYBSV.mjs.map +1 -0
  28. package/dist/{chunk-CJN25EXL.js → chunk-JMP6XYRL.js} +46 -32
  29. package/dist/chunk-JMP6XYRL.js.map +1 -0
  30. package/dist/{chunk-Y5KX5ICF.mjs → chunk-JQLPWQIR.mjs} +3 -3
  31. package/dist/chunk-JQLPWQIR.mjs.map +1 -0
  32. package/dist/{chunk-54TYYPAN.js → chunk-JZCXZEFV.js} +72 -43
  33. package/dist/chunk-JZCXZEFV.js.map +1 -0
  34. package/dist/{chunk-NSLYI2LS.js → chunk-M2NMZ4ER.js} +3 -3
  35. package/dist/chunk-M2NMZ4ER.js.map +1 -0
  36. package/dist/{chunk-Q4I5QTVC.mjs → chunk-MB23XAVD.mjs} +2 -2
  37. package/dist/chunk-MB23XAVD.mjs.map +1 -0
  38. package/dist/{chunk-75VM3O4K.mjs → chunk-MD2JCQBG.mjs} +2 -2
  39. package/dist/{chunk-25LS4KZK.mjs → chunk-PGQXTXAQ.mjs} +3 -3
  40. package/dist/chunk-PGQXTXAQ.mjs.map +1 -0
  41. package/dist/{chunk-N7WIJNHY.js → chunk-PRJADV7W.js} +4 -4
  42. package/dist/chunk-PRJADV7W.js.map +1 -0
  43. package/dist/{chunk-K276CM3B.mjs → chunk-SD6JM5ZU.mjs} +6 -7
  44. package/dist/chunk-SD6JM5ZU.mjs.map +1 -0
  45. package/dist/{chunk-VOZOZKRC.mjs → chunk-XO7KDFBY.mjs} +21 -3
  46. package/dist/chunk-XO7KDFBY.mjs.map +1 -0
  47. package/dist/{chunk-ZETJVFUS.mjs → chunk-XSFI32LB.mjs} +2 -2
  48. package/dist/cronjob/CronjobController.js +11 -11
  49. package/dist/cronjob/CronjobController.mjs +10 -10
  50. package/dist/cronjob/index.js +11 -11
  51. package/dist/cronjob/index.mjs +10 -10
  52. package/dist/index.js +13 -11
  53. package/dist/index.mjs +12 -10
  54. package/dist/interface/SnapInterfaceController.js +2 -2
  55. package/dist/interface/SnapInterfaceController.mjs +1 -1
  56. package/dist/interface/index.js +2 -2
  57. package/dist/interface/index.mjs +1 -1
  58. package/dist/node.js +15 -13
  59. package/dist/node.mjs +14 -12
  60. package/dist/react-native.js +14 -12
  61. package/dist/react-native.mjs +13 -11
  62. package/dist/services/AbstractExecutionService.js +4 -4
  63. package/dist/services/AbstractExecutionService.mjs +3 -3
  64. package/dist/services/browser.js +9 -9
  65. package/dist/services/browser.mjs +8 -8
  66. package/dist/services/iframe/IframeExecutionService.js +5 -5
  67. package/dist/services/iframe/IframeExecutionService.mjs +4 -4
  68. package/dist/services/iframe/index.js +5 -5
  69. package/dist/services/iframe/index.mjs +4 -4
  70. package/dist/services/index.js +8 -8
  71. package/dist/services/index.mjs +7 -7
  72. package/dist/services/node-js/NodeProcessExecutionService.js +9 -9
  73. package/dist/services/node-js/NodeProcessExecutionService.mjs +8 -8
  74. package/dist/services/node-js/NodeThreadExecutionService.js +9 -9
  75. package/dist/services/node-js/NodeThreadExecutionService.mjs +8 -8
  76. package/dist/services/node-js/index.js +10 -10
  77. package/dist/services/node-js/index.mjs +9 -9
  78. package/dist/services/node.js +10 -10
  79. package/dist/services/node.mjs +9 -9
  80. package/dist/services/offscreen/OffscreenExecutionService.js +6 -6
  81. package/dist/services/offscreen/OffscreenExecutionService.mjs +5 -5
  82. package/dist/services/offscreen/index.js +6 -6
  83. package/dist/services/offscreen/index.mjs +5 -5
  84. package/dist/services/proxy/ProxyExecutionService.js +5 -5
  85. package/dist/services/proxy/ProxyExecutionService.mjs +4 -4
  86. package/dist/services/react-native.js +9 -9
  87. package/dist/services/react-native.mjs +8 -8
  88. package/dist/services/webview/WebViewExecutionService.js +6 -6
  89. package/dist/services/webview/WebViewExecutionService.mjs +5 -5
  90. package/dist/services/webview/index.js +6 -6
  91. package/dist/services/webview/index.mjs +5 -5
  92. package/dist/services/webworker/WebWorkerExecutionService.js +5 -5
  93. package/dist/services/webworker/WebWorkerExecutionService.mjs +4 -4
  94. package/dist/services/webworker/index.js +5 -5
  95. package/dist/services/webworker/index.mjs +4 -4
  96. package/dist/snaps/SnapController.js +4 -4
  97. package/dist/snaps/SnapController.mjs +3 -3
  98. package/dist/snaps/Timer.js +2 -2
  99. package/dist/snaps/Timer.mjs +1 -1
  100. package/dist/snaps/index.js +4 -4
  101. package/dist/snaps/index.mjs +3 -3
  102. package/dist/tsconfig.build.tsbuildinfo +1 -1
  103. package/dist/types/services/AbstractExecutionService.d.ts +17 -12
  104. package/dist/types/services/ExecutionService.d.ts +1 -1
  105. package/dist/types/services/iframe/IframeExecutionService.d.ts +2 -2
  106. package/dist/types/services/node-js/NodeProcessExecutionService.d.ts +2 -2
  107. package/dist/types/services/node-js/NodeThreadExecutionService.d.ts +2 -2
  108. package/dist/types/services/proxy/ProxyExecutionService.d.ts +2 -2
  109. package/dist/types/services/webworker/WebWorkerExecutionService.d.ts +2 -2
  110. package/dist/types/snaps/SnapController.d.ts +5 -6
  111. package/dist/types/snaps/Timer.d.ts +7 -0
  112. package/dist/types/utils.d.ts +12 -0
  113. package/dist/utils.js +5 -3
  114. package/dist/utils.mjs +4 -2
  115. package/package.json +5 -4
  116. package/dist/chunk-25LS4KZK.mjs.map +0 -1
  117. package/dist/chunk-36YC4Z3T.mjs.map +0 -1
  118. package/dist/chunk-3ZC4LB7T.js.map +0 -1
  119. package/dist/chunk-54TYYPAN.js.map +0 -1
  120. package/dist/chunk-5MVIYRYL.mjs.map +0 -1
  121. package/dist/chunk-63GNCRER.js.map +0 -1
  122. package/dist/chunk-BJOQRBH2.mjs.map +0 -1
  123. package/dist/chunk-CJN25EXL.js.map +0 -1
  124. package/dist/chunk-K276CM3B.mjs.map +0 -1
  125. package/dist/chunk-N7WIJNHY.js.map +0 -1
  126. package/dist/chunk-NOLPMHXS.js.map +0 -1
  127. package/dist/chunk-NSLYI2LS.js.map +0 -1
  128. package/dist/chunk-Q2ON6SMV.js.map +0 -1
  129. package/dist/chunk-Q4I5QTVC.mjs.map +0 -1
  130. package/dist/chunk-SCERVW3B.mjs.map +0 -1
  131. package/dist/chunk-VOZOZKRC.mjs.map +0 -1
  132. package/dist/chunk-WVGK5B5P.mjs.map +0 -1
  133. package/dist/chunk-XE5IWVNV.js.map +0 -1
  134. package/dist/chunk-Y5KX5ICF.mjs.map +0 -1
  135. package/dist/chunk-Z6SOB3SY.js.map +0 -1
  136. /package/dist/{chunk-2KCUVQFS.mjs.map → chunk-7DLODFQK.mjs.map} +0 -0
  137. /package/dist/{chunk-WQYMF7QP.js.map → chunk-CXT7XBMN.js.map} +0 -0
  138. /package/dist/{chunk-YVNRYLOC.js.map → chunk-DVTMXCTZ.js.map} +0 -0
  139. /package/dist/{chunk-MYWDTEX2.js.map → chunk-GRBWVPLF.js.map} +0 -0
  140. /package/dist/{chunk-75VM3O4K.mjs.map → chunk-MD2JCQBG.mjs.map} +0 -0
  141. /package/dist/{chunk-ZETJVFUS.mjs.map → chunk-XSFI32LB.mjs.map} +0 -0
@@ -4,7 +4,10 @@ import {
4
4
  import {
5
5
  hasTimedOut,
6
6
  withTimeout
7
- } from "./chunk-36YC4Z3T.mjs";
7
+ } from "./chunk-GTDDODNP.mjs";
8
+ import {
9
+ Timer
10
+ } from "./chunk-XO7KDFBY.mjs";
8
11
  import {
9
12
  __privateAdd,
10
13
  __privateGet,
@@ -28,11 +31,12 @@ import {
28
31
  import { nanoid } from "nanoid";
29
32
  import { pipeline } from "readable-stream";
30
33
  var controllerName = "ExecutionService";
31
- var _snapRpcHooks, _snapToJobMap, _jobToSnapMap, _messenger, _pingTimeout, _terminationTimeout, _removeSnapHooks, removeSnapHooks_fn, _createSnapHooks, createSnapHooks_fn, _mapSnapAndJob, mapSnapAndJob_fn, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn;
34
+ var _snapRpcHooks, _snapToJobMap, _jobToSnapMap, _messenger, _initTimeout, _pingTimeout, _terminationTimeout, _removeSnapHooks, removeSnapHooks_fn, _createSnapHooks, createSnapHooks_fn, _mapSnapAndJob, mapSnapAndJob_fn, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn;
32
35
  var AbstractExecutionService = class {
33
36
  constructor({
34
37
  setupSnapProvider,
35
38
  messenger,
39
+ initTimeout = inMilliseconds(60, Duration.Second),
36
40
  pingTimeout = inMilliseconds(2, Duration.Second),
37
41
  terminationTimeout = inMilliseconds(1, Duration.Second)
38
42
  }) {
@@ -44,6 +48,7 @@ var AbstractExecutionService = class {
44
48
  __privateAdd(this, _snapToJobMap, void 0);
45
49
  __privateAdd(this, _jobToSnapMap, void 0);
46
50
  __privateAdd(this, _messenger, void 0);
51
+ __privateAdd(this, _initTimeout, void 0);
47
52
  __privateAdd(this, _pingTimeout, void 0);
48
53
  __privateAdd(this, _terminationTimeout, void 0);
49
54
  __privateSet(this, _snapRpcHooks, /* @__PURE__ */ new Map());
@@ -52,6 +57,7 @@ var AbstractExecutionService = class {
52
57
  __privateSet(this, _snapToJobMap, /* @__PURE__ */ new Map());
53
58
  __privateSet(this, _jobToSnapMap, /* @__PURE__ */ new Map());
54
59
  __privateSet(this, _messenger, messenger);
60
+ __privateSet(this, _initTimeout, initTimeout);
55
61
  __privateSet(this, _pingTimeout, pingTimeout);
56
62
  __privateSet(this, _terminationTimeout, terminationTimeout);
57
63
  this.registerMessageHandlers();
@@ -67,7 +73,7 @@ var AbstractExecutionService = class {
67
73
  );
68
74
  __privateGet(this, _messenger).registerActionHandler(
69
75
  `${controllerName}:executeSnap`,
70
- async (snapData) => this.executeSnap(snapData)
76
+ async (data) => this.executeSnap(data)
71
77
  );
72
78
  __privateGet(this, _messenger).registerActionHandler(
73
79
  `${controllerName}:terminateSnap`,
@@ -91,17 +97,20 @@ var AbstractExecutionService = class {
91
97
  if (!jobWrapper) {
92
98
  throw new Error(`Job with id "${jobId}" not found.`);
93
99
  }
94
- const result = await withTimeout(
95
- this.command(jobId, {
96
- jsonrpc: "2.0",
97
- method: "terminate",
98
- params: [],
99
- id: nanoid()
100
- }),
101
- __privateGet(this, _terminationTimeout)
102
- );
103
- if (result === hasTimedOut || result !== "OK") {
104
- logError(`Job "${jobId}" failed to terminate gracefully.`, result);
100
+ try {
101
+ const result = await withTimeout(
102
+ this.command(jobId, {
103
+ jsonrpc: "2.0",
104
+ method: "terminate",
105
+ params: [],
106
+ id: nanoid()
107
+ }),
108
+ __privateGet(this, _terminationTimeout)
109
+ );
110
+ if (result === hasTimedOut || result !== "OK") {
111
+ logError(`Job "${jobId}" failed to terminate gracefully.`, result);
112
+ }
113
+ } catch {
105
114
  }
106
115
  Object.values(jobWrapper.streams).forEach((stream) => {
107
116
  try {
@@ -112,20 +121,20 @@ var AbstractExecutionService = class {
112
121
  }
113
122
  });
114
123
  this.terminateJob(jobWrapper);
115
- __privateMethod(this, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn).call(this, jobId);
116
124
  this.jobs.delete(jobId);
125
+ __privateMethod(this, _removeSnapAndJobMapping, removeSnapAndJobMapping_fn).call(this, jobId);
117
126
  log(`Job "${jobId}" terminated.`);
118
127
  }
119
128
  /**
120
129
  * Initiates a job for a snap.
121
130
  *
122
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
123
- *
131
+ * @param jobId - The ID of the job to initiate.
132
+ * @param timer - The timer to use for timeouts.
124
133
  * @returns Information regarding the created job.
134
+ * @throws If the execution service returns an error or execution times out.
125
135
  */
126
- async initJob() {
127
- const jobId = nanoid();
128
- const { streams, worker } = await this.initStreams(jobId);
136
+ async initJob(jobId, timer) {
137
+ const { streams, worker } = await this.initStreams(jobId, timer);
129
138
  const rpcEngine = new JsonRpcEngine();
130
139
  const jsonRpcConnection = createStreamMiddleware();
131
140
  pipeline(
@@ -151,13 +160,18 @@ var AbstractExecutionService = class {
151
160
  /**
152
161
  * Sets up the streams for an initiated job.
153
162
  *
154
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
155
- *
156
163
  * @param jobId - The id of the job.
164
+ * @param timer - The timer to use for timeouts.
157
165
  * @returns The streams to communicate with the worker and the worker itself.
166
+ * @throws If the execution service returns an error or execution times out.
158
167
  */
159
- async initStreams(jobId) {
160
- const { worker, stream: envStream } = await this.initEnvStream(jobId);
168
+ async initStreams(jobId, timer) {
169
+ const result = await withTimeout(this.initEnvStream(jobId), timer);
170
+ if (result === hasTimedOut) {
171
+ this.terminateJob({ id: jobId });
172
+ throw new Error("The Snaps execution environment failed to start.");
173
+ }
174
+ const { worker, stream: envStream } = result;
161
175
  const mux = setupMultiplex(envStream, `Job: "${jobId}"`);
162
176
  const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);
163
177
  const notificationHandler = (message) => {
@@ -235,18 +249,25 @@ var AbstractExecutionService = class {
235
249
  /**
236
250
  * Initializes and executes a snap, setting up the communication channels to the snap etc.
237
251
  *
238
- * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.
239
- *
240
252
  * @param snapData - Data needed for Snap execution.
253
+ * @param snapData.snapId - The ID of the Snap to execute.
254
+ * @param snapData.sourceCode - The source code of the Snap to execute.
255
+ * @param snapData.endowments - The endowments available to the executing Snap.
241
256
  * @returns A string `OK` if execution succeeded.
242
- * @throws If the execution service returns an error.
257
+ * @throws If the execution service returns an error or execution times out.
243
258
  */
244
- async executeSnap(snapData) {
245
- if (__privateGet(this, _snapToJobMap).has(snapData.snapId)) {
246
- throw new Error(`Snap "${snapData.snapId}" is already being executed.`);
259
+ async executeSnap({
260
+ snapId,
261
+ sourceCode,
262
+ endowments
263
+ }) {
264
+ if (__privateGet(this, _snapToJobMap).has(snapId)) {
265
+ throw new Error(`Snap "${snapId}" is already being executed.`);
247
266
  }
248
- const job = await this.initJob();
249
- __privateMethod(this, _mapSnapAndJob, mapSnapAndJob_fn).call(this, snapData.snapId, job.id);
267
+ const jobId = nanoid();
268
+ const timer = new Timer(__privateGet(this, _initTimeout));
269
+ const job = await this.initJob(jobId, timer);
270
+ __privateMethod(this, _mapSnapAndJob, mapSnapAndJob_fn).call(this, snapId, job.id);
250
271
  const pingResult = await withTimeout(
251
272
  this.command(job.id, {
252
273
  jsonrpc: "2.0",
@@ -259,14 +280,21 @@ var AbstractExecutionService = class {
259
280
  throw new Error("The Snaps execution environment failed to start.");
260
281
  }
261
282
  const rpcStream = job.streams.rpc;
262
- this.setupSnapProvider(snapData.snapId, rpcStream);
263
- const result = await this.command(job.id, {
264
- jsonrpc: "2.0",
265
- method: "executeSnap",
266
- params: snapData,
267
- id: nanoid()
268
- });
269
- __privateMethod(this, _createSnapHooks, createSnapHooks_fn).call(this, snapData.snapId, job.id);
283
+ this.setupSnapProvider(snapId, rpcStream);
284
+ const remainingTime = timer.remaining;
285
+ const result = await withTimeout(
286
+ this.command(job.id, {
287
+ jsonrpc: "2.0",
288
+ method: "executeSnap",
289
+ params: { snapId, sourceCode, endowments },
290
+ id: nanoid()
291
+ }),
292
+ remainingTime
293
+ );
294
+ if (result === hasTimedOut) {
295
+ throw new Error(`${snapId} failed to start.`);
296
+ }
297
+ __privateMethod(this, _createSnapHooks, createSnapHooks_fn).call(this, snapId, job.id);
270
298
  return result;
271
299
  }
272
300
  // Cannot be hash private yet because of tests.
@@ -310,6 +338,7 @@ _snapRpcHooks = new WeakMap();
310
338
  _snapToJobMap = new WeakMap();
311
339
  _jobToSnapMap = new WeakMap();
312
340
  _messenger = new WeakMap();
341
+ _initTimeout = new WeakMap();
313
342
  _pingTimeout = new WeakMap();
314
343
  _terminationTimeout = new WeakMap();
315
344
  _removeSnapHooks = new WeakSet();
@@ -362,4 +391,4 @@ export {
362
391
  AbstractExecutionService,
363
392
  setupMultiplex
364
393
  };
365
- //# sourceMappingURL=chunk-WVGK5B5P.mjs.map
394
+ //# sourceMappingURL=chunk-IRVUYBSV.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/services/AbstractExecutionService.ts"],"sourcesContent":["import { JsonRpcEngine } from '@metamask/json-rpc-engine';\nimport { createStreamMiddleware } from '@metamask/json-rpc-middleware-stream';\nimport ObjectMultiplex from '@metamask/object-multiplex';\nimport type { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { JsonRpcError } from '@metamask/rpc-errors';\nimport type { SnapRpcHook, SnapRpcHookArgs } from '@metamask/snaps-utils';\nimport { SNAP_STREAM_NAMES, logError } from '@metamask/snaps-utils';\nimport type {\n Json,\n JsonRpcNotification,\n JsonRpcRequest,\n PendingJsonRpcResponse,\n} from '@metamask/utils';\nimport {\n Duration,\n assertIsJsonRpcRequest,\n inMilliseconds,\n isJsonRpcNotification,\n isObject,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\nimport { pipeline } from 'readable-stream';\nimport type { Duplex } from 'readable-stream';\n\nimport { log } from '../logging';\nimport { Timer } from '../snaps/Timer';\nimport { hasTimedOut, withTimeout } from '../utils';\nimport type {\n ExecutionService,\n ExecutionServiceMessenger,\n SnapErrorJson,\n SnapExecutionData,\n} from './ExecutionService';\n\nconst controllerName = 'ExecutionService';\n\nexport type SetupSnapProvider = (snapId: string, stream: Duplex) => void;\n\nexport type ExecutionServiceArgs = {\n setupSnapProvider: SetupSnapProvider;\n messenger: ExecutionServiceMessenger;\n initTimeout?: number;\n pingTimeout?: number;\n terminationTimeout?: number;\n};\n\nexport type JobStreams = {\n command: Duplex;\n rpc: Duplex;\n _connection: BasePostMessageStream;\n};\n\nexport type Job<WorkerType> = {\n id: string;\n streams: JobStreams;\n rpcEngine: JsonRpcEngine;\n worker: WorkerType;\n};\n\nexport type TerminateJobArgs<WorkerType> = Partial<Job<WorkerType>> &\n Pick<Job<WorkerType>, 'id'>;\n\nexport abstract class AbstractExecutionService<WorkerType>\n implements ExecutionService\n{\n #snapRpcHooks: Map<string, SnapRpcHook>;\n\n // Cannot be hash private yet because of tests.\n protected jobs: Map<string, Job<WorkerType>>;\n\n // Cannot be hash private yet because of tests.\n private readonly setupSnapProvider: SetupSnapProvider;\n\n #snapToJobMap: Map<string, string>;\n\n #jobToSnapMap: Map<string, string>;\n\n #messenger: ExecutionServiceMessenger;\n\n #initTimeout: number;\n\n #pingTimeout: number;\n\n #terminationTimeout: number;\n\n constructor({\n setupSnapProvider,\n messenger,\n initTimeout = inMilliseconds(60, Duration.Second),\n pingTimeout = inMilliseconds(2, Duration.Second),\n terminationTimeout = inMilliseconds(1, Duration.Second),\n }: ExecutionServiceArgs) {\n this.#snapRpcHooks = new Map();\n this.jobs = new Map();\n this.setupSnapProvider = setupSnapProvider;\n this.#snapToJobMap = new Map();\n this.#jobToSnapMap = new Map();\n this.#messenger = messenger;\n this.#initTimeout = initTimeout;\n this.#pingTimeout = pingTimeout;\n this.#terminationTimeout = terminationTimeout;\n\n this.registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering the controller's messaging system\n * actions.\n */\n private registerMessageHandlers(): void {\n this.#messenger.registerActionHandler(\n `${controllerName}:handleRpcRequest`,\n async (snapId: string, options: SnapRpcHookArgs) =>\n this.handleRpcRequest(snapId, options),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:executeSnap`,\n async (data: SnapExecutionData) => this.executeSnap(data),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateSnap`,\n async (snapId: string) => this.terminateSnap(snapId),\n );\n\n this.#messenger.registerActionHandler(\n `${controllerName}:terminateAllSnaps`,\n async () => this.terminateAllSnaps(),\n );\n }\n\n /**\n * Performs additional necessary work during job termination. **MUST** be\n * implemented by concrete implementations. See\n * {@link AbstractExecutionService.terminate} for details.\n *\n * @param job - The object corresponding to the job to be terminated.\n */\n protected abstract terminateJob(job: TerminateJobArgs<WorkerType>): void;\n\n /**\n * Terminates the job with the specified ID and deletes all its associated\n * data. Any subsequent messages targeting the job will fail with an error.\n * Throws an error if the specified job does not exist, or if termination\n * fails unexpectedly.\n *\n * @param jobId - The id of the job to be terminated.\n */\n public async terminate(jobId: string): Promise<void> {\n const jobWrapper = this.jobs.get(jobId);\n if (!jobWrapper) {\n throw new Error(`Job with id \"${jobId}\" not found.`);\n }\n\n try {\n // Ping worker and tell it to run teardown, continue with termination if it takes too long\n const result = await withTimeout(\n this.command(jobId, {\n jsonrpc: '2.0',\n method: 'terminate',\n params: [],\n id: nanoid(),\n }),\n this.#terminationTimeout,\n );\n\n if (result === hasTimedOut || result !== 'OK') {\n // We tried to shutdown gracefully but failed. This probably means the Snap is in infinite loop and\n // hogging down the whole JS process.\n // TODO(ritave): It might be doing weird things such as posting a lot of setTimeouts. Add a test to ensure that this behaviour\n // doesn't leak into other workers. Especially important in IframeExecutionEnvironment since they all share the same\n // JS process.\n logError(`Job \"${jobId}\" failed to terminate gracefully.`, result);\n }\n } catch {\n // Ignore\n }\n\n Object.values(jobWrapper.streams).forEach((stream) => {\n try {\n !stream.destroyed && stream.destroy();\n stream.removeAllListeners();\n } catch (error) {\n logError('Error while destroying stream', error);\n }\n });\n\n this.terminateJob(jobWrapper);\n\n this.jobs.delete(jobId);\n this.#removeSnapAndJobMapping(jobId);\n log(`Job \"${jobId}\" terminated.`);\n }\n\n /**\n * Initiates a job for a snap.\n *\n * @param jobId - The ID of the job to initiate.\n * @param timer - The timer to use for timeouts.\n * @returns Information regarding the created job.\n * @throws If the execution service returns an error or execution times out.\n */\n protected async initJob(\n jobId: string,\n timer: Timer,\n ): Promise<Job<WorkerType>> {\n const { streams, worker } = await this.initStreams(jobId, timer);\n const rpcEngine = new JsonRpcEngine();\n\n const jsonRpcConnection = createStreamMiddleware();\n\n pipeline(\n jsonRpcConnection.stream,\n streams.command,\n jsonRpcConnection.stream,\n (error) => {\n if (error) {\n logError(`Command stream failure.`, error);\n }\n },\n );\n\n rpcEngine.push(jsonRpcConnection.middleware);\n\n const envMetadata = {\n id: jobId,\n streams,\n rpcEngine,\n worker,\n };\n this.jobs.set(jobId, envMetadata);\n\n return envMetadata;\n }\n\n /**\n * Sets up the streams for an initiated job.\n *\n * @param jobId - The id of the job.\n * @param timer - The timer to use for timeouts.\n * @returns The streams to communicate with the worker and the worker itself.\n * @throws If the execution service returns an error or execution times out.\n */\n protected async initStreams(\n jobId: string,\n timer: Timer,\n ): Promise<{ streams: JobStreams; worker: WorkerType }> {\n const result = await withTimeout(this.initEnvStream(jobId), timer);\n\n if (result === hasTimedOut) {\n // For certain environments, such as the iframe we may have already created the worker and wish to terminate it.\n this.terminateJob({ id: jobId });\n throw new Error('The Snaps execution environment failed to start.');\n }\n\n const { worker, stream: envStream } = result;\n const mux = setupMultiplex(envStream, `Job: \"${jobId}\"`);\n const commandStream = mux.createStream(SNAP_STREAM_NAMES.COMMAND);\n\n // Handle out-of-band errors, i.e. errors thrown from the snap outside of the req/res cycle.\n // Also keep track of outbound request/responses\n const notificationHandler = (\n message:\n | JsonRpcRequest\n | JsonRpcNotification<Json[] | Record<string, Json>>,\n ) => {\n if (!isJsonRpcNotification(message)) {\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const snapId = this.#jobToSnapMap.get(jobId)!;\n if (message.method === 'OutboundRequest') {\n this.#messenger.publish('ExecutionService:outboundRequest', snapId);\n } else if (message.method === 'OutboundResponse') {\n this.#messenger.publish('ExecutionService:outboundResponse', snapId);\n } else if (message.method === 'UnhandledError') {\n if (isObject(message.params) && message.params.error) {\n this.#messenger.publish(\n 'ExecutionService:unhandledError',\n snapId,\n message.params.error as SnapErrorJson,\n );\n commandStream.removeListener('data', notificationHandler);\n } else {\n logError(\n new Error(\n `Received malformed \"${message.method}\" command stream notification.`,\n ),\n );\n }\n } else {\n logError(\n new Error(\n `Received unexpected command stream notification \"${message.method}\".`,\n ),\n );\n }\n };\n\n commandStream.on('data', notificationHandler);\n const rpcStream = mux.createStream(SNAP_STREAM_NAMES.JSON_RPC);\n\n // Typecast: stream type mismatch\n return {\n streams: {\n command: commandStream,\n rpc: rpcStream,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n _connection: envStream,\n },\n worker,\n };\n }\n\n /**\n * Abstract function implemented by implementing class that spins up a new worker for a job.\n *\n * Depending on the execution environment, this may run forever if the Snap fails to start up properly, therefore any call to this function should be wrapped in a timeout.\n */\n protected abstract initEnvStream(jobId: string): Promise<{\n worker: WorkerType;\n stream: BasePostMessageStream;\n }>;\n\n /**\n * Terminates the Snap with the specified ID. May throw an error if\n * termination unexpectedly fails, but will not fail if no job for the snap\n * with the specified ID is found.\n *\n * @param snapId - The ID of the snap to terminate.\n */\n async terminateSnap(snapId: string) {\n const jobId = this.#snapToJobMap.get(snapId);\n if (jobId) {\n await this.terminate(jobId);\n }\n }\n\n async terminateAllSnaps() {\n await Promise.all(\n [...this.jobs.keys()].map(async (jobId) => this.terminate(jobId)),\n );\n this.#snapRpcHooks.clear();\n }\n\n /**\n * Gets the RPC request handler for the given snap.\n *\n * @param snapId - The id of the Snap whose message handler to get.\n * @returns The RPC request handler for the snap.\n */\n private getRpcRequestHandler(snapId: string) {\n return this.#snapRpcHooks.get(snapId);\n }\n\n /**\n * Initializes and executes a snap, setting up the communication channels to the snap etc.\n *\n * @param snapData - Data needed for Snap execution.\n * @param snapData.snapId - The ID of the Snap to execute.\n * @param snapData.sourceCode - The source code of the Snap to execute.\n * @param snapData.endowments - The endowments available to the executing Snap.\n * @returns A string `OK` if execution succeeded.\n * @throws If the execution service returns an error or execution times out.\n */\n async executeSnap({\n snapId,\n sourceCode,\n endowments,\n }: SnapExecutionData): Promise<string> {\n if (this.#snapToJobMap.has(snapId)) {\n throw new Error(`Snap \"${snapId}\" is already being executed.`);\n }\n\n const jobId = nanoid();\n const timer = new Timer(this.#initTimeout);\n\n // This may resolve even if the environment has failed to start up fully\n const job = await this.initJob(jobId, timer);\n\n this.#mapSnapAndJob(snapId, job.id);\n\n // Ping the worker to ensure that it started up\n const pingResult = await withTimeout(\n this.command(job.id, {\n jsonrpc: '2.0',\n method: 'ping',\n id: nanoid(),\n }),\n this.#pingTimeout,\n );\n\n if (pingResult === hasTimedOut) {\n throw new Error('The Snaps execution environment failed to start.');\n }\n\n const rpcStream = job.streams.rpc;\n\n this.setupSnapProvider(snapId, rpcStream);\n\n const remainingTime = timer.remaining;\n\n const result = await withTimeout(\n this.command(job.id, {\n jsonrpc: '2.0',\n method: 'executeSnap',\n params: { snapId, sourceCode, endowments },\n id: nanoid(),\n }),\n remainingTime,\n );\n\n if (result === hasTimedOut) {\n throw new Error(`${snapId} failed to start.`);\n }\n\n this.#createSnapHooks(snapId, job.id);\n return result as string;\n }\n\n // Cannot be hash private yet because of tests.\n private async command(\n jobId: string,\n message: JsonRpcRequest,\n ): Promise<Json | undefined> {\n assertIsJsonRpcRequest(message);\n\n const job = this.jobs.get(jobId);\n if (!job) {\n throw new Error(`Job with id \"${jobId}\" not found.`);\n }\n\n log('Parent: Sending Command', message);\n const response: PendingJsonRpcResponse<Json> = await job.rpcEngine.handle(\n message,\n );\n\n if (response.error) {\n throw new JsonRpcError(\n response.error.code,\n response.error.message,\n response.error.data,\n );\n }\n\n return response.result;\n }\n\n #removeSnapHooks(snapId: string) {\n this.#snapRpcHooks.delete(snapId);\n }\n\n #createSnapHooks(snapId: string, workerId: string) {\n const rpcHook = async ({ origin, handler, request }: SnapRpcHookArgs) => {\n return await this.command(workerId, {\n id: nanoid(),\n jsonrpc: '2.0',\n method: 'snapRpc',\n params: {\n origin,\n handler,\n request: request as JsonRpcRequest,\n target: snapId,\n },\n });\n };\n\n this.#snapRpcHooks.set(snapId, rpcHook);\n }\n\n #mapSnapAndJob(snapId: string, jobId: string): void {\n this.#snapToJobMap.set(snapId, jobId);\n this.#jobToSnapMap.set(jobId, snapId);\n }\n\n #removeSnapAndJobMapping(jobId: string): void {\n const snapId = this.#jobToSnapMap.get(jobId);\n if (!snapId) {\n throw new Error(`job: \"${jobId}\" has no mapped snap.`);\n }\n\n this.#jobToSnapMap.delete(jobId);\n this.#snapToJobMap.delete(snapId);\n this.#removeSnapHooks(snapId);\n }\n\n /**\n * Handle RPC request.\n *\n * @param snapId - The ID of the recipient snap.\n * @param options - Bag of options to pass to the RPC handler.\n * @returns Promise that can handle the request.\n */\n public async handleRpcRequest(\n snapId: string,\n options: SnapRpcHookArgs,\n ): Promise<unknown> {\n const rpcRequestHandler = this.getRpcRequestHandler(snapId);\n\n if (!rpcRequestHandler) {\n throw new Error(\n `Snap execution service returned no RPC handler for running snap \"${snapId}\".`,\n );\n }\n\n return rpcRequestHandler(options);\n }\n}\n\n/**\n * Sets up stream multiplexing for the given stream.\n *\n * @param connectionStream - The stream to mux.\n * @param streamName - The name of the stream, for identification in errors.\n * @returns The multiplexed stream.\n */\nexport function setupMultiplex(\n connectionStream: Duplex,\n streamName: string,\n): ObjectMultiplex {\n const mux = new ObjectMultiplex();\n pipeline(connectionStream, mux, connectionStream, (error) => {\n if (error) {\n streamName\n ? logError(`\"${streamName}\" stream failure.`, error)\n : logError(error);\n }\n });\n return mux;\n}\n"],"mappings":"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","names":[]}
@@ -19,10 +19,11 @@ var _chunkNXZVKBSVjs = require('./chunk-NXZVKBSV.js');
19
19
 
20
20
 
21
21
 
22
- var _chunkXE5IWVNVjs = require('./chunk-XE5IWVNV.js');
23
22
 
23
+ var _chunk4DPX4O3Tjs = require('./chunk-4DPX4O3T.js');
24
24
 
25
- var _chunkNOLPMHXSjs = require('./chunk-NOLPMHXS.js');
25
+
26
+ var _chunkBOFPNIRXjs = require('./chunk-BOFPNIRX.js');
26
27
 
27
28
 
28
29
 
@@ -116,7 +117,7 @@ function truncateSnap(snap) {
116
117
  return truncatedSnap;
117
118
  }
118
119
  var name = "SnapController";
119
- var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _maxInitTime, _encryptor, _getMnemonic, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
120
+ var _closeAllConnections, _dynamicPermissions, _environmentEndowmentPermissions, _excludedPermissions, _featureFlags, _fetchFunction, _idleTimeCheckInterval, _maxIdleTime, _encryptor, _getMnemonic, _detectSnapLocation, _snapsRuntimeData, _rollbackSnapshots, _timeoutForLastRequestStatus, _statusMachine, _initializeStateMachine, initializeStateMachine_fn, _registerMessageHandlers, registerMessageHandlers_fn, _handlePreinstalledSnaps, handlePreinstalledSnaps_fn, _pollForLastRequestStatus, pollForLastRequestStatus_fn, _blockSnap, blockSnap_fn, _unblockSnap, unblockSnap_fn, _assertIsInstallAllowed, assertIsInstallAllowed_fn, _stopSnapsLastRequestPastMax, stopSnapsLastRequestPastMax_fn, _transition, transition_fn, _terminateSnap, terminateSnap_fn, _getSnapEncryptionKey, getSnapEncryptionKey_fn, _decryptSnapState, decryptSnapState_fn, _encryptSnapState, encryptSnapState_fn, _handleInitialConnections, handleInitialConnections_fn, _addSnapToSubject, addSnapToSubject_fn, _removeSnapFromSubjects, removeSnapFromSubjects_fn, _revokeAllSnapPermissions, revokeAllSnapPermissions_fn, _createApproval, createApproval_fn, _updateApproval, updateApproval_fn, _resolveAllowlistVersion, resolveAllowlistVersion_fn, _add, add_fn, _startSnap, startSnap_fn, _getEndowments, getEndowments_fn, _set, set_fn, _validateSnapPermissions, validateSnapPermissions_fn, _getExecutionTimeout, getExecutionTimeout_fn, _getRpcRequestHandler, getRpcRequestHandler_fn, _createInterface, createInterface_fn, _assertInterfaceExists, assertInterfaceExists_fn, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn, _getRollbackSnapshot, getRollbackSnapshot_fn, _createRollbackSnapshot, createRollbackSnapshot_fn, _rollbackSnap, rollbackSnap_fn, _rollbackSnaps, rollbackSnaps_fn, _getRuntime, getRuntime_fn, _getRuntimeExpect, getRuntimeExpect_fn, _setupRuntime, setupRuntime_fn, _calculatePermissionsChange, calculatePermissionsChange_fn, _updatePermissions, updatePermissions_fn, _isValidUpdate, isValidUpdate_fn, _callLifecycleHook, callLifecycleHook_fn;
120
121
  var SnapController = class extends _basecontroller.BaseController {
121
122
  constructor({
122
123
  closeAllConnections,
@@ -128,7 +129,6 @@ var SnapController = class extends _basecontroller.BaseController {
128
129
  idleTimeCheckInterval = _utils.inMilliseconds.call(void 0, 5, _utils.Duration.Second),
129
130
  maxIdleTime = _utils.inMilliseconds.call(void 0, 30, _utils.Duration.Second),
130
131
  maxRequestTime = _utils.inMilliseconds.call(void 0, 60, _utils.Duration.Second),
131
- maxInitTime = _utils.inMilliseconds.call(void 0, 60, _utils.Duration.Second),
132
132
  fetchFunction = globalThis.fetch.bind(globalThis),
133
133
  featureFlags = {},
134
134
  detectSnapLocation: detectSnapLocationFunction = _chunkPT22IXNSjs.detectSnapLocation,
@@ -418,7 +418,7 @@ var SnapController = class extends _basecontroller.BaseController {
418
418
  * to return false in that scenario.
419
419
  *
420
420
  * @param snapId - The snap id.
421
- * @param newVersionRange - The new version range being requsted.
421
+ * @param newVersionRange - The new version range being requested.
422
422
  * @returns `true` if validation checks pass and `false` if they do not.
423
423
  */
424
424
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _isValidUpdate);
@@ -441,7 +441,6 @@ var SnapController = class extends _basecontroller.BaseController {
441
441
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _fetchFunction, void 0);
442
442
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _idleTimeCheckInterval, void 0);
443
443
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _maxIdleTime, void 0);
444
- _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _maxInitTime, void 0);
445
444
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _encryptor, void 0);
446
445
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _getMnemonic, void 0);
447
446
  _chunkEXN2TFDJjs.__privateAdd.call(void 0, this, _detectSnapLocation, void 0);
@@ -458,7 +457,6 @@ var SnapController = class extends _basecontroller.BaseController {
458
457
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _idleTimeCheckInterval, idleTimeCheckInterval);
459
458
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _maxIdleTime, maxIdleTime);
460
459
  this.maxRequestTime = maxRequestTime;
461
- _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _maxInitTime, maxInitTime);
462
460
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _detectSnapLocation, detectSnapLocationFunction);
463
461
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _encryptor, encryptor);
464
462
  _chunkEXN2TFDJjs.__privateSet.call(void 0, this, _getMnemonic, getMnemonic);
@@ -625,15 +623,20 @@ var SnapController = class extends _basecontroller.BaseController {
625
623
  if (!runtime) {
626
624
  throw new Error(`The snap "${snapId}" is not running.`);
627
625
  }
628
- runtime.lastRequest = null;
629
- runtime.pendingInboundRequests = [];
630
- runtime.pendingOutboundRequests = 0;
626
+ if (runtime.stopping) {
627
+ return;
628
+ }
629
+ runtime.stopping = true;
631
630
  try {
632
631
  if (this.isRunning(snapId)) {
633
632
  (_a = _chunkEXN2TFDJjs.__privateGet.call(void 0, this, _closeAllConnections)) == null ? void 0 : _a.call(this, snapId);
634
633
  await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _terminateSnap, terminateSnap_fn).call(this, snapId);
635
634
  }
636
635
  } finally {
636
+ runtime.lastRequest = null;
637
+ runtime.pendingInboundRequests = [];
638
+ runtime.pendingOutboundRequests = 0;
639
+ runtime.stopping = false;
637
640
  if (this.isRunning(snapId)) {
638
641
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _transition, transition_fn).call(this, snapId, statusEvent);
639
642
  }
@@ -1162,7 +1165,7 @@ var SnapController = class extends _basecontroller.BaseController {
1162
1165
  );
1163
1166
  const snap = this.getExpect(snapId);
1164
1167
  const oldManifest = snap.manifest;
1165
- const newSnap = await _chunkXE5IWVNVjs.fetchSnap.call(void 0, snapId, location);
1168
+ const newSnap = await _chunk4DPX4O3Tjs.fetchSnap.call(void 0, snapId, location);
1166
1169
  const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
1167
1170
  const manifest = manifestFile.result;
1168
1171
  const newVersion = manifest.version;
@@ -1410,7 +1413,6 @@ _featureFlags = new WeakMap();
1410
1413
  _fetchFunction = new WeakMap();
1411
1414
  _idleTimeCheckInterval = new WeakMap();
1412
1415
  _maxIdleTime = new WeakMap();
1413
- _maxInitTime = new WeakMap();
1414
1416
  _encryptor = new WeakMap();
1415
1417
  _getMnemonic = new WeakMap();
1416
1418
  _detectSnapLocation = new WeakMap();
@@ -1698,6 +1700,10 @@ transition_fn = function(snapId, event) {
1698
1700
  _terminateSnap = new WeakSet();
1699
1701
  terminateSnap_fn = async function(snapId) {
1700
1702
  await this.messagingSystem.call("ExecutionService:terminateSnap", snapId);
1703
+ await new Promise((resolve) => setTimeout(resolve, 1));
1704
+ const runtime = _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _getRuntimeExpect, getRuntimeExpect_fn).call(this, snapId);
1705
+ runtime.pendingInboundRequests.filter((pendingRequest) => pendingRequest.timer.status !== "finished").forEach((pendingRequest) => pendingRequest.timer.finish());
1706
+ await new Promise((resolve) => setTimeout(resolve, 1));
1701
1707
  this.messagingSystem.publish(
1702
1708
  "SnapController:snapTerminated",
1703
1709
  this.getTruncatedExpect(snapId)
@@ -1767,7 +1773,7 @@ encryptSnapState_fn = async function(snapId, state) {
1767
1773
  _handleInitialConnections = new WeakSet();
1768
1774
  handleInitialConnections_fn = function(snapId, previousInitialConnections, initialConnections) {
1769
1775
  if (previousInitialConnections) {
1770
- const revokedInitialConnections = _chunkXE5IWVNVjs.setDiff.call(void 0,
1776
+ const revokedInitialConnections = _chunk4DPX4O3Tjs.setDiff.call(void 0,
1771
1777
  previousInitialConnections,
1772
1778
  initialConnections
1773
1779
  );
@@ -1889,7 +1895,7 @@ add_fn = async function(args) {
1889
1895
  if (!runtime.installPromise) {
1890
1896
  _chunkNXZVKBSVjs.log.call(void 0, `Adding snap: ${snapId}`);
1891
1897
  runtime.installPromise = (async () => {
1892
- const fetchedSnap = await _chunkXE5IWVNVjs.fetchSnap.call(void 0, snapId, location);
1898
+ const fetchedSnap = await _chunk4DPX4O3Tjs.fetchSnap.call(void 0, snapId, location);
1893
1899
  const manifest = fetchedSnap.manifest.result;
1894
1900
  if (!_utils.satisfiesVersionRange.call(void 0, manifest.version, versionRange)) {
1895
1901
  throw new Error(
@@ -1923,16 +1929,13 @@ startSnap_fn = async function(snapData) {
1923
1929
  }
1924
1930
  try {
1925
1931
  const runtime = _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _getRuntimeExpect, getRuntimeExpect_fn).call(this, snapId);
1926
- const result = await _chunkXE5IWVNVjs.withTimeout.call(void 0,
1927
- this.messagingSystem.call("ExecutionService:executeSnap", {
1932
+ const result = await this.messagingSystem.call(
1933
+ "ExecutionService:executeSnap",
1934
+ {
1928
1935
  ...snapData,
1929
1936
  endowments: await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _getEndowments, getEndowments_fn).call(this, snapId)
1930
- }),
1931
- _chunkEXN2TFDJjs.__privateGet.call(void 0, this, _maxInitTime)
1937
+ }
1932
1938
  );
1933
- if (result === _chunkXE5IWVNVjs.hasTimedOut) {
1934
- throw new Error(`${snapId} failed to start.`);
1935
- }
1936
1939
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _transition, transition_fn).call(this, snapId, _snapsutils.SnapStatusEvents.Start);
1937
1940
  runtime.lastRequest = Date.now();
1938
1941
  return result;
@@ -2137,7 +2140,7 @@ getRpcRequestHandler_fn = function(snapId) {
2137
2140
  }
2138
2141
  }
2139
2142
  }
2140
- const timer = new (0, _chunkNOLPMHXSjs.Timer)(timeout);
2143
+ const timer = new (0, _chunkBOFPNIRXjs.Timer)(timeout);
2141
2144
  _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _recordSnapRpcRequestStart, recordSnapRpcRequestStart_fn).call(this, snapId, request.id, timer);
2142
2145
  const handleRpcRequestPromise = this.messagingSystem.call(
2143
2146
  "ExecutionService:handleRpcRequest",
@@ -2145,22 +2148,23 @@ getRpcRequestHandler_fn = function(snapId) {
2145
2148
  { origin, handler: handlerType, request }
2146
2149
  );
2147
2150
  try {
2148
- const result = await _chunkXE5IWVNVjs.withTimeout.call(void 0, handleRpcRequestPromise, timer);
2149
- if (result === _chunkXE5IWVNVjs.hasTimedOut) {
2151
+ const result = await _chunk4DPX4O3Tjs.withTimeout.call(void 0, handleRpcRequestPromise, timer);
2152
+ if (result === _chunk4DPX4O3Tjs.hasTimedOut) {
2150
2153
  throw new Error(
2151
2154
  `${snapId} failed to respond to the request in time.`
2152
2155
  );
2153
2156
  }
2154
2157
  await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _assertSnapRpcRequestResult, assertSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2155
- return _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2158
+ const transformedResult = await _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _transformSnapRpcRequestResult, transformSnapRpcRequestResult_fn).call(this, snapId, handlerType, result);
2159
+ _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2160
+ return transformedResult;
2156
2161
  } catch (error) {
2162
+ _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2157
2163
  const [jsonRpcError, handled] = _snapsutils.unwrapError.call(void 0, error);
2158
2164
  if (!handled) {
2159
2165
  await this.stopSnap(snapId, _snapsutils.SnapStatusEvents.Crash);
2160
2166
  }
2161
2167
  throw jsonRpcError;
2162
- } finally {
2163
- _chunkEXN2TFDJjs.__privateMethod.call(void 0, this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish_fn).call(this, snapId, request.id);
2164
2168
  }
2165
2169
  };
2166
2170
  runtime.rpcHandler = rpcHandler;
@@ -2344,7 +2348,8 @@ setupRuntime_fn = function(snapId) {
2344
2348
  activeReferences: 0,
2345
2349
  pendingInboundRequests: [],
2346
2350
  pendingOutboundRequests: 0,
2347
- interpreter
2351
+ interpreter,
2352
+ stopping: false
2348
2353
  });
2349
2354
  };
2350
2355
  _calculatePermissionsChange = new WeakSet();
@@ -2353,9 +2358,18 @@ calculatePermissionsChange_fn = function(snapId, desiredPermissionsSet) {
2353
2358
  "PermissionController:getPermissions",
2354
2359
  snapId
2355
2360
  ) ?? {};
2356
- const newPermissions = _chunkXE5IWVNVjs.setDiff.call(void 0, desiredPermissionsSet, oldPermissions);
2357
- const unusedPermissions = _chunkXE5IWVNVjs.setDiff.call(void 0, oldPermissions, desiredPermissionsSet);
2358
- const approvedPermissions = _chunkXE5IWVNVjs.setDiff.call(void 0, oldPermissions, unusedPermissions);
2361
+ const newPermissions = _chunk4DPX4O3Tjs.permissionsDiff.call(void 0,
2362
+ desiredPermissionsSet,
2363
+ oldPermissions
2364
+ );
2365
+ const unusedPermissions = _chunk4DPX4O3Tjs.permissionsDiff.call(void 0,
2366
+ oldPermissions,
2367
+ desiredPermissionsSet
2368
+ );
2369
+ const approvedPermissions = _chunk4DPX4O3Tjs.permissionsDiff.call(void 0,
2370
+ oldPermissions,
2371
+ unusedPermissions
2372
+ );
2359
2373
  return { newPermissions, unusedPermissions, approvedPermissions };
2360
2374
  };
2361
2375
  _updatePermissions = new WeakSet();
@@ -2420,4 +2434,4 @@ callLifecycleHook_fn = async function(snapId, handler) {
2420
2434
 
2421
2435
 
2422
2436
  exports.controllerName = controllerName; exports.SNAP_APPROVAL_INSTALL = SNAP_APPROVAL_INSTALL; exports.SNAP_APPROVAL_UPDATE = SNAP_APPROVAL_UPDATE; exports.SNAP_APPROVAL_RESULT = SNAP_APPROVAL_RESULT; exports.SnapController = SnapController;
2423
- //# sourceMappingURL=chunk-CJN25EXL.js.map
2437
+ //# sourceMappingURL=chunk-JMP6XYRL.js.map