@sentry/node 8.0.0 → 8.1.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 (215) hide show
  1. package/cjs/cron/common.js +56 -0
  2. package/cjs/cron/common.js.map +1 -0
  3. package/cjs/cron/cron.js +112 -0
  4. package/cjs/cron/cron.js.map +1 -0
  5. package/cjs/cron/index.js +15 -0
  6. package/cjs/cron/index.js.map +1 -0
  7. package/cjs/cron/node-cron.js +72 -0
  8. package/cjs/cron/node-cron.js.map +1 -0
  9. package/cjs/cron/node-schedule.js +69 -0
  10. package/cjs/cron/node-schedule.js.map +1 -0
  11. package/cjs/debug-build.js +11 -0
  12. package/cjs/debug-build.js.map +1 -0
  13. package/cjs/index.js +85 -4018
  14. package/cjs/index.js.map +1 -1
  15. package/cjs/integrations/anr/index.js +211 -0
  16. package/cjs/integrations/anr/index.js.map +1 -0
  17. package/cjs/integrations/console.js +40 -0
  18. package/cjs/integrations/console.js.map +1 -0
  19. package/cjs/integrations/context.js +435 -0
  20. package/cjs/integrations/context.js.map +1 -0
  21. package/cjs/integrations/contextlines.js +137 -0
  22. package/cjs/integrations/contextlines.js.map +1 -0
  23. package/cjs/integrations/http.js +161 -0
  24. package/cjs/integrations/http.js.map +1 -0
  25. package/cjs/integrations/local-variables/common.js +87 -0
  26. package/cjs/integrations/local-variables/common.js.map +1 -0
  27. package/cjs/integrations/local-variables/index.js +12 -0
  28. package/cjs/integrations/local-variables/index.js.map +1 -0
  29. package/cjs/integrations/local-variables/local-variables-async.js +149 -0
  30. package/cjs/integrations/local-variables/local-variables-async.js.map +1 -0
  31. package/cjs/integrations/local-variables/local-variables-sync.js +376 -0
  32. package/cjs/integrations/local-variables/local-variables-sync.js.map +1 -0
  33. package/cjs/integrations/modules.js +99 -0
  34. package/cjs/integrations/modules.js.map +1 -0
  35. package/cjs/integrations/node-fetch.js +81 -0
  36. package/cjs/integrations/node-fetch.js.map +1 -0
  37. package/cjs/integrations/onuncaughtexception.js +135 -0
  38. package/cjs/integrations/onuncaughtexception.js.map +1 -0
  39. package/cjs/integrations/onunhandledrejection.js +90 -0
  40. package/cjs/integrations/onunhandledrejection.js.map +1 -0
  41. package/cjs/integrations/spotlight.js +109 -0
  42. package/cjs/integrations/spotlight.js.map +1 -0
  43. package/cjs/integrations/tracing/connect.js +41 -0
  44. package/cjs/integrations/tracing/connect.js.map +1 -0
  45. package/cjs/integrations/tracing/express.js +127 -0
  46. package/cjs/integrations/tracing/express.js.map +1 -0
  47. package/cjs/integrations/tracing/fastify.js +84 -0
  48. package/cjs/integrations/tracing/fastify.js.map +1 -0
  49. package/cjs/integrations/tracing/graphql.js +32 -0
  50. package/cjs/integrations/tracing/graphql.js.map +1 -0
  51. package/cjs/integrations/tracing/hapi/index.js +106 -0
  52. package/cjs/integrations/tracing/hapi/index.js.map +1 -0
  53. package/cjs/integrations/tracing/index.js +43 -0
  54. package/cjs/integrations/tracing/index.js.map +1 -0
  55. package/cjs/integrations/tracing/koa.js +60 -0
  56. package/cjs/integrations/tracing/koa.js.map +1 -0
  57. package/cjs/integrations/tracing/mongo.js +31 -0
  58. package/cjs/integrations/tracing/mongo.js.map +1 -0
  59. package/cjs/integrations/tracing/mongoose.js +31 -0
  60. package/cjs/integrations/tracing/mongoose.js.map +1 -0
  61. package/cjs/integrations/tracing/mysql.js +24 -0
  62. package/cjs/integrations/tracing/mysql.js.map +1 -0
  63. package/cjs/integrations/tracing/mysql2.js +31 -0
  64. package/cjs/integrations/tracing/mysql2.js.map +1 -0
  65. package/cjs/integrations/tracing/nest.js +69 -0
  66. package/cjs/integrations/tracing/nest.js.map +1 -0
  67. package/cjs/integrations/tracing/postgres.js +32 -0
  68. package/cjs/integrations/tracing/postgres.js.map +1 -0
  69. package/cjs/integrations/tracing/prisma.js +48 -0
  70. package/cjs/integrations/tracing/prisma.js.map +1 -0
  71. package/cjs/integrations/tracing/redis.js +29 -0
  72. package/cjs/integrations/tracing/redis.js.map +1 -0
  73. package/cjs/nodeVersion.js +10 -0
  74. package/cjs/nodeVersion.js.map +1 -0
  75. package/cjs/otel/contextManager.js +16 -0
  76. package/cjs/otel/contextManager.js.map +1 -0
  77. package/cjs/proxy/base.js +127 -0
  78. package/cjs/proxy/base.js.map +1 -0
  79. package/cjs/proxy/index.js +178 -0
  80. package/cjs/proxy/index.js.map +1 -0
  81. package/cjs/proxy/parse-proxy-response.js +104 -0
  82. package/cjs/proxy/parse-proxy-response.js.map +1 -0
  83. package/cjs/sdk/api.js +45 -0
  84. package/cjs/sdk/api.js.map +1 -0
  85. package/cjs/sdk/client.js +63 -0
  86. package/cjs/sdk/client.js.map +1 -0
  87. package/cjs/sdk/init.js +318 -0
  88. package/cjs/sdk/init.js.map +1 -0
  89. package/cjs/sdk/initOtel.js +58 -0
  90. package/cjs/sdk/initOtel.js.map +1 -0
  91. package/cjs/sdk/scope.js +18 -0
  92. package/cjs/sdk/scope.js.map +1 -0
  93. package/cjs/transports/http.js +163 -0
  94. package/cjs/transports/http.js.map +1 -0
  95. package/cjs/utils/addOriginToSpan.js +11 -0
  96. package/cjs/utils/addOriginToSpan.js.map +1 -0
  97. package/cjs/utils/errorhandling.js +44 -0
  98. package/cjs/utils/errorhandling.js.map +1 -0
  99. package/cjs/utils/getRequestUrl.js +18 -0
  100. package/cjs/utils/getRequestUrl.js.map +1 -0
  101. package/cjs/utils/module.js +62 -0
  102. package/cjs/utils/module.js.map +1 -0
  103. package/esm/cron/common.js +54 -0
  104. package/esm/cron/common.js.map +1 -0
  105. package/esm/cron/cron.js +110 -0
  106. package/esm/cron/cron.js.map +1 -0
  107. package/esm/cron/index.js +13 -0
  108. package/esm/cron/index.js.map +1 -0
  109. package/esm/cron/node-cron.js +67 -0
  110. package/esm/cron/node-cron.js.map +1 -0
  111. package/esm/cron/node-schedule.js +64 -0
  112. package/esm/cron/node-schedule.js.map +1 -0
  113. package/esm/debug-build.js +9 -0
  114. package/esm/debug-build.js.map +1 -0
  115. package/esm/index.js +35 -3973
  116. package/esm/index.js.map +1 -1
  117. package/esm/integrations/anr/index.js +204 -0
  118. package/esm/integrations/anr/index.js.map +1 -0
  119. package/esm/integrations/anr/worker-script.js +2 -2
  120. package/esm/integrations/console.js +38 -0
  121. package/esm/integrations/console.js.map +1 -0
  122. package/esm/integrations/context.js +427 -0
  123. package/esm/integrations/context.js.map +1 -0
  124. package/esm/integrations/contextlines.js +131 -0
  125. package/esm/integrations/contextlines.js.map +1 -0
  126. package/esm/integrations/http.js +156 -0
  127. package/esm/integrations/http.js.map +1 -0
  128. package/esm/integrations/local-variables/common.js +81 -0
  129. package/esm/integrations/local-variables/common.js.map +1 -0
  130. package/esm/integrations/local-variables/index.js +10 -0
  131. package/esm/integrations/local-variables/index.js.map +1 -0
  132. package/esm/integrations/local-variables/local-variables-async.js +143 -0
  133. package/esm/integrations/local-variables/local-variables-async.js.map +1 -0
  134. package/esm/integrations/local-variables/local-variables-sync.js +370 -0
  135. package/esm/integrations/local-variables/local-variables-sync.js.map +1 -0
  136. package/esm/integrations/local-variables/worker-script.js +1 -1
  137. package/esm/integrations/modules.js +97 -0
  138. package/esm/integrations/modules.js.map +1 -0
  139. package/esm/integrations/node-fetch.js +79 -0
  140. package/esm/integrations/node-fetch.js.map +1 -0
  141. package/esm/integrations/onuncaughtexception.js +132 -0
  142. package/esm/integrations/onuncaughtexception.js.map +1 -0
  143. package/esm/integrations/onunhandledrejection.js +87 -0
  144. package/esm/integrations/onunhandledrejection.js.map +1 -0
  145. package/esm/integrations/spotlight.js +106 -0
  146. package/esm/integrations/spotlight.js.map +1 -0
  147. package/esm/integrations/tracing/connect.js +38 -0
  148. package/esm/integrations/tracing/connect.js.map +1 -0
  149. package/esm/integrations/tracing/express.js +120 -0
  150. package/esm/integrations/tracing/express.js.map +1 -0
  151. package/esm/integrations/tracing/fastify.js +78 -0
  152. package/esm/integrations/tracing/fastify.js.map +1 -0
  153. package/esm/integrations/tracing/graphql.js +30 -0
  154. package/esm/integrations/tracing/graphql.js.map +1 -0
  155. package/esm/integrations/tracing/hapi/index.js +99 -0
  156. package/esm/integrations/tracing/hapi/index.js.map +1 -0
  157. package/esm/integrations/tracing/index.js +41 -0
  158. package/esm/integrations/tracing/index.js.map +1 -0
  159. package/esm/integrations/tracing/koa.js +57 -0
  160. package/esm/integrations/tracing/koa.js.map +1 -0
  161. package/esm/integrations/tracing/mongo.js +29 -0
  162. package/esm/integrations/tracing/mongo.js.map +1 -0
  163. package/esm/integrations/tracing/mongoose.js +29 -0
  164. package/esm/integrations/tracing/mongoose.js.map +1 -0
  165. package/esm/integrations/tracing/mysql.js +22 -0
  166. package/esm/integrations/tracing/mysql.js.map +1 -0
  167. package/esm/integrations/tracing/mysql2.js +29 -0
  168. package/esm/integrations/tracing/mysql2.js.map +1 -0
  169. package/esm/integrations/tracing/nest.js +63 -0
  170. package/esm/integrations/tracing/nest.js.map +1 -0
  171. package/esm/integrations/tracing/postgres.js +30 -0
  172. package/esm/integrations/tracing/postgres.js.map +1 -0
  173. package/esm/integrations/tracing/prisma.js +43 -0
  174. package/esm/integrations/tracing/prisma.js.map +1 -0
  175. package/esm/integrations/tracing/redis.js +27 -0
  176. package/esm/integrations/tracing/redis.js.map +1 -0
  177. package/esm/nodeVersion.js +7 -0
  178. package/esm/nodeVersion.js.map +1 -0
  179. package/esm/otel/contextManager.js +14 -0
  180. package/esm/otel/contextManager.js.map +1 -0
  181. package/esm/proxy/base.js +122 -0
  182. package/esm/proxy/base.js.map +1 -0
  183. package/esm/proxy/index.js +172 -0
  184. package/esm/proxy/index.js.map +1 -0
  185. package/esm/proxy/parse-proxy-response.js +102 -0
  186. package/esm/proxy/parse-proxy-response.js.map +1 -0
  187. package/esm/sdk/api.js +42 -0
  188. package/esm/sdk/api.js.map +1 -0
  189. package/esm/sdk/client.js +58 -0
  190. package/esm/sdk/client.js.map +1 -0
  191. package/esm/sdk/init.js +312 -0
  192. package/esm/sdk/init.js.map +1 -0
  193. package/esm/sdk/initOtel.js +55 -0
  194. package/esm/sdk/initOtel.js.map +1 -0
  195. package/esm/sdk/scope.js +16 -0
  196. package/esm/sdk/scope.js.map +1 -0
  197. package/esm/transports/http.js +158 -0
  198. package/esm/transports/http.js.map +1 -0
  199. package/esm/utils/addOriginToSpan.js +9 -0
  200. package/esm/utils/addOriginToSpan.js.map +1 -0
  201. package/esm/utils/errorhandling.js +42 -0
  202. package/esm/utils/errorhandling.js.map +1 -0
  203. package/esm/utils/getRequestUrl.js +16 -0
  204. package/esm/utils/getRequestUrl.js.map +1 -0
  205. package/esm/utils/module.js +60 -0
  206. package/esm/utils/module.js.map +1 -0
  207. package/package.json +16 -16
  208. package/types/index.d.ts +2 -2
  209. package/types/index.d.ts.map +1 -1
  210. package/types/integrations/tracing/hapi/index.d.ts.map +1 -1
  211. package/types/integrations/tracing/koa.d.ts.map +1 -1
  212. package/types/sdk/init.d.ts +4 -0
  213. package/types/sdk/init.d.ts.map +1 -1
  214. package/types-ts3.8/index.d.ts +2 -2
  215. package/types-ts3.8/sdk/init.d.ts +4 -0
@@ -0,0 +1,204 @@
1
+ import { _optionalChain, _optionalChainDelete } from '@sentry/utils';
2
+ import { defineIntegration, getGlobalScope, mergeScopeData, getIsolationScope, getCurrentScope } from '@sentry/core';
3
+ import { logger, GLOBAL_OBJ } from '@sentry/utils';
4
+ import * as inspector from 'inspector';
5
+ import { Worker } from 'worker_threads';
6
+ import { NODE_VERSION } from '../../nodeVersion.js';
7
+
8
+ // This string is a placeholder that gets overwritten with the worker code.
9
+ const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA4LjEuMCAoZDMxZDdhMCkgfCBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0ICovCmltcG9ydHtTZXNzaW9uIGFzIHR9ZnJvbSJpbnNwZWN0b3IiO2ltcG9ydHtwYXJlbnRQb3J0IGFzIGUsd29ya2VyRGF0YSBhcyBufWZyb20id29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyByLHNlcCBhcyBvfWZyb20icGF0aCI7aW1wb3J0KmFzIHMgZnJvbSJub2RlOmh0dHAiO2ltcG9ydCphcyBpIGZyb20ibm9kZTpodHRwcyI7aW1wb3J0e1JlYWRhYmxlIGFzIGN9ZnJvbSJzdHJlYW0iO2ltcG9ydHtjcmVhdGVHemlwIGFzIHV9ZnJvbSJ6bGliIjtpbXBvcnQqYXMgYSBmcm9tIm5ldCI7aW1wb3J0KmFzIGYgZnJvbSJ0bHMiO2ltcG9ydCphcyBoIGZyb20iaHR0cCI7Y29uc3QgcD1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO2Z1bmN0aW9uIGwodCxlKXtyZXR1cm4gcC5jYWxsKHQpPT09YFtvYmplY3QgJHtlfV1gfWZ1bmN0aW9uIGQodCl7cmV0dXJuIGwodCwiT2JqZWN0Iil9ZnVuY3Rpb24gbSh0KXtyZXR1cm4gQm9vbGVhbih0JiZ0LnRoZW4mJiJmdW5jdGlvbiI9PXR5cGVvZiB0LnRoZW4pfWZ1bmN0aW9uIGcodCxlKXt0cnl7cmV0dXJuIHQgaW5zdGFuY2VvZiBlfWNhdGNoKHQpe3JldHVybiExfX1jb25zdCB5PWdsb2JhbFRoaXM7ZnVuY3Rpb24gYih0LGUsbil7Y29uc3Qgcj1ufHx5LG89ci5fX1NFTlRSWV9fPXIuX19TRU5UUllfX3x8e307cmV0dXJuIG9bdF18fChvW3RdPWUoKSl9Y29uc3Qgdj15LF89ODA7ZnVuY3Rpb24gdyh0LGUpe2NvbnN0IG49dCxyPVtdO2xldCBvLHMsaSxjLHU7aWYoIW58fCFuLnRhZ05hbWUpcmV0dXJuIiI7aWYodi5IVE1MRWxlbWVudCYmbiBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZuLmRhdGFzZXQpe2lmKG4uZGF0YXNldC5zZW50cnlDb21wb25lbnQpcmV0dXJuIG4uZGF0YXNldC5zZW50cnlDb21wb25lbnQ7aWYobi5kYXRhc2V0LnNlbnRyeUVsZW1lbnQpcmV0dXJuIG4uZGF0YXNldC5zZW50cnlFbGVtZW50fXIucHVzaChuLnRhZ05hbWUudG9Mb3dlckNhc2UoKSk7Y29uc3QgYT1lJiZlLmxlbmd0aD9lLmZpbHRlcigodD0+bi5nZXRBdHRyaWJ1dGUodCkpKS5tYXAoKHQ9Plt0LG4uZ2V0QXR0cmlidXRlKHQpXSkpOm51bGw7aWYoYSYmYS5sZW5ndGgpYS5mb3JFYWNoKCh0PT57ci5wdXNoKGBbJHt0WzBdfT0iJHt0WzFdfSJdYCl9KSk7ZWxzZSBpZihuLmlkJiZyLnB1c2goYCMke24uaWR9YCksbz1uLmNsYXNzTmFtZSxvJiZsKG8sIlN0cmluZyIpKWZvcihzPW8uc3BsaXQoL1xzKy8pLHU9MDt1PHMubGVuZ3RoO3UrKylyLnB1c2goYC4ke3NbdV19YCk7Y29uc3QgZj1bImFyaWEtbGFiZWwiLCJ0eXBlIiwibmFtZSIsInRpdGxlIiwiYWx0Il07Zm9yKHU9MDt1PGYubGVuZ3RoO3UrKylpPWZbdV0sYz1uLmdldEF0dHJpYnV0ZShpKSxjJiZyLnB1c2goYFske2l9PSIke2N9Il1gKTtyZXR1cm4gci5qb2luKCIiKX1jb25zdCBTPSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXywkPVsiZGVidWciLCJpbmZvIiwid2FybiIsImVycm9yIiwibG9nIiwiYXNzZXJ0IiwidHJhY2UiXSxFPXt9O2Z1bmN0aW9uIHgodCl7aWYoISgiY29uc29sZSJpbiB5KSlyZXR1cm4gdCgpO2NvbnN0IGU9eS5jb25zb2xlLG49e30scj1PYmplY3Qua2V5cyhFKTtyLmZvckVhY2goKHQ9Pntjb25zdCByPUVbdF07blt0XT1lW3RdLGVbdF09cn0pKTt0cnl7cmV0dXJuIHQoKX1maW5hbGx5e3IuZm9yRWFjaCgodD0+e2VbdF09blt0XX0pKX19Y29uc3QgTj1mdW5jdGlvbigpe2xldCB0PSExO2NvbnN0IGU9e2VuYWJsZTooKT0+e3Q9ITB9LGRpc2FibGU6KCk9Pnt0PSExfSxpc0VuYWJsZWQ6KCk9PnR9O3JldHVybiBTPyQuZm9yRWFjaCgobj0+e2Vbbl09KC4uLmUpPT57dCYmeCgoKCk9Pnt5LmNvbnNvbGVbbl0oYFNlbnRyeSBMb2dnZXIgWyR7bn1dOmAsLi4uZSl9KSl9fSkpOiQuZm9yRWFjaCgodD0+e2VbdF09KCk9Pnt9fSkpLGV9KCk7ZnVuY3Rpb24gayh0LGU9ITEpe2NvbnN0e2hvc3Q6bixwYXRoOnIscGFzczpvLHBvcnQ6cyxwcm9qZWN0SWQ6aSxwcm90b2NvbDpjLHB1YmxpY0tleTp1fT10O3JldHVybmAke2N9Oi8vJHt1fSR7ZSYmbz9gOiR7b31gOiIifUAke259JHtzP2A6JHtzfWA6IiJ9LyR7cj9gJHtyfS9gOnJ9JHtpfWB9Y2xhc3MgQyBleHRlbmRzIEVycm9ye2NvbnN0cnVjdG9yKHQsZT0id2FybiIpe3N1cGVyKHQpLHRoaXMubWVzc2FnZT10LHRoaXMubmFtZT1uZXcudGFyZ2V0LnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5uYW1lLE9iamVjdC5zZXRQcm90b3R5cGVPZih0aGlzLG5ldy50YXJnZXQucHJvdG90eXBlKSx0aGlzLmxvZ0xldmVsPWV9fWZ1bmN0aW9uIEQodCl7aWYoZnVuY3Rpb24odCl7c3dpdGNoKHAuY2FsbCh0KSl7Y2FzZSJbb2JqZWN0IEVycm9yXSI6Y2FzZSJbb2JqZWN0IEV4Y2VwdGlvbl0iOmNhc2UiW29iamVjdCBET01FeGNlcHRpb25dIjpyZXR1cm4hMDtkZWZhdWx0OnJldHVybiBnKHQsRXJyb3IpfX0odCkpcmV0dXJue21lc3NhZ2U6dC5tZXNzYWdlLG5hbWU6dC5uYW1lLHN0YWNrOnQuc3RhY2ssLi4uTyh0KX07aWYoZT10LCJ1bmRlZmluZWQiIT10eXBlb2YgRXZlbnQmJmcoZSxFdmVudCkpe2NvbnN0IGU9e3R5cGU6dC50eXBlLHRhcmdldDpUKHQudGFyZ2V0KSxjdXJyZW50VGFyZ2V0OlQodC5jdXJyZW50VGFyZ2V0KSwuLi5PKHQpfTtyZXR1cm4idW5kZWZpbmVkIiE9dHlwZW9mIEN1c3RvbUV2ZW50JiZnKHQsQ3VzdG9tRXZlbnQpJiYoZS5kZXRhaWw9dC5kZXRhaWwpLGV9cmV0dXJuIHQ7dmFyIGV9ZnVuY3Rpb24gVCh0KXt0cnl7cmV0dXJuIGU9dCwidW5kZWZpbmVkIiE9dHlwZW9mIEVsZW1lbnQmJmcoZSxFbGVtZW50KT9mdW5jdGlvbih0LGU9e30pe2lmKCF0KXJldHVybiI8dW5rbm93bj4iO3RyeXtsZXQgbj10O2NvbnN0IHI9NSxvPVtdO2xldCBzPTAsaT0wO2NvbnN0IGM9IiA+ICIsdT1jLmxlbmd0aDtsZXQgYTtjb25zdCBmPUFycmF5LmlzQXJyYXkoZSk/ZTplLmtleUF0dHJzLGg9IUFycmF5LmlzQXJyYXkoZSkmJmUubWF4U3RyaW5nTGVuZ3RofHxfO2Zvcig7biYmcysrPHImJihhPXcobixmKSwhKCJodG1sIj09PWF8fHM+MSYmaStvLmxlbmd0aCp1K2EubGVuZ3RoPj1oKSk7KW8ucHVzaChhKSxpKz1hLmxlbmd0aCxuPW4ucGFyZW50Tm9kZTtyZXR1cm4gby5yZXZlcnNlKCkuam9pbihjKX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In19KHQpOk9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KX1jYXRjaCh0KXtyZXR1cm4iPHVua25vd24+In12YXIgZX1mdW5jdGlvbiBPKHQpe2lmKCJvYmplY3QiPT10eXBlb2YgdCYmbnVsbCE9PXQpe2NvbnN0IGU9e307Zm9yKGNvbnN0IG4gaW4gdClPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodCxuKSYmKGVbbl09dFtuXSk7cmV0dXJuIGV9cmV0dXJue319ZnVuY3Rpb24gaih0KXtyZXR1cm4gUih0LG5ldyBNYXApfWZ1bmN0aW9uIFIodCxlKXtpZihmdW5jdGlvbih0KXtpZighZCh0KSlyZXR1cm4hMTt0cnl7Y29uc3QgZT1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCkuY29uc3RydWN0b3IubmFtZTtyZXR1cm4hZXx8Ik9iamVjdCI9PT1lfWNhdGNoKHQpe3JldHVybiEwfX0odCkpe2NvbnN0IG49ZS5nZXQodCk7aWYodm9pZCAwIT09bilyZXR1cm4gbjtjb25zdCByPXt9O2Uuc2V0KHQscik7Zm9yKGNvbnN0IG4gb2YgT2JqZWN0LmtleXModCkpdm9pZCAwIT09dFtuXSYmKHJbbl09Uih0W25dLGUpKTtyZXR1cm4gcn1pZihBcnJheS5pc0FycmF5KHQpKXtjb25zdCBuPWUuZ2V0KHQpO2lmKHZvaWQgMCE9PW4pcmV0dXJuIG47Y29uc3Qgcj1bXTtyZXR1cm4gZS5zZXQodCxyKSx0LmZvckVhY2goKHQ9PntyLnB1c2goUih0LGUpKX0pKSxyfXJldHVybiB0fWNvbnN0IEE9NTAsST0iPyIsUD0vY2FwdHVyZU1lc3NhZ2V8Y2FwdHVyZUV4Y2VwdGlvbi87Y29uc3QgVT0iPGFub255bW91cz4iO2Z1bmN0aW9uIE0oKXtjb25zdCB0PXksZT10LmNyeXB0b3x8dC5tc0NyeXB0bztsZXQgbj0oKT0+MTYqTWF0aC5yYW5kb20oKTt0cnl7aWYoZSYmZS5yYW5kb21VVUlEKXJldHVybiBlLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csIiIpO2UmJmUuZ2V0UmFuZG9tVmFsdWVzJiYobj0oKT0+e2NvbnN0IHQ9bmV3IFVpbnQ4QXJyYXkoMSk7cmV0dXJuIGUuZ2V0UmFuZG9tVmFsdWVzKHQpLHRbMF19KX1jYXRjaCh0KXt9cmV0dXJuKFsxZTddKzFlMys0ZTMrOGUzKzFlMTEpLnJlcGxhY2UoL1swMThdL2csKHQ9Pih0XigxNSZuKCkpPj50LzQpLnRvU3RyaW5nKDE2KSkpfWZ1bmN0aW9uIEwodCxlPTEwMCxuPTEvMCl7dHJ5e3JldHVybiBCKCIiLHQsZSxuKX1jYXRjaCh0KXtyZXR1cm57RVJST1I6YCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9fX1mdW5jdGlvbiBCKHQsZSxuPTEvMCxyPTEvMCxvPWZ1bmN0aW9uKCl7Y29uc3QgdD0iZnVuY3Rpb24iPT10eXBlb2YgV2Vha1NldCxlPXQ/bmV3IFdlYWtTZXQ6W107cmV0dXJuW2Z1bmN0aW9uKG4pe2lmKHQpcmV0dXJuISFlLmhhcyhuKXx8KGUuYWRkKG4pLCExKTtmb3IobGV0IHQ9MDt0PGUubGVuZ3RoO3QrKylpZihlW3RdPT09bilyZXR1cm4hMDtyZXR1cm4gZS5wdXNoKG4pLCExfSxmdW5jdGlvbihuKXtpZih0KWUuZGVsZXRlKG4pO2Vsc2UgZm9yKGxldCB0PTA7dDxlLmxlbmd0aDt0KyspaWYoZVt0XT09PW4pe2Uuc3BsaWNlKHQsMSk7YnJlYWt9fV19KCkpe2NvbnN0W3MsaV09bztpZihudWxsPT1lfHxbIm51bWJlciIsImJvb2xlYW4iLCJzdHJpbmciXS5pbmNsdWRlcyh0eXBlb2YgZSkmJiFOdW1iZXIuaXNOYU4oZSkpcmV0dXJuIGU7Y29uc3QgYz1mdW5jdGlvbih0LGUpe3RyeXtpZigiZG9tYWluIj09PXQmJmUmJiJvYmplY3QiPT10eXBlb2YgZSYmZS50KXJldHVybiJbRG9tYWluXSI7aWYoImRvbWFpbkVtaXR0ZXIiPT09dClyZXR1cm4iW0RvbWFpbkVtaXR0ZXJdIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIGdsb2JhbCYmZT09PWdsb2JhbClyZXR1cm4iW0dsb2JhbF0iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2Ygd2luZG93JiZlPT09d2luZG93KXJldHVybiJbV2luZG93XSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBkb2N1bWVudCYmZT09PWRvY3VtZW50KXJldHVybiJbRG9jdW1lbnRdIjtpZigib2JqZWN0Ij09dHlwZW9mKG49ZSkmJm51bGwhPT1uJiYobi5fX2lzVnVlfHxuLm8pKXJldHVybiJbVnVlVmlld01vZGVsXSI7aWYoZnVuY3Rpb24odCl7cmV0dXJuIGQodCkmJiJuYXRpdmVFdmVudCJpbiB0JiYicHJldmVudERlZmF1bHQiaW4gdCYmInN0b3BQcm9wYWdhdGlvbiJpbiB0fShlKSlyZXR1cm4iW1N5bnRoZXRpY0V2ZW50XSI7aWYoIm51bWJlciI9PXR5cGVvZiBlJiZlIT1lKXJldHVybiJbTmFOXSI7aWYoImZ1bmN0aW9uIj09dHlwZW9mIGUpcmV0dXJuYFtGdW5jdGlvbjogJHtmdW5jdGlvbih0KXt0cnl7cmV0dXJuIHQmJiJmdW5jdGlvbiI9PXR5cGVvZiB0JiZ0Lm5hbWV8fFV9Y2F0Y2godCl7cmV0dXJuIFV9fShlKX1dYDtpZigic3ltYm9sIj09dHlwZW9mIGUpcmV0dXJuYFske1N0cmluZyhlKX1dYDtpZigiYmlnaW50Ij09dHlwZW9mIGUpcmV0dXJuYFtCaWdJbnQ6ICR7U3RyaW5nKGUpfV1gO2NvbnN0IHI9ZnVuY3Rpb24odCl7Y29uc3QgZT1PYmplY3QuZ2V0UHJvdG90eXBlT2YodCk7cmV0dXJuIGU/ZS5jb25zdHJ1Y3Rvci5uYW1lOiJudWxsIHByb3RvdHlwZSJ9KGUpO3JldHVybi9eSFRNTChcdyopRWxlbWVudCQvLnRlc3Qocik/YFtIVE1MRWxlbWVudDogJHtyfV1gOmBbb2JqZWN0ICR7cn1dYH1jYXRjaCh0KXtyZXR1cm5gKipub24tc2VyaWFsaXphYmxlKiogKCR7dH0pYH12YXIgbn0odCxlKTtpZighYy5zdGFydHNXaXRoKCJbb2JqZWN0ICIpKXJldHVybiBjO2lmKGUuX19zZW50cnlfc2tpcF9ub3JtYWxpemF0aW9uX18pcmV0dXJuIGU7Y29uc3QgdT0ibnVtYmVyIj09dHlwZW9mIGUuX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fP2UuX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fOm47aWYoMD09PXUpcmV0dXJuIGMucmVwbGFjZSgib2JqZWN0ICIsIiIpO2lmKHMoZSkpcmV0dXJuIltDaXJjdWxhciB+XSI7Y29uc3QgYT1lO2lmKGEmJiJmdW5jdGlvbiI9PXR5cGVvZiBhLnRvSlNPTil0cnl7cmV0dXJuIEIoIiIsYS50b0pTT04oKSx1LTEscixvKX1jYXRjaCh0KXt9Y29uc3QgZj1BcnJheS5pc0FycmF5KGUpP1tdOnt9O2xldCBoPTA7Y29uc3QgcD1EKGUpO2Zvcihjb25zdCB0IGluIHApe2lmKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocCx0KSljb250aW51ZTtpZihoPj1yKXtmW3RdPSJbTWF4UHJvcGVydGllcyB+XSI7YnJlYWt9Y29uc3QgZT1wW3RdO2ZbdF09Qih0LGUsdS0xLHIsbyksaCsrfXJldHVybiBpKGUpLGZ9ZnVuY3Rpb24gRyh0LGUpe2NvbnN0IG49ZS5yZXBsYWNlKC9cXC9nLCIvIikucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csIlxcJCYiKTtsZXQgcj10O3RyeXtyPWRlY29kZVVSSSh0KX1jYXRjaCh0KXt9cmV0dXJuIHIucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL3dlYnBhY2s6XC8/L2csIiIpLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtufS8qYCwiaWciKSwiYXBwOi8vLyIpfWNvbnN0IEo9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIHoodCl7Y29uc3QgZT1mdW5jdGlvbih0KXtjb25zdCBlPXQubGVuZ3RoPjEwMjQ/YDx0cnVuY2F0ZWQ+JHt0LnNsaWNlKC0xMDI0KX1gOnQsbj1KLmV4ZWMoZSk7cmV0dXJuIG4/bi5zbGljZSgxKTpbXX0odCksbj1lWzBdO2xldCByPWVbMV07cmV0dXJuIG58fHI/KHImJihyPXIuc2xpY2UoMCxyLmxlbmd0aC0xKSksbityKToiLiJ9dmFyIEg7ZnVuY3Rpb24gVyh0KXtyZXR1cm4gbmV3IFkoKGU9PntlKHQpfSkpfSFmdW5jdGlvbih0KXt0W3QuUEVORElORz0wXT0iUEVORElORyI7dFt0LlJFU09MVkVEPTFdPSJSRVNPTFZFRCI7dFt0LlJFSkVDVEVEPTJdPSJSRUpFQ1RFRCJ9KEh8fChIPXt9KSk7Y2xhc3MgWXtjb25zdHJ1Y3Rvcih0KXtZLnByb3RvdHlwZS5fX2luaXQuY2FsbCh0aGlzKSxZLnByb3RvdHlwZS5fX2luaXQyLmNhbGwodGhpcyksWS5wcm90b3R5cGUuX19pbml0My5jYWxsKHRoaXMpLFkucHJvdG90eXBlLl9faW5pdDQuY2FsbCh0aGlzKSx0aGlzLmk9SC5QRU5ESU5HLHRoaXMudT1bXTt0cnl7dCh0aGlzLmgsdGhpcy5wKX1jYXRjaCh0KXt0aGlzLnAodCl9fXRoZW4odCxlKXtyZXR1cm4gbmV3IFkoKChuLHIpPT57dGhpcy51LnB1c2goWyExLGU9PntpZih0KXRyeXtuKHQoZSkpfWNhdGNoKHQpe3IodCl9ZWxzZSBuKGUpfSx0PT57aWYoZSl0cnl7bihlKHQpKX1jYXRjaCh0KXtyKHQpfWVsc2Ugcih0KX1dKSx0aGlzLmwoKX0pKX1jYXRjaCh0KXtyZXR1cm4gdGhpcy50aGVuKCh0PT50KSx0KX1maW5hbGx5KHQpe3JldHVybiBuZXcgWSgoKGUsbik9PntsZXQgcixvO3JldHVybiB0aGlzLnRoZW4oKGU9PntvPSExLHI9ZSx0JiZ0KCl9KSwoZT0+e289ITAscj1lLHQmJnQoKX0pKS50aGVuKCgoKT0+e28/bihyKTplKHIpfSkpfSkpfV9faW5pdCgpe3RoaXMuaD10PT57dGhpcy5tKEguUkVTT0xWRUQsdCl9fV9faW5pdDIoKXt0aGlzLnA9dD0+e3RoaXMubShILlJFSkVDVEVELHQpfX1fX2luaXQzKCl7dGhpcy5tPSh0LGUpPT57dGhpcy5pPT09SC5QRU5ESU5HJiYobShlKT9lLnRoZW4odGhpcy5oLHRoaXMucCk6KHRoaXMuaT10LHRoaXMudj1lLHRoaXMubCgpKSl9fV9faW5pdDQoKXt0aGlzLmw9KCk9PntpZih0aGlzLmk9PT1ILlBFTkRJTkcpcmV0dXJuO2NvbnN0IHQ9dGhpcy51LnNsaWNlKCk7dGhpcy51PVtdLHQuZm9yRWFjaCgodD0+e3RbMF18fCh0aGlzLmk9PT1ILlJFU09MVkVEJiZ0WzFdKHRoaXMudiksdGhpcy5pPT09SC5SRUpFQ1RFRCYmdFsyXSh0aGlzLnYpLHRbMF09ITApfSkpfX19ZnVuY3Rpb24gcSh0KXtjb25zdCBlPVtdO2Z1bmN0aW9uIG4odCl7cmV0dXJuIGUuc3BsaWNlKGUuaW5kZXhPZih0KSwxKVswXX1yZXR1cm57JDplLGFkZDpmdW5jdGlvbihyKXtpZighKHZvaWQgMD09PXR8fGUubGVuZ3RoPHQpKXJldHVybiBvPW5ldyBDKCJOb3QgYWRkaW5nIFByb21pc2UgYmVjYXVzZSBidWZmZXIgbGltaXQgd2FzIHJlYWNoZWQuIiksbmV3IFkoKCh0LGUpPT57ZShvKX0pKTt2YXIgbztjb25zdCBzPXIoKTtyZXR1cm4tMT09PWUuaW5kZXhPZihzKSYmZS5wdXNoKHMpLHMudGhlbigoKCk9Pm4ocykpKS50aGVuKG51bGwsKCgpPT5uKHMpLnRoZW4obnVsbCwoKCk9Pnt9KSkpKSxzfSxkcmFpbjpmdW5jdGlvbih0KXtyZXR1cm4gbmV3IFkoKChuLHIpPT57bGV0IG89ZS5sZW5ndGg7aWYoIW8pcmV0dXJuIG4oITApO2NvbnN0IHM9c2V0VGltZW91dCgoKCk9Pnt0JiZ0PjAmJm4oITEpfSksdCk7ZS5mb3JFYWNoKCh0PT57Vyh0KS50aGVuKCgoKT0+ey0tb3x8KGNsZWFyVGltZW91dChzKSxuKCEwKSl9KSxyKX0pKX0pKX19fWZ1bmN0aW9uIEYodCxlPSExKXtyZXR1cm4hKGV8fHQmJiF0LnN0YXJ0c1dpdGgoIi8iKSYmIXQubWF0Y2goL15bQS1aXTovKSYmIXQuc3RhcnRzV2l0aCgiLiIpJiYhdC5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSkmJnZvaWQgMCE9PXQmJiF0LmluY2x1ZGVzKCJub2RlX21vZHVsZXMvIil9Y29uc3QgSz0xZTM7ZnVuY3Rpb24gVigpe3JldHVybiBEYXRlLm5vdygpL0t9Y29uc3QgWj1mdW5jdGlvbigpe2NvbnN0e3BlcmZvcm1hbmNlOnR9PXk7aWYoIXR8fCF0Lm5vdylyZXR1cm4gVjtjb25zdCBlPURhdGUubm93KCktdC5ub3coKSxuPW51bGw9PXQudGltZU9yaWdpbj9lOnQudGltZU9yaWdpbjtyZXR1cm4oKT0+KG4rdC5ub3coKSkvS30oKTtmdW5jdGlvbiBRKHQsZT1bXSl7cmV0dXJuW3QsZV19ZnVuY3Rpb24gWCh0LGUpe2NvbnN0IG49dFsxXTtmb3IoY29uc3QgdCBvZiBuKXtpZihlKHQsdFswXS50eXBlKSlyZXR1cm4hMH1yZXR1cm4hMX1mdW5jdGlvbiB0dCh0KXtyZXR1cm4geS5fX1NFTlRSWV9fJiZ5Ll9fU0VOVFJZX18uZW5jb2RlUG9seWZpbGw/eS5fX1NFTlRSWV9fLmVuY29kZVBvbHlmaWxsKHQpOihuZXcgVGV4dEVuY29kZXIpLmVuY29kZSh0KX1mdW5jdGlvbiBldCh0KXtjb25zdFtlLG5dPXQ7bGV0IHI9SlNPTi5zdHJpbmdpZnkoZSk7ZnVuY3Rpb24gbyh0KXsic3RyaW5nIj09dHlwZW9mIHI/cj0ic3RyaW5nIj09dHlwZW9mIHQ/cit0Olt0dChyKSx0XTpyLnB1c2goInN0cmluZyI9PXR5cGVvZiB0P3R0KHQpOnQpfWZvcihjb25zdCB0IG9mIG4pe2NvbnN0W2Usbl09dDtpZihvKGBcbiR7SlNPTi5zdHJpbmdpZnkoZSl9XG5gKSwic3RyaW5nIj09dHlwZW9mIG58fG4gaW5zdGFuY2VvZiBVaW50OEFycmF5KW8obik7ZWxzZXtsZXQgdDt0cnl7dD1KU09OLnN0cmluZ2lmeShuKX1jYXRjaChlKXt0PUpTT04uc3RyaW5naWZ5KEwobikpfW8odCl9fXJldHVybiJzdHJpbmciPT10eXBlb2Ygcj9yOmZ1bmN0aW9uKHQpe2NvbnN0IGU9dC5yZWR1Y2UoKCh0LGUpPT50K2UubGVuZ3RoKSwwKSxuPW5ldyBVaW50OEFycmF5KGUpO2xldCByPTA7Zm9yKGNvbnN0IGUgb2YgdCluLnNldChlLHIpLHIrPWUubGVuZ3RoO3JldHVybiBufShyKX0oKCk9Pntjb25zdHtwZXJmb3JtYW5jZTp0fT15O2lmKCF0fHwhdC5ub3cpcmV0dXJuO2NvbnN0IGU9MzZlNSxuPXQubm93KCkscj1EYXRlLm5vdygpLG89dC50aW1lT3JpZ2luP01hdGguYWJzKHQudGltZU9yaWdpbituLXIpOmUscz1vPGUsaT10LnRpbWluZyYmdC50aW1pbmcubmF2aWdhdGlvblN0YXJ0LGM9Im51bWJlciI9PXR5cGVvZiBpP01hdGguYWJzKGkrbi1yKTplOyhzfHxjPGUpJiYobzw9YyYmdC50aW1lT3JpZ2luKX0pKCk7Y29uc3QgbnQ9e3Nlc3Npb246InNlc3Npb24iLHNlc3Npb25zOiJzZXNzaW9uIixhdHRhY2htZW50OiJhdHRhY2htZW50Iix0cmFuc2FjdGlvbjoidHJhbnNhY3Rpb24iLGV2ZW50OiJlcnJvciIsY2xpZW50X3JlcG9ydDoiaW50ZXJuYWwiLHVzZXJfcmVwb3J0OiJkZWZhdWx0Iixwcm9maWxlOiJwcm9maWxlIixyZXBsYXlfZXZlbnQ6InJlcGxheSIscmVwbGF5X3JlY29yZGluZzoicmVwbGF5IixjaGVja19pbjoibW9uaXRvciIsZmVlZGJhY2s6ImZlZWRiYWNrIixzcGFuOiJzcGFuIixzdGF0c2Q6Im1ldHJpY19idWNrZXQifTtmdW5jdGlvbiBydCh0KXtyZXR1cm4gbnRbdF19ZnVuY3Rpb24gb3QodCl7aWYoIXR8fCF0LnNkaylyZXR1cm47Y29uc3R7bmFtZTplLHZlcnNpb246bn09dC5zZGs7cmV0dXJue25hbWU6ZSx2ZXJzaW9uOm59fWNvbnN0IHN0PTZlNDtmdW5jdGlvbiBpdCh0LHtzdGF0dXNDb2RlOmUsaGVhZGVyczpufSxyPURhdGUubm93KCkpe2NvbnN0IG89ey4uLnR9LHM9biYmblsieC1zZW50cnktcmF0ZS1saW1pdHMiXSxpPW4mJm5bInJldHJ5LWFmdGVyIl07aWYocylmb3IoY29uc3QgdCBvZiBzLnRyaW0oKS5zcGxpdCgiLCIpKXtjb25zdFtlLG4sLCxzXT10LnNwbGl0KCI6Iiw1KSxpPXBhcnNlSW50KGUsMTApLGM9MWUzKihpc05hTihpKT82MDppKTtpZihuKWZvcihjb25zdCB0IG9mIG4uc3BsaXQoIjsiKSkibWV0cmljX2J1Y2tldCI9PT10JiZzJiYhcy5zcGxpdCgiOyIpLmluY2x1ZGVzKCJjdXN0b20iKXx8KG9bdF09citjKTtlbHNlIG8uYWxsPXIrY31lbHNlIGk/by5hbGw9citmdW5jdGlvbih0LGU9RGF0ZS5ub3coKSl7Y29uc3Qgbj1wYXJzZUludChgJHt0fWAsMTApO2lmKCFpc05hTihuKSlyZXR1cm4gMWUzKm47Y29uc3Qgcj1EYXRlLnBhcnNlKGAke3R9YCk7cmV0dXJuIGlzTmFOKHIpP3N0OnItZX0oaSxyKTo0Mjk9PT1lJiYoby5hbGw9cis2ZTQpO3JldHVybiBvfWNvbnN0IGN0PSJ1bmRlZmluZWQiPT10eXBlb2YgX19TRU5UUllfREVCVUdfX3x8X19TRU5UUllfREVCVUdfXztmdW5jdGlvbiB1dCgpe3JldHVybiBhdCh5KSx5fWZ1bmN0aW9uIGF0KHQpe3JldHVybiB0Ll9fU0VOVFJZX198fCh0Ll9fU0VOVFJZX189e2V4dGVuc2lvbnM6e319KSx0Ll9fU0VOVFJZX199ZnVuY3Rpb24gZnQodCl7Y29uc3QgZT1aKCksbj17c2lkOk0oKSxpbml0OiEwLHRpbWVzdGFtcDplLHN0YXJ0ZWQ6ZSxkdXJhdGlvbjowLHN0YXR1czoib2siLGVycm9yczowLGlnbm9yZUR1cmF0aW9uOiExLHRvSlNPTjooKT0+ZnVuY3Rpb24odCl7cmV0dXJuIGooe3NpZDpgJHt0LnNpZH1gLGluaXQ6dC5pbml0LHN0YXJ0ZWQ6bmV3IERhdGUoMWUzKnQuc3RhcnRlZCkudG9JU09TdHJpbmcoKSx0aW1lc3RhbXA6bmV3IERhdGUoMWUzKnQudGltZXN0YW1wKS50b0lTT1N0cmluZygpLHN0YXR1czp0LnN0YXR1cyxlcnJvcnM6dC5lcnJvcnMsZGlkOiJudW1iZXIiPT10eXBlb2YgdC5kaWR8fCJzdHJpbmciPT10eXBlb2YgdC5kaWQ/YCR7dC5kaWR9YDp2b2lkIDAsZHVyYXRpb246dC5kdXJhdGlvbixhYm5vcm1hbF9tZWNoYW5pc206dC5hYm5vcm1hbF9tZWNoYW5pc20sYXR0cnM6e3JlbGVhc2U6dC5yZWxlYXNlLGVudmlyb25tZW50OnQuZW52aXJvbm1lbnQsaXBfYWRkcmVzczp0LmlwQWRkcmVzcyx1c2VyX2FnZW50OnQudXNlckFnZW50fX0pfShuKX07cmV0dXJuIHQmJmh0KG4sdCksbn1mdW5jdGlvbiBodCh0LGU9e30pe2lmKGUudXNlciYmKCF0LmlwQWRkcmVzcyYmZS51c2VyLmlwX2FkZHJlc3MmJih0LmlwQWRkcmVzcz1lLnVzZXIuaXBfYWRkcmVzcyksdC5kaWR8fGUuZGlkfHwodC5kaWQ9ZS51c2VyLmlkfHxlLnVzZXIuZW1haWx8fGUudXNlci51c2VybmFtZSkpLHQudGltZXN0YW1wPWUudGltZXN0YW1wfHxaKCksZS5hYm5vcm1hbF9tZWNoYW5pc20mJih0LmFibm9ybWFsX21lY2hhbmlzbT1lLmFibm9ybWFsX21lY2hhbmlzbSksZS5pZ25vcmVEdXJhdGlvbiYmKHQuaWdub3JlRHVyYXRpb249ZS5pZ25vcmVEdXJhdGlvbiksZS5zaWQmJih0LnNpZD0zMj09PWUuc2lkLmxlbmd0aD9lLnNpZDpNKCkpLHZvaWQgMCE9PWUuaW5pdCYmKHQuaW5pdD1lLmluaXQpLCF0LmRpZCYmZS5kaWQmJih0LmRpZD1gJHtlLmRpZH1gKSwibnVtYmVyIj09dHlwZW9mIGUuc3RhcnRlZCYmKHQuc3RhcnRlZD1lLnN0YXJ0ZWQpLHQuaWdub3JlRHVyYXRpb24pdC5kdXJhdGlvbj12b2lkIDA7ZWxzZSBpZigibnVtYmVyIj09dHlwZW9mIGUuZHVyYXRpb24pdC5kdXJhdGlvbj1lLmR1cmF0aW9uO2Vsc2V7Y29uc3QgZT10LnRpbWVzdGFtcC10LnN0YXJ0ZWQ7dC5kdXJhdGlvbj1lPj0wP2U6MH1lLnJlbGVhc2UmJih0LnJlbGVhc2U9ZS5yZWxlYXNlKSxlLmVudmlyb25tZW50JiYodC5lbnZpcm9ubWVudD1lLmVudmlyb25tZW50KSwhdC5pcEFkZHJlc3MmJmUuaXBBZGRyZXNzJiYodC5pcEFkZHJlc3M9ZS5pcEFkZHJlc3MpLCF0LnVzZXJBZ2VudCYmZS51c2VyQWdlbnQmJih0LnVzZXJBZ2VudD1lLnVzZXJBZ2VudCksIm51bWJlciI9PXR5cGVvZiBlLmVycm9ycyYmKHQuZXJyb3JzPWUuZXJyb3JzKSxlLnN0YXR1cyYmKHQuc3RhdHVzPWUuc3RhdHVzKX1jb25zdCBwdD0iX3NlbnRyeVNwYW4iO2Z1bmN0aW9uIGx0KHQsZSl7ZT9mdW5jdGlvbih0LGUsbil7dHJ5e09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LGUse3ZhbHVlOm4sd3JpdGFibGU6ITAsY29uZmlndXJhYmxlOiEwfSl9Y2F0Y2gobil7UyYmTi5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7ZX0iIHRvIG9iamVjdGAsdCl9fSh0LHB0LGUpOmRlbGV0ZSB0W3B0XX1mdW5jdGlvbiBkdCh0KXtyZXR1cm4gdFtwdF19Y2xhc3MgbXR7Y29uc3RydWN0b3IoKXt0aGlzLl89ITEsdGhpcy5TPVtdLHRoaXMuTj1bXSx0aGlzLms9W10sdGhpcy5DPVtdLHRoaXMuRD17fSx0aGlzLlQ9e30sdGhpcy5PPXt9LHRoaXMuaj17fSx0aGlzLlI9e30sdGhpcy5BPWd0KCl9Y2xvbmUoKXtjb25zdCB0PW5ldyBtdDtyZXR1cm4gdC5rPVsuLi50aGlzLmtdLHQuVD17Li4udGhpcy5UfSx0Lk89ey4uLnRoaXMuT30sdC5qPXsuLi50aGlzLmp9LHQuRD10aGlzLkQsdC5JPXRoaXMuSSx0LlA9dGhpcy5QLHQuVT10aGlzLlUsdC5NPXRoaXMuTSx0Lk49Wy4uLnRoaXMuTl0sdC5MPXRoaXMuTCx0LkM9Wy4uLnRoaXMuQ10sdC5SPXsuLi50aGlzLlJ9LHQuQT17Li4udGhpcy5BfSx0LkI9dGhpcy5CLHQuRz10aGlzLkcsbHQodCxkdCh0aGlzKSksdH1zZXRDbGllbnQodCl7dGhpcy5CPXR9c2V0TGFzdEV2ZW50SWQodCl7dGhpcy5HPXR9Z2V0Q2xpZW50KCl7cmV0dXJuIHRoaXMuQn1sYXN0RXZlbnRJZCgpe3JldHVybiB0aGlzLkd9YWRkU2NvcGVMaXN0ZW5lcih0KXt0aGlzLlMucHVzaCh0KX1hZGRFdmVudFByb2Nlc3Nvcih0KXtyZXR1cm4gdGhpcy5OLnB1c2godCksdGhpc31zZXRVc2VyKHQpe3JldHVybiB0aGlzLkQ9dHx8e2VtYWlsOnZvaWQgMCxpZDp2b2lkIDAsaXBfYWRkcmVzczp2b2lkIDAsdXNlcm5hbWU6dm9pZCAwfSx0aGlzLlAmJmh0KHRoaXMuUCx7dXNlcjp0fSksdGhpcy5KKCksdGhpc31nZXRVc2VyKCl7cmV0dXJuIHRoaXMuRH1nZXRSZXF1ZXN0U2Vzc2lvbigpe3JldHVybiB0aGlzLkx9c2V0UmVxdWVzdFNlc3Npb24odCl7cmV0dXJuIHRoaXMuTD10LHRoaXN9c2V0VGFncyh0KXtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsLi4udH0sdGhpcy5KKCksdGhpc31zZXRUYWcodCxlKXtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsW3RdOmV9LHRoaXMuSigpLHRoaXN9c2V0RXh0cmFzKHQpe3JldHVybiB0aGlzLk89ey4uLnRoaXMuTywuLi50fSx0aGlzLkooKSx0aGlzfXNldEV4dHJhKHQsZSl7cmV0dXJuIHRoaXMuTz17Li4udGhpcy5PLFt0XTplfSx0aGlzLkooKSx0aGlzfXNldEZpbmdlcnByaW50KHQpe3JldHVybiB0aGlzLk09dCx0aGlzLkooKSx0aGlzfXNldExldmVsKHQpe3JldHVybiB0aGlzLkk9dCx0aGlzLkooKSx0aGlzfXNldFRyYW5zYWN0aW9uTmFtZSh0KXtyZXR1cm4gdGhpcy5VPXQsdGhpcy5KKCksdGhpc31zZXRDb250ZXh0KHQsZSl7cmV0dXJuIG51bGw9PT1lP2RlbGV0ZSB0aGlzLmpbdF06dGhpcy5qW3RdPWUsdGhpcy5KKCksdGhpc31zZXRTZXNzaW9uKHQpe3JldHVybiB0P3RoaXMuUD10OmRlbGV0ZSB0aGlzLlAsdGhpcy5KKCksdGhpc31nZXRTZXNzaW9uKCl7cmV0dXJuIHRoaXMuUH11cGRhdGUodCl7aWYoIXQpcmV0dXJuIHRoaXM7Y29uc3QgZT0iZnVuY3Rpb24iPT10eXBlb2YgdD90KHRoaXMpOnQsW24scl09ZSBpbnN0YW5jZW9mIG10P1tlLmdldFNjb3BlRGF0YSgpLGUuZ2V0UmVxdWVzdFNlc3Npb24oKV06ZChlKT9bdCx0LnJlcXVlc3RTZXNzaW9uXTpbXSx7dGFnczpvLGV4dHJhOnMsdXNlcjppLGNvbnRleHRzOmMsbGV2ZWw6dSxmaW5nZXJwcmludDphPVtdLHByb3BhZ2F0aW9uQ29udGV4dDpmfT1ufHx7fTtyZXR1cm4gdGhpcy5UPXsuLi50aGlzLlQsLi4ub30sdGhpcy5PPXsuLi50aGlzLk8sLi4uc30sdGhpcy5qPXsuLi50aGlzLmosLi4uY30saSYmT2JqZWN0LmtleXMoaSkubGVuZ3RoJiYodGhpcy5EPWkpLHUmJih0aGlzLkk9dSksYS5sZW5ndGgmJih0aGlzLk09YSksZiYmKHRoaXMuQT1mKSxyJiYodGhpcy5MPXIpLHRoaXN9Y2xlYXIoKXtyZXR1cm4gdGhpcy5rPVtdLHRoaXMuVD17fSx0aGlzLk89e30sdGhpcy5EPXt9LHRoaXMuaj17fSx0aGlzLkk9dm9pZCAwLHRoaXMuVT12b2lkIDAsdGhpcy5NPXZvaWQgMCx0aGlzLkw9dm9pZCAwLHRoaXMuUD12b2lkIDAsbHQodGhpcyx2b2lkIDApLHRoaXMuQz1bXSx0aGlzLkE9Z3QoKSx0aGlzLkooKSx0aGlzfWFkZEJyZWFkY3J1bWIodCxlKXtjb25zdCBuPSJudW1iZXIiPT10eXBlb2YgZT9lOjEwMDtpZihuPD0wKXJldHVybiB0aGlzO2NvbnN0IHI9e3RpbWVzdGFtcDpWKCksLi4udH0sbz10aGlzLms7cmV0dXJuIG8ucHVzaChyKSx0aGlzLms9by5sZW5ndGg+bj9vLnNsaWNlKC1uKTpvLHRoaXMuSigpLHRoaXN9Z2V0TGFzdEJyZWFkY3J1bWIoKXtyZXR1cm4gdGhpcy5rW3RoaXMuay5sZW5ndGgtMV19Y2xlYXJCcmVhZGNydW1icygpe3JldHVybiB0aGlzLms9W10sdGhpcy5KKCksdGhpc31hZGRBdHRhY2htZW50KHQpe3JldHVybiB0aGlzLkMucHVzaCh0KSx0aGlzfWNsZWFyQXR0YWNobWVudHMoKXtyZXR1cm4gdGhpcy5DPVtdLHRoaXN9Z2V0U2NvcGVEYXRhKCl7cmV0dXJue2JyZWFkY3J1bWJzOnRoaXMuayxhdHRhY2htZW50czp0aGlzLkMsY29udGV4dHM6dGhpcy5qLHRhZ3M6dGhpcy5ULGV4dHJhOnRoaXMuTyx1c2VyOnRoaXMuRCxsZXZlbDp0aGlzLkksZmluZ2VycHJpbnQ6dGhpcy5NfHxbXSxldmVudFByb2Nlc3NvcnM6dGhpcy5OLHByb3BhZ2F0aW9uQ29udGV4dDp0aGlzLkEsc2RrUHJvY2Vzc2luZ01ldGFkYXRhOnRoaXMuUix0cmFuc2FjdGlvbk5hbWU6dGhpcy5VLHNwYW46ZHQodGhpcyl9fXNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh0KXtyZXR1cm4gdGhpcy5SPXsuLi50aGlzLlIsLi4udH0sdGhpc31zZXRQcm9wYWdhdGlvbkNvbnRleHQodCl7cmV0dXJuIHRoaXMuQT10LHRoaXN9Z2V0UHJvcGFnYXRpb25Db250ZXh0KCl7cmV0dXJuIHRoaXMuQX1jYXB0dXJlRXhjZXB0aW9uKHQsZSl7Y29uc3Qgbj1lJiZlLmV2ZW50X2lkP2UuZXZlbnRfaWQ6TSgpO2lmKCF0aGlzLkIpcmV0dXJuIE4ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEiKSxuO2NvbnN0IHI9bmV3IEVycm9yKCJTZW50cnkgc3ludGhldGljRXhjZXB0aW9uIik7cmV0dXJuIHRoaXMuQi5jYXB0dXJlRXhjZXB0aW9uKHQse29yaWdpbmFsRXhjZXB0aW9uOnQsc3ludGhldGljRXhjZXB0aW9uOnIsLi4uZSxldmVudF9pZDpufSx0aGlzKSxufWNhcHR1cmVNZXNzYWdlKHQsZSxuKXtjb25zdCByPW4mJm4uZXZlbnRfaWQ/bi5ldmVudF9pZDpNKCk7aWYoIXRoaXMuQilyZXR1cm4gTi53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgbWVzc2FnZSEiKSxyO2NvbnN0IG89bmV3IEVycm9yKHQpO3JldHVybiB0aGlzLkIuY2FwdHVyZU1lc3NhZ2UodCxlLHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpvLC4uLm4sZXZlbnRfaWQ6cn0sdGhpcykscn1jYXB0dXJlRXZlbnQodCxlKXtjb25zdCBuPWUmJmUuZXZlbnRfaWQ/ZS5ldmVudF9pZDpNKCk7cmV0dXJuIHRoaXMuQj8odGhpcy5CLmNhcHR1cmVFdmVudCh0LHsuLi5lLGV2ZW50X2lkOm59LHRoaXMpLG4pOihOLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEiKSxuKX1KKCl7dGhpcy5ffHwodGhpcy5fPSEwLHRoaXMuUy5mb3JFYWNoKCh0PT57dCh0aGlzKX0pKSx0aGlzLl89ITEpfX1mdW5jdGlvbiBndCgpe3JldHVybnt0cmFjZUlkOk0oKSxzcGFuSWQ6TSgpLnN1YnN0cmluZygxNil9fWZ1bmN0aW9uIHl0KCl7cmV0dXJuICR0KHV0KCkpLmdldEN1cnJlbnRTY29wZSgpLmdldENsaWVudCgpfWNsYXNzIGJ0e2NvbnN0cnVjdG9yKHQsZSl7bGV0IG4scjtuPXR8fG5ldyBtdCxyPWV8fG5ldyBtdCx0aGlzLkg9W3tzY29wZTpufV0sdGhpcy5XPXJ9d2l0aFNjb3BlKHQpe2NvbnN0IGU9dGhpcy5ZKCk7bGV0IG47dHJ5e249dChlKX1jYXRjaCh0KXt0aHJvdyB0aGlzLnEoKSx0fXJldHVybiBtKG4pP24udGhlbigodD0+KHRoaXMucSgpLHQpKSwodD0+e3Rocm93IHRoaXMucSgpLHR9KSk6KHRoaXMucSgpLG4pfWdldENsaWVudCgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuY2xpZW50fWdldFNjb3BlKCl7cmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZX1nZXRJc29sYXRpb25TY29wZSgpe3JldHVybiB0aGlzLld9Z2V0U3RhY2soKXtyZXR1cm4gdGhpcy5IfWdldFN0YWNrVG9wKCl7cmV0dXJuIHRoaXMuSFt0aGlzLkgubGVuZ3RoLTFdfVkoKXtjb25zdCB0PXRoaXMuZ2V0U2NvcGUoKS5jbG9uZSgpO3JldHVybiB0aGlzLmdldFN0YWNrKCkucHVzaCh7Y2xpZW50OnRoaXMuZ2V0Q2xpZW50KCksc2NvcGU6dH0pLHR9cSgpe3JldHVybiEodGhpcy5nZXRTdGFjaygpLmxlbmd0aDw9MSkmJiEhdGhpcy5nZXRTdGFjaygpLnBvcCgpfX1mdW5jdGlvbiB2dCgpe2NvbnN0IHQ9YXQodXQoKSk7cmV0dXJuIHQuaHVifHwodC5odWI9bmV3IGJ0KGIoImRlZmF1bHRDdXJyZW50U2NvcGUiLCgoKT0+bmV3IG10KSksYigiZGVmYXVsdElzb2xhdGlvblNjb3BlIiwoKCk9Pm5ldyBtdCkpKSksdC5odWJ9ZnVuY3Rpb24gX3QodCl7cmV0dXJuIHZ0KCkud2l0aFNjb3BlKHQpfWZ1bmN0aW9uIHd0KHQsZSl7Y29uc3Qgbj12dCgpO3JldHVybiBuLndpdGhTY29wZSgoKCk9PihuLmdldFN0YWNrVG9wKCkuc2NvcGU9dCxlKHQpKSkpfWZ1bmN0aW9uIFN0KHQpe3JldHVybiB2dCgpLndpdGhTY29wZSgoKCk9PnQodnQoKS5nZXRJc29sYXRpb25TY29wZSgpKSkpfWZ1bmN0aW9uICR0KHQpe2NvbnN0IGU9YXQodCk7cmV0dXJuIGUuYWNzP2UuYWNzOnt3aXRoSXNvbGF0aW9uU2NvcGU6U3Qsd2l0aFNjb3BlOl90LHdpdGhTZXRTY29wZTp3dCx3aXRoU2V0SXNvbGF0aW9uU2NvcGU6KHQsZSk9PlN0KGUpLGdldEN1cnJlbnRTY29wZTooKT0+dnQoKS5nZXRTY29wZSgpLGdldElzb2xhdGlvblNjb3BlOigpPT52dCgpLmdldElzb2xhdGlvblNjb3BlKCl9fWNvbnN0IEV0PSJzZW50cnkuc291cmNlIix4dD0ic2VudHJ5LnNhbXBsZV9yYXRlIixOdD0ic2VudHJ5Lm9wIixrdD0ic2VudHJ5Lm9yaWdpbiIsQ3Q9MCxEdD0xLFR0PSJwcm9kdWN0aW9uIixPdD0iX2Zyb3plbkRzYyI7ZnVuY3Rpb24ganQodCl7Y29uc3QgZT15dCgpO2lmKCFlKXJldHVybnt9O2NvbnN0IG49ZnVuY3Rpb24odCxlKXtjb25zdCBuPWUuZ2V0T3B0aW9ucygpLHtwdWJsaWNLZXk6cn09ZS5nZXREc24oKXx8e30sbz1qKHtlbnZpcm9ubWVudDpuLmVudmlyb25tZW50fHxUdCxyZWxlYXNlOm4ucmVsZWFzZSxwdWJsaWNfa2V5OnIsdHJhY2VfaWQ6dH0pO3JldHVybiBlLmVtaXQoImNyZWF0ZURzYyIsbyksb30oVXQodCkudHJhY2VfaWR8fCIiLGUpLHI9QnQodCk7aWYoIXIpcmV0dXJuIG47Y29uc3Qgbz1yW090XTtpZihvKXJldHVybiBvO2NvbnN0IHM9VXQociksaT1zLmRhdGF8fHt9LGM9aVt4dF07bnVsbCE9YyYmKG4uc2FtcGxlX3JhdGU9YCR7Y31gKTtjb25zdCB1PWlbRXRdO3JldHVybiB1JiYidXJsIiE9PXUmJihuLnRyYW5zYWN0aW9uPXMuZGVzY3JpcHRpb24pLG4uc2FtcGxlZD1TdHJpbmcoZnVuY3Rpb24odCl7Y29uc3R7dHJhY2VGbGFnczplfT10LnNwYW5Db250ZXh0KCk7cmV0dXJuIGU9PT1SdH0ocikpLGUuZW1pdCgiY3JlYXRlRHNjIixuKSxufWNvbnN0IFJ0PTE7ZnVuY3Rpb24gQXQodCl7Y29uc3R7c3BhbklkOmUsdHJhY2VJZDpufT10LnNwYW5Db250ZXh0KCkse3BhcmVudF9zcGFuX2lkOnJ9PVV0KHQpO3JldHVybiBqKHtwYXJlbnRfc3Bhbl9pZDpyLHNwYW5faWQ6ZSx0cmFjZV9pZDpufSl9ZnVuY3Rpb24gSXQodCl7cmV0dXJuIm51bWJlciI9PXR5cGVvZiB0P1B0KHQpOkFycmF5LmlzQXJyYXkodCk/dFswXSt0WzFdLzFlOTp0IGluc3RhbmNlb2YgRGF0ZT9QdCh0LmdldFRpbWUoKSk6WigpfWZ1bmN0aW9uIFB0KHQpe3JldHVybiB0Pjk5OTk5OTk5OTk/dC8xZTM6dH1mdW5jdGlvbiBVdCh0KXtpZihmdW5jdGlvbih0KXtyZXR1cm4iZnVuY3Rpb24iPT10eXBlb2YgdC5nZXRTcGFuSlNPTn0odCkpcmV0dXJuIHQuZ2V0U3BhbkpTT04oKTt0cnl7Y29uc3R7c3BhbklkOmUsdHJhY2VJZDpufT10LnNwYW5Db250ZXh0KCk7aWYoZnVuY3Rpb24odCl7Y29uc3QgZT10O3JldHVybiEhKGUuYXR0cmlidXRlcyYmZS5zdGFydFRpbWUmJmUubmFtZSYmZS5lbmRUaW1lJiZlLnN0YXR1cyl9KHQpKXtjb25zdHthdHRyaWJ1dGVzOnIsc3RhcnRUaW1lOm8sbmFtZTpzLGVuZFRpbWU6aSxwYXJlbnRTcGFuSWQ6YyxzdGF0dXM6dX09dDtyZXR1cm4gaih7c3Bhbl9pZDplLHRyYWNlX2lkOm4sZGF0YTpyLGRlc2NyaXB0aW9uOnMscGFyZW50X3NwYW5faWQ6YyxzdGFydF90aW1lc3RhbXA6SXQobyksdGltZXN0YW1wOkl0KGkpfHx2b2lkIDAsc3RhdHVzOk10KHUpLG9wOnJbTnRdLG9yaWdpbjpyW2t0XSxGOnZvaWQgMH0pfXJldHVybntzcGFuX2lkOmUsdHJhY2VfaWQ6bn19Y2F0Y2godCl7cmV0dXJue319fWZ1bmN0aW9uIE10KHQpe2lmKHQmJnQuY29kZSE9PUN0KXJldHVybiB0LmNvZGU9PT1EdD8ib2siOnQubWVzc2FnZXx8InVua25vd25fZXJyb3IifWNvbnN0IEx0PSJfc2VudHJ5Um9vdFNwYW4iO2Z1bmN0aW9uIEJ0KHQpe3JldHVybiB0W0x0XXx8dH1mdW5jdGlvbiBHdCh0LGUsbixyKXtjb25zdCBvPW90KG4pLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxlKXtlJiYodC5zZGs9dC5zZGt8fHt9LHQuc2RrLm5hbWU9dC5zZGsubmFtZXx8ZS5uYW1lLHQuc2RrLnZlcnNpb249dC5zZGsudmVyc2lvbnx8ZS52ZXJzaW9uLHQuc2RrLmludGVncmF0aW9ucz1bLi4udC5zZGsuaW50ZWdyYXRpb25zfHxbXSwuLi5lLmludGVncmF0aW9uc3x8W11dLHQuc2RrLnBhY2thZ2VzPVsuLi50LnNkay5wYWNrYWdlc3x8W10sLi4uZS5wYWNrYWdlc3x8W11dKX0odCxuJiZuLnNkayk7Y29uc3QgaT1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhJiZ0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YS5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLmUmJntzZGs6ZX0sLi4uISFuJiZyJiZ7ZHNuOmsocil9LC4uLm8mJnt0cmFjZTpqKHsuLi5vfSl9fX0odCxvLHIsZSk7ZGVsZXRlIHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhO3JldHVybiBRKGksW1t7dHlwZTpzfSx0XV0pfWNvbnN0IEp0PSJfX1NFTlRSWV9TVVBQUkVTU19UUkFDSU5HX18iO2Z1bmN0aW9uIHp0KHQpe2NvbnN0IGU9JHQodXQoKSk7cmV0dXJuIGUuc3VwcHJlc3NUcmFjaW5nP2Uuc3VwcHJlc3NUcmFjaW5nKHQpOmZ1bmN0aW9uKC4uLnQpe2NvbnN0IGU9JHQodXQoKSk7aWYoMj09PXQubGVuZ3RoKXtjb25zdFtuLHJdPXQ7cmV0dXJuIG4/ZS53aXRoU2V0U2NvcGUobixyKTplLndpdGhTY29wZShyKX1yZXR1cm4gZS53aXRoU2NvcGUodFswXSl9KChlPT4oZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoe1tKdF06ITB9KSx0KCkpKSl9ZnVuY3Rpb24gSHQodCxlKXtjb25zdHtmaW5nZXJwcmludDpuLHNwYW46cixicmVhZGNydW1iczpvLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTpzfT1lOyFmdW5jdGlvbih0LGUpe2NvbnN0e2V4dHJhOm4sdGFnczpyLHVzZXI6byxjb250ZXh0czpzLGxldmVsOmksdHJhbnNhY3Rpb25OYW1lOmN9PWUsdT1qKG4pO3UmJk9iamVjdC5rZXlzKHUpLmxlbmd0aCYmKHQuZXh0cmE9ey4uLnUsLi4udC5leHRyYX0pO2NvbnN0IGE9aihyKTthJiZPYmplY3Qua2V5cyhhKS5sZW5ndGgmJih0LnRhZ3M9ey4uLmEsLi4udC50YWdzfSk7Y29uc3QgZj1qKG8pO2YmJk9iamVjdC5rZXlzKGYpLmxlbmd0aCYmKHQudXNlcj17Li4uZiwuLi50LnVzZXJ9KTtjb25zdCBoPWoocyk7aCYmT2JqZWN0LmtleXMoaCkubGVuZ3RoJiYodC5jb250ZXh0cz17Li4uaCwuLi50LmNvbnRleHRzfSk7aSYmKHQubGV2ZWw9aSk7YyYmInRyYW5zYWN0aW9uIiE9PXQudHlwZSYmKHQudHJhbnNhY3Rpb249Yyl9KHQsZSksciYmZnVuY3Rpb24odCxlKXt0LmNvbnRleHRzPXt0cmFjZTpBdChlKSwuLi50LmNvbnRleHRzfSx0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YT17ZHluYW1pY1NhbXBsaW5nQ29udGV4dDpqdChlKSwuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YX07Y29uc3Qgbj1CdChlKSxyPVV0KG4pLmRlc2NyaXB0aW9uO3ImJiF0LnRyYW5zYWN0aW9uJiYidHJhbnNhY3Rpb24iPT09dC50eXBlJiYodC50cmFuc2FjdGlvbj1yKX0odCxyKSxmdW5jdGlvbih0LGUpe3QuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludD9mdW5jdGlvbih0KXtyZXR1cm4gQXJyYXkuaXNBcnJheSh0KT90Olt0XX0odC5maW5nZXJwcmludCk6W10sZSYmKHQuZmluZ2VycHJpbnQ9dC5maW5nZXJwcmludC5jb25jYXQoZSkpO3QuZmluZ2VycHJpbnQmJiF0LmZpbmdlcnByaW50Lmxlbmd0aCYmZGVsZXRlIHQuZmluZ2VycHJpbnR9KHQsbiksZnVuY3Rpb24odCxlKXtjb25zdCBuPVsuLi50LmJyZWFkY3J1bWJzfHxbXSwuLi5lXTt0LmJyZWFkY3J1bWJzPW4ubGVuZ3RoP246dm9pZCAwfSh0LG8pLGZ1bmN0aW9uKHQsZSl7dC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9ey4uLnQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhLC4uLmV9fSh0LHMpfWNvbnN0IFd0PSI3IjtmdW5jdGlvbiBZdCh0LGUpe3JldHVybiBuPXtzZW50cnlfa2V5OnQucHVibGljS2V5LHNlbnRyeV92ZXJzaW9uOld0LC4uLmUmJntzZW50cnlfY2xpZW50OmAke2UubmFtZX0vJHtlLnZlcnNpb259YH19LE9iamVjdC5rZXlzKG4pLm1hcCgodD0+YCR7ZW5jb2RlVVJJQ29tcG9uZW50KHQpfT0ke2VuY29kZVVSSUNvbXBvbmVudChuW3RdKX1gKSkuam9pbigiJiIpO3ZhciBufWNvbnN0IHF0PTY0O2Z1bmN0aW9uIEZ0KHQsZSxuPXEodC5idWZmZXJTaXplfHxxdCkpe2xldCByPXt9O3JldHVybntzZW5kOmZ1bmN0aW9uKG8pe2NvbnN0IHM9W107aWYoWChvLCgoZSxuKT0+e2NvbnN0IG89cnQobik7aWYoZnVuY3Rpb24odCxlLG49RGF0ZS5ub3coKSl7cmV0dXJuIGZ1bmN0aW9uKHQsZSl7cmV0dXJuIHRbZV18fHQuYWxsfHwwfSh0LGUpPm59KHIsbykpe2NvbnN0IHI9S3QoZSxuKTt0LnJlY29yZERyb3BwZWRFdmVudCgicmF0ZWxpbWl0X2JhY2tvZmYiLG8scil9ZWxzZSBzLnB1c2goZSl9KSksMD09PXMubGVuZ3RoKXJldHVybiBXKHt9KTtjb25zdCBpPVEob1swXSxzKSxjPWU9PntYKGksKChuLHIpPT57Y29uc3Qgbz1LdChuLHIpO3QucmVjb3JkRHJvcHBlZEV2ZW50KGUscnQociksbyl9KSl9O3JldHVybiBuLmFkZCgoKCk9PmUoe2JvZHk6ZXQoaSl9KS50aGVuKCh0PT4odm9pZCAwIT09dC5zdGF0dXNDb2RlJiYodC5zdGF0dXNDb2RlPDIwMHx8dC5zdGF0dXNDb2RlPj0zMDApJiZjdCYmTi53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHt0LnN0YXR1c0NvZGV9IHRvIHNlbnQgZXZlbnQuYCkscj1pdChyLHQpLHQpKSwodD0+e3Rocm93IGMoIm5ldHdvcmtfZXJyb3IiKSx0fSkpKSkudGhlbigodD0+dCksKHQ9PntpZih0IGluc3RhbmNlb2YgQylyZXR1cm4gY3QmJk4uZXJyb3IoIlNraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLiIpLGMoInF1ZXVlX292ZXJmbG93IiksVyh7fSk7dGhyb3cgdH0pKX0sZmx1c2g6dD0+bi5kcmFpbih0KX19ZnVuY3Rpb24gS3QodCxlKXtpZigiZXZlbnQiPT09ZXx8InRyYW5zYWN0aW9uIj09PWUpcmV0dXJuIEFycmF5LmlzQXJyYXkodCk/dFsxXTp2b2lkIDB9Y29uc3QgVnQ9U3ltYm9sKCJBZ2VudEJhc2VJbnRlcm5hbFN0YXRlIik7Y2xhc3MgWnQgZXh0ZW5kcyBoLkFnZW50e1tWdF07b3B0aW9ucztrZWVwQWxpdmU7Y29uc3RydWN0b3IodCl7c3VwZXIodCksdGhpc1tWdF09e319aXNTZWN1cmVFbmRwb2ludCh0KXtpZih0KXtpZigiYm9vbGVhbiI9PXR5cGVvZiB0LnNlY3VyZUVuZHBvaW50KXJldHVybiB0LnNlY3VyZUVuZHBvaW50O2lmKCJzdHJpbmciPT10eXBlb2YgdC5wcm90b2NvbClyZXR1cm4iaHR0cHM6Ij09PXQucHJvdG9jb2x9Y29uc3R7c3RhY2s6ZX09bmV3IEVycm9yO3JldHVybiJzdHJpbmciPT10eXBlb2YgZSYmZS5zcGxpdCgiXG4iKS5zb21lKCh0PT4tMSE9PXQuaW5kZXhPZigiKGh0dHBzLmpzOiIpfHwtMSE9PXQuaW5kZXhPZigibm9kZTpodHRwczoiKSkpfWNyZWF0ZVNvY2tldCh0LGUsbil7Y29uc3Qgcj17Li4uZSxzZWN1cmVFbmRwb2ludDp0aGlzLmlzU2VjdXJlRW5kcG9pbnQoZSl9O1Byb21pc2UucmVzb2x2ZSgpLnRoZW4oKCgpPT50aGlzLmNvbm5lY3QodCxyKSkpLnRoZW4oKG89PntpZihvIGluc3RhbmNlb2YgaC5BZ2VudClyZXR1cm4gby5hZGRSZXF1ZXN0KHQscik7dGhpc1tWdF0uY3VycmVudFNvY2tldD1vLHN1cGVyLmNyZWF0ZVNvY2tldCh0LGUsbil9KSxuKX1jcmVhdGVDb25uZWN0aW9uKCl7Y29uc3QgdD10aGlzW1Z0XS5jdXJyZW50U29ja2V0O2lmKHRoaXNbVnRdLmN1cnJlbnRTb2NrZXQ9dm9pZCAwLCF0KXRocm93IG5ldyBFcnJvcigiTm8gc29ja2V0IHdhcyByZXR1cm5lZCBpbiB0aGUgYGNvbm5lY3QoKWAgZnVuY3Rpb24iKTtyZXR1cm4gdH1nZXQgZGVmYXVsdFBvcnQoKXtyZXR1cm4gdGhpc1tWdF0uZGVmYXVsdFBvcnQ/PygiaHR0cHM6Ij09PXRoaXMucHJvdG9jb2w/NDQzOjgwKX1zZXQgZGVmYXVsdFBvcnQodCl7dGhpc1tWdF0mJih0aGlzW1Z0XS5kZWZhdWx0UG9ydD10KX1nZXQgcHJvdG9jb2woKXtyZXR1cm4gdGhpc1tWdF0ucHJvdG9jb2w/Pyh0aGlzLmlzU2VjdXJlRW5kcG9pbnQoKT8iaHR0cHM6IjoiaHR0cDoiKX1zZXQgcHJvdG9jb2wodCl7dGhpc1tWdF0mJih0aGlzW1Z0XS5wcm90b2NvbD10KX19ZnVuY3Rpb24gUXQoLi4udCl7Ti5sb2coIltodHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0iLC4uLnQpfWZ1bmN0aW9uIFh0KHQpe3JldHVybiBuZXcgUHJvbWlzZSgoKGUsbik9PntsZXQgcj0wO2NvbnN0IG89W107ZnVuY3Rpb24gcygpe2NvbnN0IGM9dC5yZWFkKCk7Yz9mdW5jdGlvbihjKXtvLnB1c2goYykscis9Yy5sZW5ndGg7Y29uc3QgdT1CdWZmZXIuY29uY2F0KG8sciksYT11LmluZGV4T2YoIlxyXG5cclxuIik7aWYoLTE9PT1hKXJldHVybiBRdCgiaGF2ZSBub3QgcmVjZWl2ZWQgZW5kIG9mIEhUVFAgaGVhZGVycyB5ZXQuLi4iKSx2b2lkIHMoKTtjb25zdCBmPXUuc2xpY2UoMCxhKS50b1N0cmluZygiYXNjaWkiKS5zcGxpdCgiXHJcbiIpLGg9Zi5zaGlmdCgpO2lmKCFoKXJldHVybiB0LmRlc3Ryb3koKSxuKG5ldyBFcnJvcigiTm8gaGVhZGVyIHJlY2VpdmVkIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZSIpKTtjb25zdCBwPWguc3BsaXQoIiAiKSxsPStwWzFdLGQ9cC5zbGljZSgyKS5qb2luKCIgIiksbT17fTtmb3IoY29uc3QgZSBvZiBmKXtpZighZSljb250aW51ZTtjb25zdCByPWUuaW5kZXhPZigiOiIpO2lmKC0xPT09cilyZXR1cm4gdC5kZXN0cm95KCksbihuZXcgRXJyb3IoYEludmFsaWQgaGVhZGVyIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZTogIiR7ZX0iYCkpO2NvbnN0IG89ZS5zbGljZSgwLHIpLnRvTG93ZXJDYXNlKCkscz1lLnNsaWNlKHIrMSkudHJpbVN0YXJ0KCksaT1tW29dOyJzdHJpbmciPT10eXBlb2YgaT9tW29dPVtpLHNdOkFycmF5LmlzQXJyYXkoaSk/aS5wdXNoKHMpOm1bb109c31RdCgiZ290IHByb3h5IHNlcnZlciByZXNwb25zZTogJW8gJW8iLGgsbSksaSgpLGUoe2Nvbm5lY3Q6e3N0YXR1c0NvZGU6bCxzdGF0dXNUZXh0OmQsaGVhZGVyczptfSxidWZmZXJlZDp1fSl9KGMpOnQub25jZSgicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGkoKXt0LnJlbW92ZUxpc3RlbmVyKCJlbmQiLGMpLHQucmVtb3ZlTGlzdGVuZXIoImVycm9yIix1KSx0LnJlbW92ZUxpc3RlbmVyKCJyZWFkYWJsZSIscyl9ZnVuY3Rpb24gYygpe2koKSxRdCgib25lbmQiKSxuKG5ldyBFcnJvcigiUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UiKSl9ZnVuY3Rpb24gdSh0KXtpKCksUXQoIm9uZXJyb3IgJW8iLHQpLG4odCl9dC5vbigiZXJyb3IiLHUpLHQub24oImVuZCIsYykscygpfSkpfWZ1bmN0aW9uIHRlKC4uLnQpe04ubG9nKCJbaHR0cHMtcHJveHktYWdlbnRdIiwuLi50KX1jbGFzcyBlZSBleHRlbmRzIFp0e3N0YXRpYyBwcm90b2NvbHM9WyJodHRwIiwiaHR0cHMiXTtwcm94eTtwcm94eUhlYWRlcnM7Y29ubmVjdE9wdHM7Y29uc3RydWN0b3IodCxlKXtzdXBlcihlKSx0aGlzLm9wdGlvbnM9e30sdGhpcy5wcm94eT0ic3RyaW5nIj09dHlwZW9mIHQ/bmV3IFVSTCh0KTp0LHRoaXMucHJveHlIZWFkZXJzPWU/LmhlYWRlcnM/P3t9LHRlKCJDcmVhdGluZyBuZXcgSHR0cHNQcm94eUFnZW50IGluc3RhbmNlOiAlbyIsdGhpcy5wcm94eS5ocmVmKTtjb25zdCBuPSh0aGlzLnByb3h5Lmhvc3RuYW1lfHx0aGlzLnByb3h5Lmhvc3QpLnJlcGxhY2UoL15cW3xcXSQvZywiIikscj10aGlzLnByb3h5LnBvcnQ/cGFyc2VJbnQodGhpcy5wcm94eS5wb3J0LDEwKToiaHR0cHM6Ij09PXRoaXMucHJveHkucHJvdG9jb2w/NDQzOjgwO3RoaXMuY29ubmVjdE9wdHM9e0FMUE5Qcm90b2NvbHM6WyJodHRwLzEuMSJdLC4uLmU/cmUoZSwiaGVhZGVycyIpOm51bGwsaG9zdDpuLHBvcnQ6cn19YXN5bmMgY29ubmVjdCh0LGUpe2NvbnN0e3Byb3h5Om59PXRoaXM7aWYoIWUuaG9zdCl0aHJvdyBuZXcgVHlwZUVycm9yKCdObyAiaG9zdCIgcHJvdmlkZWQnKTtsZXQgcjtpZigiaHR0cHM6Ij09PW4ucHJvdG9jb2wpe3RlKCJDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvIix0aGlzLmNvbm5lY3RPcHRzKTtjb25zdCB0PXRoaXMuY29ubmVjdE9wdHMuc2VydmVybmFtZXx8dGhpcy5jb25uZWN0T3B0cy5ob3N0O3I9Zi5jb25uZWN0KHsuLi50aGlzLmNvbm5lY3RPcHRzLHNlcnZlcm5hbWU6dCYmYS5pc0lQKHQpP3ZvaWQgMDp0fSl9ZWxzZSB0ZSgiQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cykscj1hLmNvbm5lY3QodGhpcy5jb25uZWN0T3B0cyk7Y29uc3Qgbz0iZnVuY3Rpb24iPT10eXBlb2YgdGhpcy5wcm94eUhlYWRlcnM/dGhpcy5wcm94eUhlYWRlcnMoKTp7Li4udGhpcy5wcm94eUhlYWRlcnN9LHM9YS5pc0lQdjYoZS5ob3N0KT9gWyR7ZS5ob3N0fV1gOmUuaG9zdDtsZXQgaT1gQ09OTkVDVCAke3N9OiR7ZS5wb3J0fSBIVFRQLzEuMVxyXG5gO2lmKG4udXNlcm5hbWV8fG4ucGFzc3dvcmQpe2NvbnN0IHQ9YCR7ZGVjb2RlVVJJQ29tcG9uZW50KG4udXNlcm5hbWUpfToke2RlY29kZVVSSUNvbXBvbmVudChuLnBhc3N3b3JkKX1gO29bIlByb3h5LUF1dGhvcml6YXRpb24iXT1gQmFzaWMgJHtCdWZmZXIuZnJvbSh0KS50b1N0cmluZygiYmFzZTY0Iil9YH1vLkhvc3Q9YCR7c306JHtlLnBvcnR9YCxvWyJQcm94eS1Db25uZWN0aW9uIl18fChvWyJQcm94eS1Db25uZWN0aW9uIl09dGhpcy5rZWVwQWxpdmU/IktlZXAtQWxpdmUiOiJjbG9zZSIpO2Zvcihjb25zdCB0IG9mIE9iamVjdC5rZXlzKG8pKWkrPWAke3R9OiAke29bdF19XHJcbmA7Y29uc3QgYz1YdChyKTtyLndyaXRlKGAke2l9XHJcbmApO2NvbnN0e2Nvbm5lY3Q6dSxidWZmZXJlZDpofT1hd2FpdCBjO2lmKHQuZW1pdCgicHJveHlDb25uZWN0Iix1KSx0aGlzLmVtaXQoInByb3h5Q29ubmVjdCIsdSx0KSwyMDA9PT11LnN0YXR1c0NvZGUpe2lmKHQub25jZSgic29ja2V0IixuZSksZS5zZWN1cmVFbmRwb2ludCl7dGUoIlVwZ3JhZGluZyBzb2NrZXQgY29ubmVjdGlvbiB0byBUTFMiKTtjb25zdCB0PWUuc2VydmVybmFtZXx8ZS5ob3N0O3JldHVybiBmLmNvbm5lY3Qoey4uLnJlKGUsImhvc3QiLCJwYXRoIiwicG9ydCIpLHNvY2tldDpyLHNlcnZlcm5hbWU6YS5pc0lQKHQpP3ZvaWQgMDp0fSl9cmV0dXJuIHJ9ci5kZXN0cm95KCk7Y29uc3QgcD1uZXcgYS5Tb2NrZXQoe3dyaXRhYmxlOiExfSk7cmV0dXJuIHAucmVhZGFibGU9ITAsdC5vbmNlKCJzb2NrZXQiLCh0PT57dGUoIlJlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0IiksdC5wdXNoKGgpLHQucHVzaChudWxsKX0pKSxwfX1mdW5jdGlvbiBuZSh0KXt0LnJlc3VtZSgpfWZ1bmN0aW9uIHJlKHQsLi4uZSl7Y29uc3Qgbj17fTtsZXQgcjtmb3IociBpbiB0KWUuaW5jbHVkZXMocil8fChuW3JdPXRbcl0pO3JldHVybiBufWNvbnN0IG9lPTMyNzY4O2Z1bmN0aW9uIHNlKHQpe3JldHVybiB0LnJlcGxhY2UoL15bQS1aXTovLCIiKS5yZXBsYWNlKC9cXC9nLCIvIil9Y29uc3QgaWU9bjtsZXQgY2UsdWU9ITE7ZnVuY3Rpb24gYWUodCl7aWUuZGVidWcmJmNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHt0fWApfXZhciBmZSxoZSxwZTtjb25zdCBsZT1mdW5jdGlvbih0KXtsZXQgZTt0cnl7ZT1uZXcgVVJMKHQudXJsKX1jYXRjaChlKXtyZXR1cm4geCgoKCk9Pntjb25zb2xlLndhcm4oIltAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuIil9KSksRnQodCwoKCk9PlByb21pc2UucmVzb2x2ZSh7fSkpKX1jb25zdCBuPSJodHRwczoiPT09ZS5wcm90b2NvbCxyPWZ1bmN0aW9uKHQsZSl7Y29uc3R7bm9fcHJveHk6bn09cHJvY2Vzcy5lbnY7cmV0dXJuIG4mJm4uc3BsaXQoIiwiKS5zb21lKChlPT50Lmhvc3QuZW5kc1dpdGgoZSl8fHQuaG9zdG5hbWUuZW5kc1dpdGgoZSkpKT92b2lkIDA6ZX0oZSx0LnByb3h5fHwobj9wcm9jZXNzLmVudi5odHRwc19wcm94eTp2b2lkIDApfHxwcm9jZXNzLmVudi5odHRwX3Byb3h5KSxvPW4/aTpzLGE9dm9pZCAwIT09dC5rZWVwQWxpdmUmJnQua2VlcEFsaXZlLGY9cj9uZXcgZWUocik6bmV3IG8uQWdlbnQoe2tlZXBBbGl2ZTphLG1heFNvY2tldHM6MzAsdGltZW91dDoyZTN9KTtyZXR1cm4genQoKCgpPT57Y29uc3QgZT1mdW5jdGlvbih0LGUsbil7Y29uc3R7aG9zdG5hbWU6cixwYXRobmFtZTpvLHBvcnQ6cyxwcm90b2NvbDppLHNlYXJjaDphfT1uZXcgVVJMKHQudXJsKTtyZXR1cm4gZnVuY3Rpb24oZil7cmV0dXJuIG5ldyBQcm9taXNlKCgoaCxwKT0+e2xldCBsPWZ1bmN0aW9uKHQpe3JldHVybiBuZXcgYyh7cmVhZCgpe3RoaXMucHVzaCh0KSx0aGlzLnB1c2gobnVsbCl9fSl9KGYuYm9keSk7Y29uc3QgZD17Li4udC5oZWFkZXJzfTtmLmJvZHkubGVuZ3RoPm9lJiYoZFsiY29udGVudC1lbmNvZGluZyJdPSJnemlwIixsPWwucGlwZSh1KCkpKTtjb25zdCBtPWUucmVxdWVzdCh7bWV0aG9kOiJQT1NUIixhZ2VudDpuLGhlYWRlcnM6ZCxob3N0bmFtZTpyLHBhdGg6YCR7b30ke2F9YCxwb3J0OnMscHJvdG9jb2w6aSxjYTp0LmNhQ2VydHN9LCh0PT57dC5vbigiZGF0YSIsKCgpPT57fSkpLHQub24oImVuZCIsKCgpPT57fSkpLHQuc2V0RW5jb2RpbmcoInV0ZjgiKTtjb25zdCBlPXQuaGVhZGVyc1sicmV0cnktYWZ0ZXIiXT8/bnVsbCxuPXQuaGVhZGVyc1sieC1zZW50cnktcmF0ZS1saW1pdHMiXT8/bnVsbDtoKHtzdGF0dXNDb2RlOnQuc3RhdHVzQ29kZSxoZWFkZXJzOnsicmV0cnktYWZ0ZXIiOmUsIngtc2VudHJ5LXJhdGUtbGltaXRzIjpBcnJheS5pc0FycmF5KG4pP25bMF06bn19KX0pKTttLm9uKCJlcnJvciIscCksbC5waXBlKG0pfSkpfX0odCx0Lmh0dHBNb2R1bGU/P28sZik7cmV0dXJuIEZ0KHQsZSl9KSl9KHt1cmw6KGZlPWllLmRzbixoZT1pZS50dW5uZWwscGU9aWUuc2RrTWV0YWRhdGEuc2RrLGhlfHxgJHtmdW5jdGlvbih0KXtyZXR1cm5gJHtmdW5jdGlvbih0KXtjb25zdCBlPXQucHJvdG9jb2w/YCR7dC5wcm90b2NvbH06YDoiIixuPXQucG9ydD9gOiR7dC5wb3J0fWA6IiI7cmV0dXJuYCR7ZX0vLyR7dC5ob3N0fSR7bn0ke3QucGF0aD9gLyR7dC5wYXRofWA6IiJ9L2FwaS9gfSh0KX0ke3QucHJvamVjdElkfS9lbnZlbG9wZS9gfShmZSl9PyR7WXQoZmUscGUpfWApLHJlY29yZERyb3BwZWRFdmVudDooKT0+e319KTthc3luYyBmdW5jdGlvbiBkZSgpe2lmKGNlKXthZSgiU2VuZGluZyBhYm5vcm1hbCBzZXNzaW9uIiksaHQoY2Use3N0YXR1czoiYWJub3JtYWwiLGFibm9ybWFsX21lY2hhbmlzbToiYW5yX2ZvcmVncm91bmQifSk7Y29uc3QgdD1mdW5jdGlvbih0LGUsbixyKXtjb25zdCBvPW90KG4pO3JldHVybiBRKHtzZW50X2F0OihuZXcgRGF0ZSkudG9JU09TdHJpbmcoKSwuLi5vJiZ7c2RrOm99LC4uLiEhciYmZSYme2RzbjprKGUpfX0sWyJhZ2dyZWdhdGVzImluIHQ/W3t0eXBlOiJzZXNzaW9ucyJ9LHRdOlt7dHlwZToic2Vzc2lvbiJ9LHQudG9KU09OKCldXSl9KGNlLGllLmRzbixpZS5zZGtNZXRhZGF0YSxpZS50dW5uZWwpO2FlKEpTT04uc3RyaW5naWZ5KHQpKSxhd2FpdCBsZS5zZW5kKHQpO3RyeXtlPy5wb3N0TWVzc2FnZSgic2Vzc2lvbi1lbmRlZCIpfWNhdGNoKHQpe319fWZ1bmN0aW9uIG1lKHQpe2lmKCF0KXJldHVybjtjb25zdCBlPWZ1bmN0aW9uKHQpe2lmKCF0Lmxlbmd0aClyZXR1cm5bXTtjb25zdCBlPUFycmF5LmZyb20odCk7cmV0dXJuL3NlbnRyeVdyYXBwZWQvLnRlc3QoZVtlLmxlbmd0aC0xXS5mdW5jdGlvbnx8IiIpJiZlLnBvcCgpLGUucmV2ZXJzZSgpLFAudGVzdChlW2UubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJihlLnBvcCgpLFAudGVzdChlW2UubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJmUucG9wKCkpLGUuc2xpY2UoMCxBKS5tYXAoKHQ9Pih7Li4udCxmaWxlbmFtZTp0LmZpbGVuYW1lfHxlW2UubGVuZ3RoLTFdLmZpbGVuYW1lLGZ1bmN0aW9uOnQuZnVuY3Rpb258fEl9KSkpfSh0KTtpZihpZS5hcHBSb290UGF0aClmb3IoY29uc3QgdCBvZiBlKXQuZmlsZW5hbWUmJih0LmZpbGVuYW1lPUcodC5maWxlbmFtZSxpZS5hcHBSb290UGF0aCkpO3JldHVybiBlfWFzeW5jIGZ1bmN0aW9uIGdlKHQsZSl7aWYodWUpcmV0dXJuO3VlPSEwLGF3YWl0IGRlKCksYWUoIlNlbmRpbmcgZXZlbnQiKTtjb25zdCBuPXtldmVudF9pZDpNKCksY29udGV4dHM6aWUuY29udGV4dHMscmVsZWFzZTppZS5yZWxlYXNlLGVudmlyb25tZW50OmllLmVudmlyb25tZW50LGRpc3Q6aWUuZGlzdCxwbGF0Zm9ybToibm9kZSIsbGV2ZWw6ImVycm9yIixleGNlcHRpb246e3ZhbHVlczpbe3R5cGU6IkFwcGxpY2F0aW9uTm90UmVzcG9uZGluZyIsdmFsdWU6YEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke2llLmFuclRocmVzaG9sZH0gbXNgLHN0YWNrdHJhY2U6e2ZyYW1lczptZSh0KX0sbWVjaGFuaXNtOnt0eXBlOiJBTlIifX1dfSx0YWdzOmllLnN0YXRpY1RhZ3N9O2UmJmZ1bmN0aW9uKHQsZSl7aWYoSHQodCxlKSwhdC5jb250ZXh0cz8udHJhY2Upe2NvbnN0e3RyYWNlSWQ6bixzcGFuSWQ6cixwYXJlbnRTcGFuSWQ6b309ZS5wcm9wYWdhdGlvbkNvbnRleHQ7dC5jb250ZXh0cz17dHJhY2U6e3RyYWNlX2lkOm4sc3Bhbl9pZDpyLHBhcmVudF9zcGFuX2lkOm99LC4uLnQuY29udGV4dHN9fX0obixlKTtjb25zdCByPUd0KG4saWUuZHNuLGllLnNka01ldGFkYXRhLGllLnR1bm5lbCk7YWUoSlNPTi5zdHJpbmdpZnkocikpLGF3YWl0IGxlLnNlbmQociksYXdhaXQgbGUuZmx1c2goMmUzKSxzZXRUaW1lb3V0KCgoKT0+e3Byb2Nlc3MuZXhpdCgwKX0pLDVlMyl9bGV0IHllO2lmKGFlKCJTdGFydGVkIiksaWUuY2FwdHVyZVN0YWNrVHJhY2Upe2FlKCJDb25uZWN0aW5nIHRvIGRlYnVnZ2VyIik7Y29uc3QgZT1uZXcgdDtlLmNvbm5lY3RUb01haW5UaHJlYWQoKSxhZSgiQ29ubmVjdGVkIHRvIGRlYnVnZ2VyIik7Y29uc3Qgbj1uZXcgTWFwO2Uub24oIkRlYnVnZ2VyLnNjcmlwdFBhcnNlZCIsKHQ9PntuLnNldCh0LnBhcmFtcy5zY3JpcHRJZCx0LnBhcmFtcy51cmwpfSkpLGUub24oIkRlYnVnZ2VyLnBhdXNlZCIsKHQ9PntpZigib3RoZXIiPT09dC5wYXJhbXMucmVhc29uKXRyeXthZSgiRGVidWdnZXIgcGF1c2VkIik7Y29uc3Qgcz1bLi4udC5wYXJhbXMuY2FsbEZyYW1lc10saT1pZS5hcHBSb290UGF0aD9mdW5jdGlvbih0PShwcm9jZXNzLmFyZ3ZbMV0/eihwcm9jZXNzLmFyZ3ZbMV0pOnByb2Nlc3MuY3dkKCkpLGU9IlxcIj09PW8pe2NvbnN0IG49ZT9zZSh0KTp0O3JldHVybiB0PT57aWYoIXQpcmV0dXJuO2NvbnN0IG89ZT9zZSh0KTp0O2xldHtkaXI6cyxiYXNlOmksZXh0OmN9PXIucGFyc2Uobyk7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwoaT1pLnNsaWNlKDAsLTEqYy5sZW5ndGgpKSxzfHwocz0iLiIpO2NvbnN0IHU9cy5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKHU+LTEpcmV0dXJuYCR7cy5zbGljZSh1KzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7aX1gO2lmKHMuc3RhcnRzV2l0aChuKSl7bGV0IHQ9cy5zbGljZShuLmxlbmd0aCsxKS5yZXBsYWNlKC9cLy9nLCIuIik7cmV0dXJuIHQmJih0Kz0iOiIpLHQrPWksdH1yZXR1cm4gaX19KGllLmFwcFJvb3RQYXRoKTooKT0+e30sYz1zLm1hcCgodD0+ZnVuY3Rpb24odCxlLG4pe2NvbnN0IHI9ZT9lLnJlcGxhY2UoL15maWxlOlwvXC8vLCIiKTp2b2lkIDAsbz10LmxvY2F0aW9uLmNvbHVtbk51bWJlcj90LmxvY2F0aW9uLmNvbHVtbk51bWJlcisxOnZvaWQgMCxzPXQubG9jYXRpb24ubGluZU51bWJlcj90LmxvY2F0aW9uLmxpbmVOdW1iZXIrMTp2b2lkIDA7cmV0dXJuIGooe2ZpbGVuYW1lOnIsbW9kdWxlOm4ociksZnVuY3Rpb246dC5mdW5jdGlvbk5hbWV8fEksY29sbm86byxsaW5lbm86cyxpbl9hcHA6cj9GKHIpOnZvaWQgMH0pfSh0LG4uZ2V0KHQubG9jYXRpb24uc2NyaXB0SWQpLGkpKSksdT1zZXRUaW1lb3V0KCgoKT0+e2dlKGMpLnRoZW4obnVsbCwoKCk9PnthZSgiU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLiIpfSkpfSksNWUzKTtlLnBvc3QoIlJ1bnRpbWUuZXZhbHVhdGUiLHtleHByZXNzaW9uOiJnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7IixzaWxlbnQ6ITAscmV0dXJuQnlWYWx1ZTohMH0sKCh0LG4pPT57dCYmYWUoYEVycm9yIGV4ZWN1dGluZyBzY3JpcHQ6ICcke3QubWVzc2FnZX0nYCksY2xlYXJUaW1lb3V0KHUpO2NvbnN0IHI9biYmbi5yZXN1bHQ/bi5yZXN1bHQudmFsdWU6dm9pZCAwO2UucG9zdCgiRGVidWdnZXIucmVzdW1lIiksZS5wb3N0KCJEZWJ1Z2dlci5kaXNhYmxlIiksZ2UoYyxyKS50aGVuKG51bGwsKCgpPT57YWUoIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pKX1jYXRjaCh0KXt0aHJvdyBlLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLGUucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHR9fSkpLHllPSgpPT57dHJ5e2UucG9zdCgiRGVidWdnZXIuZW5hYmxlIiwoKCk9PntlLnBvc3QoIkRlYnVnZ2VyLnBhdXNlIil9KSl9Y2F0Y2godCl7fX19Y29uc3R7cG9sbDpiZX09ZnVuY3Rpb24odCxlLG4scil7Y29uc3Qgbz10KCk7bGV0IHM9ITEsaT0hMDtyZXR1cm4gc2V0SW50ZXJ2YWwoKCgpPT57Y29uc3QgdD1vLmdldFRpbWVNcygpOyExPT09cyYmdD5lK24mJihzPSEwLGkmJnIoKSksdDxlK24mJihzPSExKX0pLDIwKSx7cG9sbDooKT0+e28ucmVzZXQoKX0sZW5hYmxlZDp0PT57aT10fX19KChmdW5jdGlvbigpe2xldCB0PXByb2Nlc3MuaHJ0aW1lKCk7cmV0dXJue2dldFRpbWVNczooKT0+e2NvbnN0W2Usbl09cHJvY2Vzcy5ocnRpbWUodCk7cmV0dXJuIE1hdGguZmxvb3IoMWUzKmUrbi8xZTYpfSxyZXNldDooKT0+e3Q9cHJvY2Vzcy5ocnRpbWUoKX19fSksaWUucG9sbEludGVydmFsLGllLmFuclRocmVzaG9sZCwoZnVuY3Rpb24oKXthZSgiV2F0Y2hkb2cgdGltZW91dCIpLHllPyhhZSgiUGF1c2luZyBkZWJ1Z2dlciB0byBjYXB0dXJlIHN0YWNrIHRyYWNlIikseWUoKSk6KGFlKCJDYXB0dXJpbmcgZXZlbnQgd2l0aG91dCBhIHN0YWNrIHRyYWNlIiksZ2UoKS50aGVuKG51bGwsKCgpPT57YWUoIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LiIpfSkpKX0pKTtlPy5vbigibWVzc2FnZSIsKHQ9Pnt0LnNlc3Npb24mJihjZT1mdCh0LnNlc3Npb24pKSxiZSgpfSkpOw==';
10
+
11
+ const DEFAULT_INTERVAL = 50;
12
+ const DEFAULT_HANG_THRESHOLD = 5000;
13
+
14
+ function log(message, ...args) {
15
+ logger.log(`[ANR] ${message}`, ...args);
16
+ }
17
+
18
+ function globalWithScopeFetchFn() {
19
+ return GLOBAL_OBJ;
20
+ }
21
+
22
+ /** Fetches merged scope data */
23
+ function getScopeData() {
24
+ const scope = getGlobalScope().getScopeData();
25
+ mergeScopeData(scope, getIsolationScope().getScopeData());
26
+ mergeScopeData(scope, getCurrentScope().getScopeData());
27
+
28
+ // We remove attachments because they likely won't serialize well as json
29
+ scope.attachments = [];
30
+ // We can't serialize event processor functions
31
+ scope.eventProcessors = [];
32
+
33
+ return scope;
34
+ }
35
+
36
+ /**
37
+ * Gets contexts by calling all event processors. This shouldn't be called until all integrations are setup
38
+ */
39
+ async function getContexts(client) {
40
+ let event = { message: 'ANR' };
41
+ const eventHint = {};
42
+
43
+ for (const processor of client.getEventProcessors()) {
44
+ if (event === null) break;
45
+ event = await processor(event, eventHint);
46
+ }
47
+
48
+ return _optionalChain([event, 'optionalAccess', _2 => _2.contexts]) || {};
49
+ }
50
+
51
+ const INTEGRATION_NAME = 'Anr';
52
+
53
+ const _anrIntegration = ((options = {}) => {
54
+ if (NODE_VERSION.major < 16 || (NODE_VERSION.major === 16 && NODE_VERSION.minor < 17)) {
55
+ throw new Error('ANR detection requires Node 16.17.0 or later');
56
+ }
57
+
58
+ let worker;
59
+ let client;
60
+
61
+ // Hookup the scope fetch function to the global object so that it can be called from the worker thread via the
62
+ // debugger when it pauses
63
+ const gbl = globalWithScopeFetchFn();
64
+ gbl.__SENTRY_GET_SCOPES__ = getScopeData;
65
+
66
+ return {
67
+ name: INTEGRATION_NAME,
68
+ startWorker: () => {
69
+ if (worker) {
70
+ return;
71
+ }
72
+
73
+ if (client) {
74
+ worker = _startWorker(client, options);
75
+ }
76
+ },
77
+ stopWorker: () => {
78
+ if (worker) {
79
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
80
+ worker.then(stop => {
81
+ stop();
82
+ worker = undefined;
83
+ });
84
+ }
85
+ },
86
+ setup(initClient) {
87
+ client = initClient;
88
+
89
+ // setImmediate is used to ensure that all other integrations have had their setup called first.
90
+ // This allows us to call into all integrations to fetch the full context
91
+ setImmediate(() => this.startWorker());
92
+ },
93
+ } ;
94
+ }) ;
95
+
96
+ const anrIntegration = defineIntegration(_anrIntegration) ;
97
+
98
+ /**
99
+ * Starts the ANR worker thread
100
+ *
101
+ * @returns A function to stop the worker
102
+ */
103
+ async function _startWorker(
104
+ client,
105
+ integrationOptions,
106
+ ) {
107
+ const dsn = client.getDsn();
108
+
109
+ if (!dsn) {
110
+ return () => {
111
+ //
112
+ };
113
+ }
114
+
115
+ const contexts = await getContexts(client);
116
+
117
+ // These will not be accurate if sent later from the worker thread
118
+ _optionalChainDelete([contexts, 'access', _3 => _3.app, 'optionalAccess', _4 => delete _4.app_memory]);
119
+ _optionalChainDelete([contexts, 'access', _5 => _5.device, 'optionalAccess', _6 => delete _6.free_memory]);
120
+
121
+ const initOptions = client.getOptions();
122
+
123
+ const sdkMetadata = client.getSdkMetadata() || {};
124
+ if (sdkMetadata.sdk) {
125
+ sdkMetadata.sdk.integrations = initOptions.integrations.map(i => i.name);
126
+ }
127
+
128
+ const options = {
129
+ debug: logger.isEnabled(),
130
+ dsn,
131
+ tunnel: initOptions.tunnel,
132
+ environment: initOptions.environment || 'production',
133
+ release: initOptions.release,
134
+ dist: initOptions.dist,
135
+ sdkMetadata,
136
+ appRootPath: integrationOptions.appRootPath,
137
+ pollInterval: integrationOptions.pollInterval || DEFAULT_INTERVAL,
138
+ anrThreshold: integrationOptions.anrThreshold || DEFAULT_HANG_THRESHOLD,
139
+ captureStackTrace: !!integrationOptions.captureStackTrace,
140
+ staticTags: integrationOptions.staticTags || {},
141
+ contexts,
142
+ };
143
+
144
+ if (options.captureStackTrace) {
145
+ if (!inspector.url()) {
146
+ inspector.open(0);
147
+ }
148
+ }
149
+
150
+ const worker = new Worker(new URL(`data:application/javascript;base64,${base64WorkerScript}`), {
151
+ workerData: options,
152
+ // We don't want any Node args to be passed to the worker
153
+ execArgv: [],
154
+ });
155
+
156
+ process.on('exit', () => {
157
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
158
+ worker.terminate();
159
+ });
160
+
161
+ const timer = setInterval(() => {
162
+ try {
163
+ const currentSession = getCurrentScope().getSession();
164
+ // We need to copy the session object and remove the toJSON method so it can be sent to the worker
165
+ // serialized without making it a SerializedSession
166
+ const session = currentSession ? { ...currentSession, toJSON: undefined } : undefined;
167
+ // message the worker to tell it the main event loop is still running
168
+ worker.postMessage({ session });
169
+ } catch (_) {
170
+ //
171
+ }
172
+ }, options.pollInterval);
173
+ // Timer should not block exit
174
+ timer.unref();
175
+
176
+ worker.on('message', (msg) => {
177
+ if (msg === 'session-ended') {
178
+ log('ANR event sent from ANR worker. Clearing session in this thread.');
179
+ getCurrentScope().setSession(undefined);
180
+ }
181
+ });
182
+
183
+ worker.once('error', (err) => {
184
+ clearInterval(timer);
185
+ log('ANR worker error', err);
186
+ });
187
+
188
+ worker.once('exit', (code) => {
189
+ clearInterval(timer);
190
+ log('ANR worker exit', code);
191
+ });
192
+
193
+ // Ensure this thread can't block app exit
194
+ worker.unref();
195
+
196
+ return () => {
197
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
198
+ worker.terminate();
199
+ clearInterval(timer);
200
+ };
201
+ }
202
+
203
+ export { anrIntegration, base64WorkerScript };
204
+ //# sourceMappingURL=index.js.map