obsidian-integration-testing 12.0.0 → 12.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 (176) hide show
  1. package/dist/lib/cjs/adb-device-list.cjs +54 -0
  2. package/dist/lib/cjs/adb-device-list.d.cts +72 -0
  3. package/dist/lib/cjs/android-sdk.cjs +52 -0
  4. package/dist/lib/cjs/android-sdk.d.cts +29 -0
  5. package/dist/lib/cjs/app-startup-progress.cjs +87 -0
  6. package/dist/lib/cjs/app-startup-progress.d.cts +128 -0
  7. package/dist/lib/cjs/appium-server-marker.cjs +29 -32
  8. package/dist/lib/cjs/appium-server-marker.d.cts +22 -0
  9. package/dist/lib/cjs/avd-probe-verdict.cjs +90 -0
  10. package/dist/lib/cjs/avd-probe-verdict.d.cts +175 -0
  11. package/dist/lib/cjs/community-plugin-registry.cjs +1 -1
  12. package/dist/lib/cjs/community-plugin-registry.d.cts +1 -1
  13. package/dist/lib/cjs/config-directory-fallback-error.cjs +57 -0
  14. package/dist/lib/cjs/config-directory-fallback-error.d.cts +64 -0
  15. package/dist/lib/cjs/config-directory.cjs +46 -0
  16. package/dist/lib/cjs/config-directory.d.cts +45 -0
  17. package/dist/lib/cjs/connect-to-cdp.cjs +13 -7
  18. package/dist/lib/cjs/connect-to-cdp.d.cts +19 -0
  19. package/dist/lib/cjs/demo-vault-bootstrap.cjs +1 -1
  20. package/dist/lib/cjs/demo-vault-bootstrap.d.cts +3 -2
  21. package/dist/lib/cjs/demo-vault-populate.cjs +3 -2
  22. package/dist/lib/cjs/device-readiness.cjs +38 -3
  23. package/dist/lib/cjs/device-readiness.d.cts +83 -9
  24. package/dist/lib/cjs/emulator-arguments.cjs +6 -2
  25. package/dist/lib/cjs/emulator-arguments.d.cts +26 -0
  26. package/dist/lib/cjs/emulator-backend.cjs +71 -0
  27. package/dist/lib/cjs/emulator-backend.d.cts +76 -0
  28. package/dist/lib/cjs/emulator-liveness.cjs +72 -0
  29. package/dist/lib/cjs/emulator-liveness.d.cts +158 -0
  30. package/dist/lib/cjs/emulator-snapshot.cjs +57 -0
  31. package/dist/lib/cjs/emulator-snapshot.d.cts +68 -0
  32. package/dist/lib/cjs/global-setup-core.cjs +30 -30
  33. package/dist/lib/cjs/global-setup-core.d.cts +27 -2
  34. package/dist/lib/cjs/headless-vault-config.cjs +51 -0
  35. package/dist/lib/cjs/headless-vault-config.d.cts +67 -0
  36. package/dist/lib/cjs/index.cjs +12 -1
  37. package/dist/lib/cjs/index.d.cts +6 -1
  38. package/dist/lib/cjs/library.cjs +1 -1
  39. package/dist/lib/cjs/mobile-input.cjs +14 -2
  40. package/dist/lib/cjs/mobile-input.d.cts +5 -9
  41. package/dist/lib/cjs/namespace-bootstrap.cjs +1 -1
  42. package/dist/lib/cjs/obsidian-instance.cjs +52 -3
  43. package/dist/lib/cjs/obsidian-instance.d.cts +12 -0
  44. package/dist/lib/cjs/open-obsidian-settings-tab.cjs +1 -1
  45. package/dist/lib/cjs/open-obsidian-settings-tab.d.cts +3 -2
  46. package/dist/lib/cjs/owned-instance-exit-marker.cjs +99 -0
  47. package/dist/lib/cjs/owned-instance-exit-marker.d.cts +106 -0
  48. package/dist/lib/cjs/owned-instance-exited-error.cjs +106 -0
  49. package/dist/lib/cjs/owned-instance-exited-error.d.cts +98 -0
  50. package/dist/lib/cjs/owned-vault-seed.cjs +9 -5
  51. package/dist/lib/cjs/owned-vault-seed.d.cts +24 -3
  52. package/dist/lib/cjs/parent-liveness.cjs +42 -5
  53. package/dist/lib/cjs/parent-liveness.d.cts +37 -5
  54. package/dist/lib/cjs/port-owner.cjs +61 -0
  55. package/dist/lib/cjs/port-owner.d.cts +47 -0
  56. package/dist/lib/cjs/process-capture.cjs +62 -0
  57. package/dist/lib/cjs/process-capture.d.cts +83 -0
  58. package/dist/lib/cjs/process-exit-message.cjs +14 -8
  59. package/dist/lib/cjs/process-exit-message.d.cts +37 -3
  60. package/dist/lib/cjs/process-liveness.cjs +51 -0
  61. package/dist/lib/cjs/process-liveness.d.cts +18 -0
  62. package/dist/lib/cjs/run-version-matrix.cjs +1 -1
  63. package/dist/lib/cjs/run-version-matrix.d.cts +1 -1
  64. package/dist/lib/cjs/teardown-verdict.cjs +53 -0
  65. package/dist/lib/cjs/teardown-verdict.d.cts +69 -0
  66. package/dist/lib/cjs/temporary-vault.cjs +43 -8
  67. package/dist/lib/cjs/temporary-vault.d.cts +47 -5
  68. package/dist/lib/cjs/transport-appium.cjs +102 -17
  69. package/dist/lib/cjs/transport-appium.d.cts +53 -3
  70. package/dist/lib/cjs/transport-desktop-cdp.cjs +195 -6
  71. package/dist/lib/cjs/transport-desktop-cdp.d.cts +99 -0
  72. package/dist/lib/cjs/transport-factory.cjs +951 -133
  73. package/dist/lib/cjs/transport-options.cjs +11 -3
  74. package/dist/lib/cjs/transport-options.d.cts +131 -12
  75. package/dist/lib/cjs/transport.cjs +1 -1
  76. package/dist/lib/cjs/transport.d.cts +7 -1
  77. package/dist/lib/cjs/vault-plugin-install.cjs +40 -0
  78. package/dist/lib/cjs/vault-plugin-install.d.cts +64 -0
  79. package/dist/lib/cjs/vault-teardown-verdict.cjs +42 -0
  80. package/dist/lib/cjs/vault-teardown-verdict.d.cts +57 -0
  81. package/dist/lib/cjs/version-matrix.cjs +1 -1
  82. package/dist/lib/cjs/version-matrix.d.cts +2 -2
  83. package/dist/lib/cjs/webview-cdp.cjs +6 -7
  84. package/dist/lib/cjs/webview-cdp.d.cts +5 -1
  85. package/dist/lib/esm/adb-device-list.d.mts +72 -0
  86. package/dist/lib/esm/adb-device-list.mjs +28 -0
  87. package/dist/lib/esm/android-sdk.d.mts +29 -0
  88. package/dist/lib/esm/android-sdk.mjs +18 -0
  89. package/dist/lib/esm/app-startup-progress.d.mts +128 -0
  90. package/dist/lib/esm/app-startup-progress.mjs +59 -0
  91. package/dist/lib/esm/appium-server-marker.d.mts +22 -0
  92. package/dist/lib/esm/appium-server-marker.mjs +28 -22
  93. package/dist/lib/esm/avd-probe-verdict.d.mts +175 -0
  94. package/dist/lib/esm/avd-probe-verdict.mjs +62 -0
  95. package/dist/lib/esm/community-plugin-registry.d.mts +1 -1
  96. package/dist/lib/esm/community-plugin-registry.mjs +1 -1
  97. package/dist/lib/esm/config-directory-fallback-error.d.mts +64 -0
  98. package/dist/lib/esm/config-directory-fallback-error.mjs +33 -0
  99. package/dist/lib/esm/config-directory.d.mts +45 -0
  100. package/dist/lib/esm/config-directory.mjs +21 -0
  101. package/dist/lib/esm/connect-to-cdp.d.mts +19 -0
  102. package/dist/lib/esm/connect-to-cdp.mjs +13 -7
  103. package/dist/lib/esm/demo-vault-bootstrap.d.mts +3 -2
  104. package/dist/lib/esm/demo-vault-bootstrap.mjs +1 -1
  105. package/dist/lib/esm/demo-vault-populate.mjs +3 -2
  106. package/dist/lib/esm/device-readiness.d.mts +83 -9
  107. package/dist/lib/esm/device-readiness.mjs +34 -2
  108. package/dist/lib/esm/emulator-arguments.d.mts +26 -0
  109. package/dist/lib/esm/emulator-arguments.mjs +6 -2
  110. package/dist/lib/esm/emulator-backend.d.mts +76 -0
  111. package/dist/lib/esm/emulator-backend.mjs +45 -0
  112. package/dist/lib/esm/emulator-liveness.d.mts +158 -0
  113. package/dist/lib/esm/emulator-liveness.mjs +47 -0
  114. package/dist/lib/esm/emulator-snapshot.d.mts +68 -0
  115. package/dist/lib/esm/emulator-snapshot.mjs +32 -0
  116. package/dist/lib/esm/global-setup-core.d.mts +27 -2
  117. package/dist/lib/esm/global-setup-core.mjs +34 -35
  118. package/dist/lib/esm/headless-vault-config.d.mts +67 -0
  119. package/dist/lib/esm/headless-vault-config.mjs +31 -0
  120. package/dist/lib/esm/index.d.mts +6 -1
  121. package/dist/lib/esm/index.mjs +11 -1
  122. package/dist/lib/esm/library.mjs +1 -1
  123. package/dist/lib/esm/mobile-input.d.mts +5 -9
  124. package/dist/lib/esm/mobile-input.mjs +14 -2
  125. package/dist/lib/esm/namespace-bootstrap.mjs +1 -1
  126. package/dist/lib/esm/obsidian-instance.d.mts +12 -0
  127. package/dist/lib/esm/obsidian-instance.mjs +55 -3
  128. package/dist/lib/esm/open-obsidian-settings-tab.d.mts +3 -2
  129. package/dist/lib/esm/open-obsidian-settings-tab.mjs +1 -1
  130. package/dist/lib/esm/owned-instance-exit-marker.d.mts +106 -0
  131. package/dist/lib/esm/owned-instance-exit-marker.mjs +78 -0
  132. package/dist/lib/esm/owned-instance-exited-error.d.mts +98 -0
  133. package/dist/lib/esm/owned-instance-exited-error.mjs +81 -0
  134. package/dist/lib/esm/owned-vault-seed.d.mts +24 -3
  135. package/dist/lib/esm/owned-vault-seed.mjs +9 -5
  136. package/dist/lib/esm/parent-liveness.d.mts +37 -5
  137. package/dist/lib/esm/parent-liveness.mjs +42 -5
  138. package/dist/lib/esm/port-owner.d.mts +47 -0
  139. package/dist/lib/esm/port-owner.mjs +36 -0
  140. package/dist/lib/esm/process-capture.d.mts +83 -0
  141. package/dist/lib/esm/process-capture.mjs +38 -0
  142. package/dist/lib/esm/process-exit-message.d.mts +37 -3
  143. package/dist/lib/esm/process-exit-message.mjs +13 -8
  144. package/dist/lib/esm/process-liveness.d.mts +18 -0
  145. package/dist/lib/esm/process-liveness.mjs +17 -0
  146. package/dist/lib/esm/run-version-matrix.d.mts +1 -1
  147. package/dist/lib/esm/run-version-matrix.mjs +1 -1
  148. package/dist/lib/esm/teardown-verdict.d.mts +69 -0
  149. package/dist/lib/esm/teardown-verdict.mjs +28 -0
  150. package/dist/lib/esm/temporary-vault.d.mts +47 -5
  151. package/dist/lib/esm/temporary-vault.mjs +43 -8
  152. package/dist/lib/esm/transport-appium.d.mts +53 -3
  153. package/dist/lib/esm/transport-appium.mjs +108 -17
  154. package/dist/lib/esm/transport-desktop-cdp.d.mts +99 -0
  155. package/dist/lib/esm/transport-desktop-cdp.mjs +202 -7
  156. package/dist/lib/esm/transport-factory.mjs +995 -138
  157. package/dist/lib/esm/transport-options.d.mts +131 -12
  158. package/dist/lib/esm/transport-options.mjs +9 -2
  159. package/dist/lib/esm/transport.d.mts +7 -1
  160. package/dist/lib/esm/vault-plugin-install.d.mts +64 -0
  161. package/dist/lib/esm/vault-plugin-install.mjs +20 -0
  162. package/dist/lib/esm/vault-teardown-verdict.d.mts +57 -0
  163. package/dist/lib/esm/vault-teardown-verdict.mjs +18 -0
  164. package/dist/lib/esm/version-matrix.d.mts +2 -2
  165. package/dist/lib/esm/version-matrix.mjs +1 -1
  166. package/dist/lib/esm/webview-cdp.d.mts +5 -1
  167. package/dist/lib/esm/webview-cdp.mjs +6 -7
  168. package/package.json +24 -23
  169. package/dist/lib/cjs/native-dialog-monitor.cjs +0 -192
  170. package/dist/lib/cjs/native-dialog-monitor.d.cts +0 -66
  171. package/dist/lib/cjs/obsidian-namespace.cjs +0 -17
  172. package/dist/lib/cjs/obsidian-namespace.d.cts +0 -128
  173. package/dist/lib/esm/native-dialog-monitor.d.mts +0 -66
  174. package/dist/lib/esm/native-dialog-monitor.mjs +0 -158
  175. package/dist/lib/esm/obsidian-namespace.d.mts +0 -128
  176. package/dist/lib/esm/obsidian-namespace.mjs +0 -1
@@ -25,6 +25,8 @@ __export(parent_liveness_exports, {
25
25
  module.exports = __toCommonJS(parent_liveness_exports);
26
26
  var import_node_net = require("node:net");
27
27
  const PARENT_LIVENESS_HOST = "127.0.0.1";
28
+ const RECONNECT_ATTEMPT_LIMIT = 3;
29
+ const RECONNECT_DELAY_IN_MILLISECONDS = 250;
28
30
  function buildParentLivenessWatchdogExpression(port) {
29
31
  return `(function() {
30
32
  var FLAG = '__obsidianIntegrationTestingParentLiveness';
@@ -39,20 +41,55 @@ function buildParentLivenessWatchdogExpression(port) {
39
41
  return 'unavailable';
40
42
  }
41
43
  }
42
- var socket = net.connect(${String(port)}, '${PARENT_LIVENESS_HOST}');
44
+ var PORT = ${String(port)};
45
+ var HOST = '${PARENT_LIVENESS_HOST}';
46
+ var RECONNECT_ATTEMPT_LIMIT = ${String(RECONNECT_ATTEMPT_LIMIT)};
47
+ var RECONNECT_DELAY_IN_MILLISECONDS = ${String(RECONNECT_DELAY_IN_MILLISECONDS)};
48
+ var socket = net.connect(PORT, HOST);
43
49
  window[FLAG] = socket;
44
50
  var isConnected = false;
45
51
  socket.on('connect', function() { isConnected = true; });
46
- socket.on('error', function() { /* Handled by the close listener below. */ });
52
+ socket.on('error', function() { /* The close handler below decides what an error meant. */ });
47
53
  socket.on('close', function() {
54
+ /* Fail open: a connection that never established is no evidence the harness died. */
48
55
  if (!isConnected) { return; }
56
+ reconnect(1);
57
+ });
58
+ return 'armed';
59
+
60
+ /* A close only asks the question. Reconnecting answers it. */
61
+ function reconnect(attempt) {
62
+ var didConnect = false;
63
+ var probe = net.connect(PORT, HOST);
64
+ probe.on('connect', function() {
65
+ /* Someone is still listening, so the harness is alive. This is the new token. */
66
+ didConnect = true;
67
+ window[FLAG] = probe;
68
+ probe.on('close', function() { reconnect(1); });
69
+ });
70
+ probe.on('error', function() {
71
+ /*
72
+ * This handler outlives the connect, so it doubles as the adopted socket's
73
+ * error handler. Once connected, an error says nothing about the harness \u2014
74
+ * the close that follows it re-runs the probe.
75
+ */
76
+ if (didConnect) { return; }
77
+ if (attempt < RECONNECT_ATTEMPT_LIMIT) {
78
+ setTimeout(function() { reconnect(attempt + 1); }, RECONNECT_DELAY_IN_MILLISECONDS);
79
+ return;
80
+ }
81
+ /* Nothing answered after several tries: the harness really is gone. */
82
+ destroyWindow();
83
+ });
84
+ }
85
+
86
+ function destroyWindow() {
49
87
  try {
50
88
  window.electronWindow.destroy();
51
89
  } catch (destroyError) {
52
90
  window.close();
53
91
  }
54
- });
55
- return 'armed';
92
+ }
56
93
  })()`;
57
94
  }
58
95
  async function startParentLivenessServer() {
@@ -90,4 +127,4 @@ async function listenOnFreeLoopbackPort(server) {
90
127
  buildParentLivenessWatchdogExpression,
91
128
  startParentLivenessServer
92
129
  });
93
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BhcmVudC1saXZlbmVzcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRpZXMgYSBoYXJuZXNzLW93bmVkIE9ic2lkaWFuIGluc3RhbmNlJ3MgbGlmZXRpbWUgdG8gdGhlIGhhcm5lc3MgcHJvY2VzcyB0aGF0XG4gKiBsYXVuY2hlZCBpdCwgaW4gdGhlIG9uZSBkaXJlY3Rpb24gdGhlIG9wZXJhdGluZyBzeXN0ZW0gd2lsbCBub3QgZG8gZm9yIHVzLlxuICpcbiAqIFRoZSBvd25lZCBpbnN0YW5jZSBpcyBhbHJlYWR5IGEgY2hpbGQgb2YgdGhlIGhhcm5lc3MgcHJvY2VzcywgYnV0IHRoYXQgbGlua1xuICogY2FycmllcyBubyBsaWZldGltZSBndWFyYW50ZWUuIFdpbmRvd3MgbmV2ZXIgcHJvcGFnYXRlcyBhIHBhcmVudCdzIGRlYXRoIHRvXG4gKiBpdHMgY2hpbGRyZW4gXHUyMDE0IGFuIG9ycGhhbiBzaW1wbHkga2VlcHMgcnVubmluZyB3aXRoIGEgc3RhbGUgcGFyZW50IGlkIFx1MjAxNCBhbmQgb25cbiAqIFBPU0lYIGEgYFNJR0tJTExgIGFpbWVkIGF0IGEgc2luZ2xlIHBpZCBuZXZlciBjYXNjYWRlcyBlaXRoZXIuIFRoZSBpbnN0YW5jZSBpc1xuICogYWRkaXRpb25hbGx5IHNwYXduZWQgYGRldGFjaGVkYCwgc28gaXQgaXMgbm90IGV2ZW4gaW4gdGhlIGhhcm5lc3MncyBwcm9jZXNzXG4gKiBncm91cC4gVGVhcmRvd24gdGhlcmVmb3JlIHJlbGllcyBlbnRpcmVseSBvbiB0aGUgaGFybmVzcyBydW5uaW5nIGl0cyBvd25cbiAqIGNsZWFudXAgKGBraWxsUHJvY2Vzc1RyZWVgIGZyb20gYW4gYGV4aXRgL3NpZ25hbCBoYW5kbGVyKSwgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBhIGBTSUdLSUxMYCwgYSBUYXNrIE1hbmFnZXIga2lsbCwgb3IgYW4gSURFIHN0b3AgYnV0dG9uIGRlbmllcyBpdC4gRXZlcnlcbiAqIHN1Y2gga2lsbCBsZWFrcyBhIGhpZGRlbiBPYnNpZGlhbiBob2xkaW5nIGEgdXNlci1kYXRhIGRpciBhbmQgYSBDRFAgcG9ydCwgYW5kXG4gKiB0aGV5IGFjY3VtdWxhdGU6IHRoZSBuZXh0IHJ1biBwaWNrcyBhIGZyZXNoIHRlbXAgZGlyIGFuZCBhIGZyZWUgcG9ydCwgc29cbiAqIG5vdGhpbmcgY29sbGlkZXMgYW5kIG5vdGhpbmcgY29tcGxhaW5zLlxuICpcbiAqIFRoZSBndWFyYW50ZWVkIGZpeCBpcyBhbiBPUyBwcmltaXRpdmUgXHUyMDE0IGEgV2luZG93cyBKb2IgT2JqZWN0IHdpdGhcbiAqIGBKT0JfT0JKRUNUX0xJTUlUX0tJTExfT05fSk9CX0NMT1NFYCwgb3IgYHByY3RsKFBSX1NFVF9QREVBVEhTSUcpYCBvbiBMaW51eCBcdTIwMTRcbiAqIGJ1dCBuZWl0aGVyIGlzIHJlYWNoYWJsZSBmcm9tIE5vZGUgd2l0aG91dCBhIG5hdGl2ZSBhZGRvbiwgd2hpY2ggaXMgZmFyIHRvb1xuICogaGVhdnkgYSBkZXBlbmRlbmN5IGZvciB0aGlzIGhhcm5lc3MuXG4gKlxuICogU28gd2UgdXNlIHRoZSBvbmUgY3Jvc3MtcGxhdGZvcm0gcmVzb3VyY2UgdGhlIGtlcm5lbCAqZG9lcyogcmVjbGFpbVxuICogZGV0ZXJtaW5pc3RpY2FsbHkgb24gcHJvY2VzcyBkZWF0aDogYSBzb2NrZXQuIFRoZSBoYXJuZXNzIGxpc3RlbnMgb24gYVxuICogbG9vcGJhY2sgcG9ydCBhbmQgdGhlIGluc3RhbmNlJ3MgcmVuZGVyZXIgY29ubmVjdHMgdG8gaXQuIEhvd2V2ZXIgdGhlIGhhcm5lc3NcbiAqIGRpZXMgXHUyMDE0IGNsZWFubHksIGBTSUdLSUxMYGVkLCBvciBjcmFzaGVkIFx1MjAxNCB0aGUga2VybmVsIGNsb3NlcyBpdHMgZW5kLCB0aGVcbiAqIHJlbmRlcmVyIHNlZXMgYGNsb3NlYCwgYW5kIHRoZSB3aW5kb3cgZGVzdHJveXMgaXRzZWxmLiBObyBwb2xsaW5nLCBub1xuICogaGVhcnRiZWF0IGludGVydmFsLCBubyB0aW1lb3V0IHRvIHR1bmUuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGZhaWwtb3BlbjogdGhlIHJlbmRlcmVyIG9ubHkgYXJtcyB0aGUgZGVzdHJveSBoYW5kbGVyIGFmdGVyIHRoZVxuICogY29ubmVjdGlvbiBpcyBhY3R1YWxseSBlc3RhYmxpc2hlZC4gQSB3YXRjaGRvZyB0aGF0IGNhbm5vdCByZWFjaCB0aGUgaGFybmVzc1xuICogbGVhdmVzIHRoZSBpbnN0YW5jZSBydW5uaW5nIHJhdGhlciB0aGFuIGtpbGxpbmcgYSB3aW5kb3cgdGhlIGRldmVsb3BlciBpc1xuICogd29ya2luZyBpbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFNlcnZlciB9IGZyb20gJ25vZGU6bmV0JztcblxuaW1wb3J0IHsgY3JlYXRlU2VydmVyIH0gZnJvbSAnbm9kZTpuZXQnO1xuXG4vKipcbiAqIEEgbGlzdGVuaW5nIGxvb3BiYWNrIHNlcnZlciB3aG9zZSBhY2NlcHRlZCBjb25uZWN0aW9ucyBhY3QgYXMgbGl2ZW5lc3MgdG9rZW5zXG4gKiBmb3IgdGhlIGhhcm5lc3MgcHJvY2Vzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJlbnRMaXZlbmVzc1NlcnZlciB7XG4gIC8qKlxuICBTdG9wcyBsaXN0ZW5pbmcgYW5kIGRyb3BzIGV2ZXJ5IGFjY2VwdGVkIGNvbm5lY3Rpb24uXG4gICAqL1xuICBjbG9zZSgpOiB2b2lkO1xuXG4gIC8qKlxuICBUaGUgbG9vcGJhY2sgcG9ydCB0aGUgcmVuZGVyZXIgd2F0Y2hkb2cgc2hvdWxkIGNvbm5lY3QgYmFjayB0by5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBMb29wYmFjayBob3N0IHRoZSBsaXZlbmVzcyBzZXJ2ZXIgYmluZHMgdG8uIE5ldmVyIGV4cG9zZWQgb2ZmLW1hY2hpbmUuXG4gKi9cbmV4cG9ydCBjb25zdCBQQVJFTlRfTElWRU5FU1NfSE9TVCA9ICcxMjcuMC4wLjEnO1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZWQgaW4gdGhlIG93bmVkIGluc3RhbmNlJ3MgcmVuZGVyZXIgdG8gYXJtIHRoZVxuICogd2F0Y2hkb2cuXG4gKlxuICogV3JpdHRlbiBpbiBFUzUgc3R5bGUgKGB2YXJgLCBgZnVuY3Rpb25gKSB3aXRoIG5vIG9wdGlvbmFsIGNoYWluaW5nLCBtYXRjaGluZ1xuICoge0BsaW5rIERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFJ9OiB0aGUgc2FtZSBleHByZXNzaW9uIGhhcyB0byBwYXJzZSBvbiB0aGVcbiAqIENocm9taXVtIDgwLWVyYSByZW5kZXJlcnMgb2YgdGhlIG9sZGVzdCBzdXBwb3J0ZWQgT2JzaWRpYW4gdmVyc2lvbnMgKEwyNikuXG4gKlxuICogQXJtaW5nIGlzIGlkZW1wb3RlbnQgXHUyMDE0IGEgc2Vjb25kIGV2YWx1YXRpb24gZmluZHMgdGhlIHN0b3JlZCBzb2NrZXQgYW5kXG4gKiByZXR1cm5zIHdpdGhvdXQgb3BlbmluZyBhbm90aGVyIGNvbm5lY3Rpb24sIHNvIGEgcmV0cmllZCByZWFkaW5lc3MgcGFzcyBkb2VzXG4gKiBub3QgcGlsZSB1cCBzb2NrZXRzLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGxvb3BiYWNrIHBvcnQgcmV0dXJuZWQgYnkge0BsaW5rIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXJ9LlxuICogQHJldHVybnMgVGhlIGV4cHJlc3Npb24gdG8gZXZhbHVhdGUsIHlpZWxkaW5nIGAnYXJtZWQnYCwgYCdhbHJlYWR5LWFybWVkJ2AsIG9yIGAndW5hdmFpbGFibGUnYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGFyZW50TGl2ZW5lc3NXYXRjaGRvZ0V4cHJlc3Npb24ocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAoZnVuY3Rpb24oKSB7XG4gIHZhciBGTEFHID0gJ19fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmdQYXJlbnRMaXZlbmVzcyc7XG4gIGlmICh3aW5kb3dbRkxBR10pIHsgcmV0dXJuICdhbHJlYWR5LWFybWVkJzsgfVxuICB2YXIgbmV0O1xuICB0cnkge1xuICAgIG5ldCA9IHdpbmRvdy5yZXF1aXJlKCdub2RlOm5ldCcpO1xuICB9IGNhdGNoIChub2RlUHJlZml4RXJyb3IpIHtcbiAgICB0cnkge1xuICAgICAgbmV0ID0gd2luZG93LnJlcXVpcmUoJ25ldCcpO1xuICAgIH0gY2F0Y2ggKGJhcmVQcmVmaXhFcnJvcikge1xuICAgICAgcmV0dXJuICd1bmF2YWlsYWJsZSc7XG4gICAgfVxuICB9XG4gIHZhciBzb2NrZXQgPSBuZXQuY29ubmVjdCgke1N0cmluZyhwb3J0KX0sICcke1BBUkVOVF9MSVZFTkVTU19IT1NUfScpO1xuICB3aW5kb3dbRkxBR10gPSBzb2NrZXQ7XG4gIHZhciBpc0Nvbm5lY3RlZCA9IGZhbHNlO1xuICBzb2NrZXQub24oJ2Nvbm5lY3QnLCBmdW5jdGlvbigpIHsgaXNDb25uZWN0ZWQgPSB0cnVlOyB9KTtcbiAgc29ja2V0Lm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkgeyAvKiBIYW5kbGVkIGJ5IHRoZSBjbG9zZSBsaXN0ZW5lciBiZWxvdy4gKi8gfSk7XG4gIHNvY2tldC5vbignY2xvc2UnLCBmdW5jdGlvbigpIHtcbiAgICBpZiAoIWlzQ29ubmVjdGVkKSB7IHJldHVybjsgfVxuICAgIHRyeSB7XG4gICAgICB3aW5kb3cuZWxlY3Ryb25XaW5kb3cuZGVzdHJveSgpO1xuICAgIH0gY2F0Y2ggKGRlc3Ryb3lFcnJvcikge1xuICAgICAgd2luZG93LmNsb3NlKCk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuICdhcm1lZCc7XG59KSgpYDtcbn1cblxuLyoqXG4gKiBTdGFydHMgdGhlIGxvb3BiYWNrIGxpdmVuZXNzIHNlcnZlciB0aGUgb3duZWQgaW5zdGFuY2UncyByZW5kZXJlciBjb25uZWN0c1xuICogYmFjayB0by5cbiAqXG4gKiBUaGUgc2VydmVyIGFuZCBldmVyeSBhY2NlcHRlZCBzb2NrZXQgYXJlIGB1bnJlZmBlZCwgc28gaG9sZGluZyBhIHdhdGNoZG9nXG4gKiBjb25uZWN0aW9uIG9wZW4gbmV2ZXIga2VlcHMgdGhlIGhhcm5lc3MgcHJvY2VzcyBhbGl2ZSBvbiBpdHMgb3duIFx1MjAxNCB0aGVcbiAqIGNvbm5lY3Rpb24gaXMgYSB0b2tlbiB0aGUga2VybmVsIHJlY2xhaW1zLCBub3Qgd29yayB0byB3YWl0IG9uLlxuICpcbiAqIEByZXR1cm5zIEEge0BsaW5rIFByb21pc2V9IHJlc29sdmluZyB0byB0aGUgbGlzdGVuaW5nIHtAbGluayBQYXJlbnRMaXZlbmVzc1NlcnZlcn0uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydFBhcmVudExpdmVuZXNzU2VydmVyKCk6IFByb21pc2U8UGFyZW50TGl2ZW5lc3NTZXJ2ZXI+IHtcbiAgY29uc3Qgc2VydmVyID0gY3JlYXRlU2VydmVyKChzb2NrZXQpID0+IHtcbiAgICBzb2NrZXQudW5yZWYoKTtcbiAgICAvLyBUaGUgY29ubmVjdGlvbiBjYXJyaWVzIG5vIGRhdGEgXHUyMDE0IGl0IGV4aXN0cyBvbmx5IHNvIGl0cyBjbG9zZSBpcyBvYnNlcnZhYmxlLlxuICAgIHNvY2tldC5vbignZXJyb3InLCAoKSA9PiB7XG4gICAgICAvLyBBIHJlbmRlcmVyIHRvcm4gZG93biBtaWQtY29ubmVjdGlvbiByZXNldHMgcmF0aGVyIHRoYW4gY2xvc2VzOyBub3QgYW4gZXJyb3IgaGVyZS5cbiAgICB9KTtcbiAgfSk7XG4gIHNlcnZlci51bnJlZigpO1xuXG4gIGNvbnN0IHBvcnQgPSBhd2FpdCBsaXN0ZW5PbkZyZWVMb29wYmFja1BvcnQoc2VydmVyKTtcbiAgcmV0dXJuIHtcbiAgICBjbG9zZSgpOiB2b2lkIHtcbiAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgIH0sXG4gICAgcG9ydFxuICB9O1xufVxuXG4vKipcbiAqIEJpbmRzIHRoZSBzZXJ2ZXIgdG8gYW4gZXBoZW1lcmFsIGxvb3BiYWNrIHBvcnQgYW5kIHJlcG9ydHMgd2hpY2ggb25lIGl0IGdvdC5cbiAqXG4gKiBAcGFyYW0gc2VydmVyIC0gVGhlIHNlcnZlciB0byBiaW5kLlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gcmVzb2x2aW5nIHRvIHRoZSBhc3NpZ25lZCBwb3J0LlxuICogQHRocm93cyBJZiB0aGUgc2VydmVyIHJlcG9ydHMgYW4gZXJyb3IgYmVmb3JlIGxpc3RlbmluZywgb3IgYmluZHMgdG8gYSBwaXBlIHJhdGhlciB0aGFuIGEgcG9ydC5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gbGlzdGVuT25GcmVlTG9vcGJhY2tQb3J0KHNlcnZlcjogU2VydmVyKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlPG51bWJlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIHNlcnZlci5vbmNlKCdlcnJvcicsIHJlamVjdCk7XG4gICAgc2VydmVyLmxpc3RlbigwLCBQQVJFTlRfTElWRU5FU1NfSE9TVCwgKCkgPT4ge1xuICAgICAgY29uc3QgYWRkcmVzcyA9IHNlcnZlci5hZGRyZXNzKCk7XG4gICAgICBpZiAoYWRkcmVzcyA9PT0gbnVsbCB8fCB0eXBlb2YgYWRkcmVzcyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgc2VydmVyLmNsb3NlKCk7XG4gICAgICAgIHJlamVjdChuZXcgRXJyb3IoJ0ZhaWxlZCB0byBkZXRlcm1pbmUgdGhlIHBhcmVudC1saXZlbmVzcyBwb3J0LicpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShhZGRyZXNzLnBvcnQpO1xuICAgIH0pO1xuICB9KTtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBc0NBLHNCQUE2QjtBQXFCdEIsTUFBTSx1QkFBdUI7QUFpQjdCLFNBQVMsc0NBQXNDLE1BQXNCO0FBQzFFLFNBQU87QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSw2QkFhb0IsT0FBTyxJQUFJLENBQUMsTUFBTSxvQkFBb0I7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZW5FO0FBWUEsZUFBc0IsNEJBQTJEO0FBQy9FLFFBQU0sYUFBUyw4QkFBYSxDQUFDLFdBQVc7QUFDdEMsV0FBTyxNQUFNO0FBRWIsV0FBTyxHQUFHLFNBQVMsTUFBTTtBQUFBLElBRXpCLENBQUM7QUFBQSxFQUNILENBQUM7QUFDRCxTQUFPLE1BQU07QUFFYixRQUFNLE9BQU8sTUFBTSx5QkFBeUIsTUFBTTtBQUNsRCxTQUFPO0FBQUEsSUFDTCxRQUFjO0FBQ1osYUFBTyxNQUFNO0FBQUEsSUFDZjtBQUFBLElBQ0E7QUFBQSxFQUNGO0FBQ0Y7QUFTQSxlQUFlLHlCQUF5QixRQUFpQztBQUN2RSxTQUFPLElBQUksUUFBZ0IsQ0FBQyxTQUFTLFdBQVc7QUFDOUMsV0FBTyxLQUFLLFNBQVMsTUFBTTtBQUMzQixXQUFPLE9BQU8sR0FBRyxzQkFBc0IsTUFBTTtBQUMzQyxZQUFNLFVBQVUsT0FBTyxRQUFRO0FBQy9CLFVBQUksWUFBWSxRQUFRLE9BQU8sWUFBWSxVQUFVO0FBQ25ELGVBQU8sTUFBTTtBQUNiLGVBQU8sSUFBSSxNQUFNLCtDQUErQyxDQUFDO0FBQ2pFO0FBQUEsTUFDRjtBQUNBLGNBQVEsUUFBUSxJQUFJO0FBQUEsSUFDdEIsQ0FBQztBQUFBLEVBQ0gsQ0FBQztBQUNIOyIsCiAgIm5hbWVzIjogW10KfQo=
130
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BhcmVudC1saXZlbmVzcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIFRpZXMgYSBoYXJuZXNzLW93bmVkIE9ic2lkaWFuIGluc3RhbmNlJ3MgbGlmZXRpbWUgdG8gdGhlIGhhcm5lc3MgcHJvY2VzcyB0aGF0XG4gKiBsYXVuY2hlZCBpdCwgaW4gdGhlIG9uZSBkaXJlY3Rpb24gdGhlIG9wZXJhdGluZyBzeXN0ZW0gd2lsbCBub3QgZG8gZm9yIHVzLlxuICpcbiAqIFRoZSBvd25lZCBpbnN0YW5jZSBpcyBhbHJlYWR5IGEgY2hpbGQgb2YgdGhlIGhhcm5lc3MgcHJvY2VzcywgYnV0IHRoYXQgbGlua1xuICogY2FycmllcyBubyBsaWZldGltZSBndWFyYW50ZWUuIFdpbmRvd3MgbmV2ZXIgcHJvcGFnYXRlcyBhIHBhcmVudCdzIGRlYXRoIHRvXG4gKiBpdHMgY2hpbGRyZW4gXHUyMDE0IGFuIG9ycGhhbiBzaW1wbHkga2VlcHMgcnVubmluZyB3aXRoIGEgc3RhbGUgcGFyZW50IGlkIFx1MjAxNCBhbmQgb25cbiAqIFBPU0lYIGEgYFNJR0tJTExgIGFpbWVkIGF0IGEgc2luZ2xlIHBpZCBuZXZlciBjYXNjYWRlcyBlaXRoZXIuIFRoZSBpbnN0YW5jZSBpc1xuICogYWRkaXRpb25hbGx5IHNwYXduZWQgYGRldGFjaGVkYCwgc28gaXQgaXMgbm90IGV2ZW4gaW4gdGhlIGhhcm5lc3MncyBwcm9jZXNzXG4gKiBncm91cC4gVGVhcmRvd24gdGhlcmVmb3JlIHJlbGllcyBlbnRpcmVseSBvbiB0aGUgaGFybmVzcyBydW5uaW5nIGl0cyBvd25cbiAqIGNsZWFudXAgKGBraWxsUHJvY2Vzc1RyZWVgIGZyb20gYW4gYGV4aXRgL3NpZ25hbCBoYW5kbGVyKSwgd2hpY2ggaXMgZXhhY3RseVxuICogd2hhdCBhIGBTSUdLSUxMYCwgYSBUYXNrIE1hbmFnZXIga2lsbCwgb3IgYW4gSURFIHN0b3AgYnV0dG9uIGRlbmllcyBpdC4gRXZlcnlcbiAqIHN1Y2gga2lsbCBsZWFrcyBhIGhpZGRlbiBPYnNpZGlhbiBob2xkaW5nIGEgdXNlci1kYXRhIGRpciBhbmQgYSBDRFAgcG9ydCwgYW5kXG4gKiB0aGV5IGFjY3VtdWxhdGU6IHRoZSBuZXh0IHJ1biBwaWNrcyBhIGZyZXNoIHRlbXAgZGlyIGFuZCBhIGZyZWUgcG9ydCwgc29cbiAqIG5vdGhpbmcgY29sbGlkZXMgYW5kIG5vdGhpbmcgY29tcGxhaW5zLlxuICpcbiAqIFRoZSBndWFyYW50ZWVkIGZpeCBpcyBhbiBPUyBwcmltaXRpdmUgXHUyMDE0IGEgV2luZG93cyBKb2IgT2JqZWN0IHdpdGhcbiAqIGBKT0JfT0JKRUNUX0xJTUlUX0tJTExfT05fSk9CX0NMT1NFYCwgb3IgYHByY3RsKFBSX1NFVF9QREVBVEhTSUcpYCBvbiBMaW51eCBcdTIwMTRcbiAqIGJ1dCBuZWl0aGVyIGlzIHJlYWNoYWJsZSBmcm9tIE5vZGUgd2l0aG91dCBhIG5hdGl2ZSBhZGRvbiwgd2hpY2ggaXMgZmFyIHRvb1xuICogaGVhdnkgYSBkZXBlbmRlbmN5IGZvciB0aGlzIGhhcm5lc3MuXG4gKlxuICogU28gd2UgdXNlIHRoZSBvbmUgY3Jvc3MtcGxhdGZvcm0gcmVzb3VyY2UgdGhlIGtlcm5lbCAqZG9lcyogcmVjbGFpbVxuICogZGV0ZXJtaW5pc3RpY2FsbHkgb24gcHJvY2VzcyBkZWF0aDogYSBzb2NrZXQuIFRoZSBoYXJuZXNzIGxpc3RlbnMgb24gYVxuICogbG9vcGJhY2sgcG9ydCBhbmQgdGhlIGluc3RhbmNlJ3MgcmVuZGVyZXIgY29ubmVjdHMgdG8gaXQuIEhvd2V2ZXIgdGhlIGhhcm5lc3NcbiAqIGRpZXMgXHUyMDE0IGNsZWFubHksIGBTSUdLSUxMYGVkLCBvciBjcmFzaGVkIFx1MjAxNCB0aGUga2VybmVsIGNsb3NlcyBpdHMgZW5kIGFuZCB0aGVcbiAqIHJlbmRlcmVyIHNlZXMgYGNsb3NlYC4gTm8gcG9sbGluZywgbm8gaGVhcnRiZWF0IGludGVydmFsLCBubyB0aW1lb3V0IHRvIHR1bmUuXG4gKlxuICogKipBIGNsb3NlIGlzIGEgcXVlc3Rpb24sIG5vdCBhIHZlcmRpY3QuKiogQSBzb2NrZXQgY2xvc2luZyBpcyBub3QgdGhlIHNhbWVcbiAqIGV2ZW50IGFzIGEgcHJvY2VzcyBkeWluZywgYW5kIHRyZWF0aW5nIHRoZW0gYXMgaWRlbnRpY2FsIGRlc3Ryb3llZCBoZWFsdGh5XG4gKiBpbnN0YW5jZXM6IG1lYXN1cmVkIG9uIDIwMjYtMDktMDUsIGEgcmVuZGVyZXIncyBpZGxlIGxpdmVuZXNzIHNvY2tldCBzZW50XG4gKiBgRklOYCBvbiBpdHMgb3duIFx1MjAxNCAzIG1pbiAxMyBzIGludG8gb25lIHJ1biwgMTEgbWluIDU2IHMgaW50byBhbm90aGVyIFx1MjAxNCB3aGlsZVxuICogdGhlIGhhcm5lc3Mgd2FzIHN0aWxsIGxpc3RlbmluZyBhbmQgd2VudCBvbiB3b3JraW5nIGZvciBhbm90aGVyIDE0IG1pbnV0ZXMuXG4gKiBFdmVyeSB0ZXN0IGZpbGUgc2NoZWR1bGVkIGFmdGVyIHRoZSBkZWF0aCB0aGVuIGZhaWxlZCBpbiB0ZW5zIG9mIG1pbGxpc2Vjb25kc1xuICogd2l0aCBgRUNPTk5SRUZVU0VEYCBvbiB0aGUgZGVhZCBDRFAgcG9ydDsgdGhlIHdvcnN0IHJ1biByZXBvcnRlZCAxNTYgc3VjaFxuICogZmFpbHVyZXMgYWNyb3NzIDIxIGZpbGVzLCBub3Qgb25lIG9mIHRoZW0gYSB0ZXN0IHJlc3VsdC4gV2h5IGFuIGlkbGUgdW5yZWYnZFxuICogbG9vcGJhY2sgc29ja2V0IGluIGFuIEVsZWN0cm9uIHJlbmRlcmVyIGRvZXMgdGhhdCBpcyBub3QgZXN0YWJsaXNoZWQsIGFuZCBkb2VzXG4gKiBub3QgbmVlZCB0byBiZTogdGhlIGxpZmV0aW1lcyB2YXJ5IHJ1biB0byBydW4sIHNvIG5vIGZpeGVkIHRpbWVvdXQgZXhwbGFpbnMgaXQuXG4gKlxuICogU28gdGhlIGBjbG9zZWAgaGFuZGxlciAqKnZlcmlmaWVzIGJlZm9yZSBkZXN0cm95aW5nKio6IGl0IHJlY29ubmVjdHMgdG8gdGhlXG4gKiBzYW1lIGxvb3BiYWNrIHBvcnQuIEEgaGFybmVzcyB0aGF0IGlzIGFsaXZlIGlzIHN0aWxsIGxpc3RlbmluZywgc28gdGhlXG4gKiByZWNvbm5lY3Qgc3VjY2VlZHMgYW5kIHRoZSBuZXcgc29ja2V0IGJlY29tZXMgdGhlIGxpdmVuZXNzIHRva2VuOyBvbmx5IHdoZW5cbiAqIG5vdGhpbmcgYW5zd2VycyBhZnRlciBhIGZldyB0cmllcyBcdTIwMTQgd2hhdCBhIGRlYWQgaGFybmVzcyBhY3R1YWxseSBsb29rcyBsaWtlIFx1MjAxNFxuICogaXMgdGhlIHdpbmRvdyBkZXN0cm95ZWQuIFRoZSBsZWFrIHRoZSB3YXRjaGRvZyBleGlzdHMgdG8gcHJldmVudCBpcyBzdGlsbFxuICogcHJldmVudGVkLCBhbmQgdGhlIG1lYXN1cmVkIHJlY292ZXJ5IGlzIDExIG1zLlxuICpcbiAqIEEgcmVjb25uZWN0IHJhdGhlciB0aGFuIGEgY2hlY2sgb24gdGhlIGhhcm5lc3MncyBwcm9jZXNzIGlkLCBiZWNhdXNlIGl0IHByb3Zlc1xuICogdGhlIHRoaW5nIHRoZSB3YXRjaGRvZyBhY3R1YWxseSBkZXBlbmRzIG9uIFx1MjAxNCB0aGUgbGl2ZW5lc3Mgc2VydmVyIHN0aWxsIHNlcnZpbmdcbiAqIFx1MjAxNCBhbmQgaXQgc3RheXMgY29ycmVjdCBhZ2FpbnN0IGEgKmJ1c3kqIGhhcm5lc3M6IHRoZSBrZXJuZWwgY29tcGxldGVzIGFcbiAqIGxvb3BiYWNrIGhhbmRzaGFrZSBvdXQgb2YgdGhlIGxpc3RlbiBiYWNrbG9nIGV2ZW4gd2hpbGUgTm9kZSdzIGV2ZW50IGxvb3AgaXNcbiAqIGJsb2NrZWQuIEl0cyBvbmUgcmVzaWR1YWwgYW1iaWd1aXR5IGlzIGFjY2VwdGVkOiBhIHJlY29ubmVjdCBwcm92ZXMgKnNvbWV0aGluZypcbiAqIGlzIGxpc3RlbmluZyBvbiB0aGF0IGVwaGVtZXJhbCBwb3J0LCBub3QgdGhhdCBpdCBpcyBvdXJzLiBUaGUgcHJvYmUgZm9sbG93cyB0aGVcbiAqIGNsb3NlIGJ5IG1pbGxpc2Vjb25kcywgc28gYW5vdGhlciBwcm9jZXNzIHdpbm5pbmcgdGhhdCBleGFjdCBwb3J0IGluIGJldHdlZW4gaXNcbiAqIG5vdCBhIHJpc2sgd29ydGggYSBoYW5kc2hha2UgcHJvdG9jb2wuXG4gKlxuICogRGVsaWJlcmF0ZWx5IGZhaWwtb3BlbjogdGhlIHJlbmRlcmVyIG9ubHkgYXJtcyB0aGUgZGVzdHJveSBwYXRoIGFmdGVyIHRoZVxuICogY29ubmVjdGlvbiBpcyBhY3R1YWxseSBlc3RhYmxpc2hlZC4gQSB3YXRjaGRvZyB0aGF0IGNhbm5vdCByZWFjaCB0aGUgaGFybmVzc1xuICogbGVhdmVzIHRoZSBpbnN0YW5jZSBydW5uaW5nIHJhdGhlciB0aGFuIGtpbGxpbmcgYSB3aW5kb3cgdGhlIGRldmVsb3BlciBpc1xuICogd29ya2luZyBpbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFNlcnZlciB9IGZyb20gJ25vZGU6bmV0JztcblxuaW1wb3J0IHsgY3JlYXRlU2VydmVyIH0gZnJvbSAnbm9kZTpuZXQnO1xuXG4vKipcbiAqIEEgbGlzdGVuaW5nIGxvb3BiYWNrIHNlcnZlciB3aG9zZSBhY2NlcHRlZCBjb25uZWN0aW9ucyBhY3QgYXMgbGl2ZW5lc3MgdG9rZW5zXG4gKiBmb3IgdGhlIGhhcm5lc3MgcHJvY2Vzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQYXJlbnRMaXZlbmVzc1NlcnZlciB7XG4gIC8qKlxuICAgKiBTdG9wcyBsaXN0ZW5pbmcuXG4gICAqXG4gICAqIE5vZGUga2VlcHMgYWxyZWFkeS1hY2NlcHRlZCBjb25uZWN0aW9ucyBhbGl2ZSBhY3Jvc3MgYSBgY2xvc2UoKWAsIHNvIHRoaXNcbiAgICogZG9lcyBub3QgYnkgaXRzZWxmIHNpZ25hbCB0aGUgcmVuZGVyZXIgXHUyMDE0IHRoZSBrZXJuZWwgcmVjbGFpbWluZyB0aGUgc29ja2V0IG9uXG4gICAqIHByb2Nlc3MgZGVhdGggaXMgd2hhdCBkb2VzLiBXaGF0IGl0IGRvZXMgZ3VhcmFudGVlIGlzIHRoYXQgYSB3YXRjaGRvZyBwcm9iZVxuICAgKiBhcnJpdmluZyBhZnRlcndhcmRzIGlzIHJlZnVzZWQsIHdoaWNoIGlzIHRoZSBhbnN3ZXIgYSB0b3JuLWRvd24gaGFybmVzc1xuICAgKiBzaG91bGQgZ2l2ZS5cbiAgICovXG4gIGNsb3NlKCk6IHZvaWQ7XG5cbiAgLyoqXG4gIFRoZSBsb29wYmFjayBwb3J0IHRoZSByZW5kZXJlciB3YXRjaGRvZyBzaG91bGQgY29ubmVjdCBiYWNrIHRvLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG4vKipcbiAqIExvb3BiYWNrIGhvc3QgdGhlIGxpdmVuZXNzIHNlcnZlciBiaW5kcyB0by4gTmV2ZXIgZXhwb3NlZCBvZmYtbWFjaGluZS5cbiAqL1xuZXhwb3J0IGNvbnN0IFBBUkVOVF9MSVZFTkVTU19IT1NUID0gJzEyNy4wLjAuMSc7XG5cbi8qKlxuICogSG93IG1hbnkgdGltZXMgdGhlIHdhdGNoZG9nIHByb2JlcyB0aGUgbG9vcGJhY2sgcG9ydCBiZWZvcmUgY29uY2x1ZGluZyB0aGVcbiAqIGhhcm5lc3MgaXMgZ29uZS5cbiAqXG4gKiBNb3JlIHRoYW4gb25lLCBzbyBhIHNpbmdsZSB0cmFuc2llbnQgcmVmdXNhbCBjYW5ub3QgY29zdCBhIHdob2xlIHJ1bjsgc21hbGwsXG4gKiBiZWNhdXNlIGV2ZXJ5IGF0dGVtcHQgaXMgYSBsb29wYmFjayBjb25uZWN0IHRoYXQgZWl0aGVyIGNvbXBsZXRlcyBvciBpc1xuICogcmVmdXNlZCBpbW1lZGlhdGVseSwgYW5kIGFuIGluc3RhbmNlIHdob3NlIGhhcm5lc3MgcmVhbGx5IGRpZCBkaWUgc2hvdWxkIG5vdFxuICogbGluZ2VyLlxuICovXG5jb25zdCBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCA9IDM7XG5cbi8qKlxuICogSG93IGxvbmcgdGhlIHdhdGNoZG9nIHdhaXRzIGJldHdlZW4gcHJvYmVzLlxuICpcbiAqIExvbmcgZW5vdWdoIHRvIG91dGxhc3QgYSBtb21lbnRhcnkgcmVmdXNhbCwgc2hvcnQgZW5vdWdoIHRoYXQgZXhoYXVzdGluZyB0aGVcbiAqIHdob2xlIGJ1ZGdldCBzdGlsbCBkZXN0cm95cyBhbiBvcnBoYW5lZCB3aW5kb3cgaW5zaWRlIGEgc2Vjb25kLlxuICovXG5jb25zdCBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTID0gMjUwO1xuXG4vKipcbiAqIEJ1aWxkcyB0aGUgZXhwcmVzc2lvbiBldmFsdWF0ZWQgaW4gdGhlIG93bmVkIGluc3RhbmNlJ3MgcmVuZGVyZXIgdG8gYXJtIHRoZVxuICogd2F0Y2hkb2cuXG4gKlxuICogV3JpdHRlbiBpbiBFUzUgc3R5bGUgKGB2YXJgLCBgZnVuY3Rpb25gKSB3aXRoIG5vIG9wdGlvbmFsIGNoYWluaW5nLCBtYXRjaGluZ1xuICoge0BsaW5rIERJU01JU1NfVFJVU1RfRElBTE9HX0VYUFJ9OiB0aGUgc2FtZSBleHByZXNzaW9uIGhhcyB0byBwYXJzZSBvbiB0aGVcbiAqIENocm9taXVtIDgwLWVyYSByZW5kZXJlcnMgb2YgdGhlIG9sZGVzdCBzdXBwb3J0ZWQgT2JzaWRpYW4gdmVyc2lvbnMgKEwyNikuXG4gKlxuICogQXJtaW5nIGlzIGlkZW1wb3RlbnQgXHUyMDE0IGEgc2Vjb25kIGV2YWx1YXRpb24gZmluZHMgdGhlIHN0b3JlZCBzb2NrZXQgYW5kXG4gKiByZXR1cm5zIHdpdGhvdXQgb3BlbmluZyBhbm90aGVyIGNvbm5lY3Rpb24sIHNvIGEgcmV0cmllZCByZWFkaW5lc3MgcGFzcyBkb2VzXG4gKiBub3QgcGlsZSB1cCBzb2NrZXRzLlxuICpcbiAqIEBwYXJhbSBwb3J0IC0gVGhlIGxvb3BiYWNrIHBvcnQgcmV0dXJuZWQgYnkge0BsaW5rIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXJ9LlxuICogQHJldHVybnMgVGhlIGV4cHJlc3Npb24gdG8gZXZhbHVhdGUsIHlpZWxkaW5nIGAnYXJtZWQnYCwgYCdhbHJlYWR5LWFybWVkJ2AsIG9yIGAndW5hdmFpbGFibGUnYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUGFyZW50TGl2ZW5lc3NXYXRjaGRvZ0V4cHJlc3Npb24ocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIGAoZnVuY3Rpb24oKSB7XG4gIHZhciBGTEFHID0gJ19fb2JzaWRpYW5JbnRlZ3JhdGlvblRlc3RpbmdQYXJlbnRMaXZlbmVzcyc7XG4gIGlmICh3aW5kb3dbRkxBR10pIHsgcmV0dXJuICdhbHJlYWR5LWFybWVkJzsgfVxuICB2YXIgbmV0O1xuICB0cnkge1xuICAgIG5ldCA9IHdpbmRvdy5yZXF1aXJlKCdub2RlOm5ldCcpO1xuICB9IGNhdGNoIChub2RlUHJlZml4RXJyb3IpIHtcbiAgICB0cnkge1xuICAgICAgbmV0ID0gd2luZG93LnJlcXVpcmUoJ25ldCcpO1xuICAgIH0gY2F0Y2ggKGJhcmVQcmVmaXhFcnJvcikge1xuICAgICAgcmV0dXJuICd1bmF2YWlsYWJsZSc7XG4gICAgfVxuICB9XG4gIHZhciBQT1JUID0gJHtTdHJpbmcocG9ydCl9O1xuICB2YXIgSE9TVCA9ICcke1BBUkVOVF9MSVZFTkVTU19IT1NUfSc7XG4gIHZhciBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCA9ICR7U3RyaW5nKFJFQ09OTkVDVF9BVFRFTVBUX0xJTUlUKX07XG4gIHZhciBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTID0gJHtTdHJpbmcoUkVDT05ORUNUX0RFTEFZX0lOX01JTExJU0VDT05EUyl9O1xuICB2YXIgc29ja2V0ID0gbmV0LmNvbm5lY3QoUE9SVCwgSE9TVCk7XG4gIHdpbmRvd1tGTEFHXSA9IHNvY2tldDtcbiAgdmFyIGlzQ29ubmVjdGVkID0gZmFsc2U7XG4gIHNvY2tldC5vbignY29ubmVjdCcsIGZ1bmN0aW9uKCkgeyBpc0Nvbm5lY3RlZCA9IHRydWU7IH0pO1xuICBzb2NrZXQub24oJ2Vycm9yJywgZnVuY3Rpb24oKSB7IC8qIFRoZSBjbG9zZSBoYW5kbGVyIGJlbG93IGRlY2lkZXMgd2hhdCBhbiBlcnJvciBtZWFudC4gKi8gfSk7XG4gIHNvY2tldC5vbignY2xvc2UnLCBmdW5jdGlvbigpIHtcbiAgICAvKiBGYWlsIG9wZW46IGEgY29ubmVjdGlvbiB0aGF0IG5ldmVyIGVzdGFibGlzaGVkIGlzIG5vIGV2aWRlbmNlIHRoZSBoYXJuZXNzIGRpZWQuICovXG4gICAgaWYgKCFpc0Nvbm5lY3RlZCkgeyByZXR1cm47IH1cbiAgICByZWNvbm5lY3QoMSk7XG4gIH0pO1xuICByZXR1cm4gJ2FybWVkJztcblxuICAvKiBBIGNsb3NlIG9ubHkgYXNrcyB0aGUgcXVlc3Rpb24uIFJlY29ubmVjdGluZyBhbnN3ZXJzIGl0LiAqL1xuICBmdW5jdGlvbiByZWNvbm5lY3QoYXR0ZW1wdCkge1xuICAgIHZhciBkaWRDb25uZWN0ID0gZmFsc2U7XG4gICAgdmFyIHByb2JlID0gbmV0LmNvbm5lY3QoUE9SVCwgSE9TVCk7XG4gICAgcHJvYmUub24oJ2Nvbm5lY3QnLCBmdW5jdGlvbigpIHtcbiAgICAgIC8qIFNvbWVvbmUgaXMgc3RpbGwgbGlzdGVuaW5nLCBzbyB0aGUgaGFybmVzcyBpcyBhbGl2ZS4gVGhpcyBpcyB0aGUgbmV3IHRva2VuLiAqL1xuICAgICAgZGlkQ29ubmVjdCA9IHRydWU7XG4gICAgICB3aW5kb3dbRkxBR10gPSBwcm9iZTtcbiAgICAgIHByb2JlLm9uKCdjbG9zZScsIGZ1bmN0aW9uKCkgeyByZWNvbm5lY3QoMSk7IH0pO1xuICAgIH0pO1xuICAgIHByb2JlLm9uKCdlcnJvcicsIGZ1bmN0aW9uKCkge1xuICAgICAgLypcbiAgICAgICAqIFRoaXMgaGFuZGxlciBvdXRsaXZlcyB0aGUgY29ubmVjdCwgc28gaXQgZG91YmxlcyBhcyB0aGUgYWRvcHRlZCBzb2NrZXQnc1xuICAgICAgICogZXJyb3IgaGFuZGxlci4gT25jZSBjb25uZWN0ZWQsIGFuIGVycm9yIHNheXMgbm90aGluZyBhYm91dCB0aGUgaGFybmVzcyBcdTIwMTRcbiAgICAgICAqIHRoZSBjbG9zZSB0aGF0IGZvbGxvd3MgaXQgcmUtcnVucyB0aGUgcHJvYmUuXG4gICAgICAgKi9cbiAgICAgIGlmIChkaWRDb25uZWN0KSB7IHJldHVybjsgfVxuICAgICAgaWYgKGF0dGVtcHQgPCBSRUNPTk5FQ1RfQVRURU1QVF9MSU1JVCkge1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgeyByZWNvbm5lY3QoYXR0ZW1wdCArIDEpOyB9LCBSRUNPTk5FQ1RfREVMQVlfSU5fTUlMTElTRUNPTkRTKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgLyogTm90aGluZyBhbnN3ZXJlZCBhZnRlciBzZXZlcmFsIHRyaWVzOiB0aGUgaGFybmVzcyByZWFsbHkgaXMgZ29uZS4gKi9cbiAgICAgIGRlc3Ryb3lXaW5kb3coKTtcbiAgICB9KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlc3Ryb3lXaW5kb3coKSB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvdy5lbGVjdHJvbldpbmRvdy5kZXN0cm95KCk7XG4gICAgfSBjYXRjaCAoZGVzdHJveUVycm9yKSB7XG4gICAgICB3aW5kb3cuY2xvc2UoKTtcbiAgICB9XG4gIH1cbn0pKClgO1xufVxuXG4vKipcbiAqIFN0YXJ0cyB0aGUgbG9vcGJhY2sgbGl2ZW5lc3Mgc2VydmVyIHRoZSBvd25lZCBpbnN0YW5jZSdzIHJlbmRlcmVyIGNvbm5lY3RzXG4gKiBiYWNrIHRvLlxuICpcbiAqIFRoZSBzZXJ2ZXIgYW5kIGV2ZXJ5IGFjY2VwdGVkIHNvY2tldCBhcmUgYHVucmVmYGVkLCBzbyBob2xkaW5nIGEgd2F0Y2hkb2dcbiAqIGNvbm5lY3Rpb24gb3BlbiBuZXZlciBrZWVwcyB0aGUgaGFybmVzcyBwcm9jZXNzIGFsaXZlIG9uIGl0cyBvd24gXHUyMDE0IHRoZVxuICogY29ubmVjdGlvbiBpcyBhIHRva2VuIHRoZSBrZXJuZWwgcmVjbGFpbXMsIG5vdCB3b3JrIHRvIHdhaXQgb24uXG4gKlxuICogQHJldHVybnMgQSB7QGxpbmsgUHJvbWlzZX0gcmVzb2x2aW5nIHRvIHRoZSBsaXN0ZW5pbmcge0BsaW5rIFBhcmVudExpdmVuZXNzU2VydmVyfS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHN0YXJ0UGFyZW50TGl2ZW5lc3NTZXJ2ZXIoKTogUHJvbWlzZTxQYXJlbnRMaXZlbmVzc1NlcnZlcj4ge1xuICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKHNvY2tldCkgPT4ge1xuICAgIHNvY2tldC51bnJlZigpO1xuICAgIC8vIFRoZSBjb25uZWN0aW9uIGNhcnJpZXMgbm8gZGF0YSBcdTIwMTQgaXQgZXhpc3RzIG9ubHkgc28gaXRzIGNsb3NlIGlzIG9ic2VydmFibGUuXG4gICAgc29ja2V0Lm9uKCdlcnJvcicsICgpID0+IHtcbiAgICAgIC8vIEEgcmVuZGVyZXIgdG9ybiBkb3duIG1pZC1jb25uZWN0aW9uIHJlc2V0cyByYXRoZXIgdGhhbiBjbG9zZXM7IG5vdCBhbiBlcnJvciBoZXJlLlxuICAgIH0pO1xuICB9KTtcbiAgc2VydmVyLnVucmVmKCk7XG5cbiAgY29uc3QgcG9ydCA9IGF3YWl0IGxpc3Rlbk9uRnJlZUxvb3BiYWNrUG9ydChzZXJ2ZXIpO1xuICByZXR1cm4ge1xuICAgIGNsb3NlKCk6IHZvaWQge1xuICAgICAgc2VydmVyLmNsb3NlKCk7XG4gICAgfSxcbiAgICBwb3J0XG4gIH07XG59XG5cbi8qKlxuICogQmluZHMgdGhlIHNlcnZlciB0byBhbiBlcGhlbWVyYWwgbG9vcGJhY2sgcG9ydCBhbmQgcmVwb3J0cyB3aGljaCBvbmUgaXQgZ290LlxuICpcbiAqIEBwYXJhbSBzZXJ2ZXIgLSBUaGUgc2VydmVyIHRvIGJpbmQuXG4gKiBAcmV0dXJucyBBIHtAbGluayBQcm9taXNlfSByZXNvbHZpbmcgdG8gdGhlIGFzc2lnbmVkIHBvcnQuXG4gKiBAdGhyb3dzIElmIHRoZSBzZXJ2ZXIgcmVwb3J0cyBhbiBlcnJvciBiZWZvcmUgbGlzdGVuaW5nLCBvciBiaW5kcyB0byBhIHBpcGUgcmF0aGVyIHRoYW4gYSBwb3J0LlxuICovXG5hc3luYyBmdW5jdGlvbiBsaXN0ZW5PbkZyZWVMb29wYmFja1BvcnQoc2VydmVyOiBTZXJ2ZXIpOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gbmV3IFByb21pc2U8bnVtYmVyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgc2VydmVyLm9uY2UoJ2Vycm9yJywgcmVqZWN0KTtcbiAgICBzZXJ2ZXIubGlzdGVuKDAsIFBBUkVOVF9MSVZFTkVTU19IT1NULCAoKSA9PiB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICAgIGlmIChhZGRyZXNzID09PSBudWxsIHx8IHR5cGVvZiBhZGRyZXNzID09PSAnc3RyaW5nJykge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcignRmFpbGVkIHRvIGRldGVybWluZSB0aGUgcGFyZW50LWxpdmVuZXNzIHBvcnQuJykpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICByZXNvbHZlKGFkZHJlc3MucG9ydCk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFnRUEsc0JBQTZCO0FBMkJ0QixNQUFNLHVCQUF1QjtBQVdwQyxNQUFNLDBCQUEwQjtBQVFoQyxNQUFNLGtDQUFrQztBQWlCakMsU0FBUyxzQ0FBc0MsTUFBc0I7QUFDMUUsU0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLGVBYU0sT0FBTyxJQUFJLENBQUM7QUFBQSxnQkFDWCxvQkFBb0I7QUFBQSxrQ0FDRixPQUFPLHVCQUF1QixDQUFDO0FBQUEsMENBQ3ZCLE9BQU8sK0JBQStCLENBQUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQStDakY7QUFZQSxlQUFzQiw0QkFBMkQ7QUFDL0UsUUFBTSxhQUFTLDhCQUFhLENBQUMsV0FBVztBQUN0QyxXQUFPLE1BQU07QUFFYixXQUFPLEdBQUcsU0FBUyxNQUFNO0FBQUEsSUFFekIsQ0FBQztBQUFBLEVBQ0gsQ0FBQztBQUNELFNBQU8sTUFBTTtBQUViLFFBQU0sT0FBTyxNQUFNLHlCQUF5QixNQUFNO0FBQ2xELFNBQU87QUFBQSxJQUNMLFFBQWM7QUFDWixhQUFPLE1BQU07QUFBQSxJQUNmO0FBQUEsSUFDQTtBQUFBLEVBQ0Y7QUFDRjtBQVNBLGVBQWUseUJBQXlCLFFBQWlDO0FBQ3ZFLFNBQU8sSUFBSSxRQUFnQixDQUFDLFNBQVMsV0FBVztBQUM5QyxXQUFPLEtBQUssU0FBUyxNQUFNO0FBQzNCLFdBQU8sT0FBTyxHQUFHLHNCQUFzQixNQUFNO0FBQzNDLFlBQU0sVUFBVSxPQUFPLFFBQVE7QUFDL0IsVUFBSSxZQUFZLFFBQVEsT0FBTyxZQUFZLFVBQVU7QUFDbkQsZUFBTyxNQUFNO0FBQ2IsZUFBTyxJQUFJLE1BQU0sK0NBQStDLENBQUM7QUFDakU7QUFBQSxNQUNGO0FBQ0EsY0FBUSxRQUFRLElBQUk7QUFBQSxJQUN0QixDQUFDO0FBQUEsRUFDSCxDQUFDO0FBQ0g7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -24,11 +24,37 @@
24
24
  * So we use the one cross-platform resource the kernel *does* reclaim
25
25
  * deterministically on process death: a socket. The harness listens on a
26
26
  * loopback port and the instance's renderer connects to it. However the harness
27
- * dies — cleanly, `SIGKILL`ed, or crashed — the kernel closes its end, the
28
- * renderer sees `close`, and the window destroys itself. No polling, no
29
- * heartbeat interval, no timeout to tune.
27
+ * dies — cleanly, `SIGKILL`ed, or crashed — the kernel closes its end and the
28
+ * renderer sees `close`. No polling, no heartbeat interval, no timeout to tune.
30
29
  *
31
- * Deliberately fail-open: the renderer only arms the destroy handler after the
30
+ * **A close is a question, not a verdict.** A socket closing is not the same
31
+ * event as a process dying, and treating them as identical destroyed healthy
32
+ * instances: measured on 2026-09-05, a renderer's idle liveness socket sent
33
+ * `FIN` on its own — 3 min 13 s into one run, 11 min 56 s into another — while
34
+ * the harness was still listening and went on working for another 14 minutes.
35
+ * Every test file scheduled after the death then failed in tens of milliseconds
36
+ * with `ECONNREFUSED` on the dead CDP port; the worst run reported 156 such
37
+ * failures across 21 files, not one of them a test result. Why an idle unref'd
38
+ * loopback socket in an Electron renderer does that is not established, and does
39
+ * not need to be: the lifetimes vary run to run, so no fixed timeout explains it.
40
+ *
41
+ * So the `close` handler **verifies before destroying**: it reconnects to the
42
+ * same loopback port. A harness that is alive is still listening, so the
43
+ * reconnect succeeds and the new socket becomes the liveness token; only when
44
+ * nothing answers after a few tries — what a dead harness actually looks like —
45
+ * is the window destroyed. The leak the watchdog exists to prevent is still
46
+ * prevented, and the measured recovery is 11 ms.
47
+ *
48
+ * A reconnect rather than a check on the harness's process id, because it proves
49
+ * the thing the watchdog actually depends on — the liveness server still serving
50
+ * — and it stays correct against a *busy* harness: the kernel completes a
51
+ * loopback handshake out of the listen backlog even while Node's event loop is
52
+ * blocked. Its one residual ambiguity is accepted: a reconnect proves *something*
53
+ * is listening on that ephemeral port, not that it is ours. The probe follows the
54
+ * close by milliseconds, so another process winning that exact port in between is
55
+ * not a risk worth a handshake protocol.
56
+ *
57
+ * Deliberately fail-open: the renderer only arms the destroy path after the
32
58
  * connection is actually established. A watchdog that cannot reach the harness
33
59
  * leaves the instance running rather than killing a window the developer is
34
60
  * working in.
@@ -39,7 +65,13 @@
39
65
  */
40
66
  export interface ParentLivenessServer {
41
67
  /**
42
- Stops listening and drops every accepted connection.
68
+ * Stops listening.
69
+ *
70
+ * Node keeps already-accepted connections alive across a `close()`, so this
71
+ * does not by itself signal the renderer — the kernel reclaiming the socket on
72
+ * process death is what does. What it does guarantee is that a watchdog probe
73
+ * arriving afterwards is refused, which is the answer a torn-down harness
74
+ * should give.
43
75
  */
44
76
  close(): void;
45
77
  /**
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var port_owner_exports = {};
20
+ __export(port_owner_exports, {
21
+ parsePosixLsofPids: () => parsePosixLsofPids,
22
+ parseWindowsNetstatPids: () => parseWindowsNetstatPids
23
+ });
24
+ module.exports = __toCommonJS(port_owner_exports);
25
+ const LISTENING_STATE = "LISTENING";
26
+ const RADIX_DECIMAL = 10;
27
+ const TCP_PROTOCOL = "TCP";
28
+ const WHITESPACE_PATTERN = /\s+/;
29
+ function parsePosixLsofPids(lsofOutput) {
30
+ const pids = [];
31
+ for (const line of lsofOutput.split("\n")) {
32
+ const pid = Number.parseInt(line.trim(), RADIX_DECIMAL);
33
+ if (Number.isNaN(pid) || pids.includes(pid)) {
34
+ continue;
35
+ }
36
+ pids.push(pid);
37
+ }
38
+ return pids;
39
+ }
40
+ function parseWindowsNetstatPids(params) {
41
+ const localAddressSuffix = `:${String(params.port)}`;
42
+ const pids = [];
43
+ for (const rawLine of params.netstatOutput.split("\n")) {
44
+ const [protocol = "", localAddress = "", , state = "", rawPid = ""] = rawLine.trim().split(WHITESPACE_PATTERN);
45
+ if (protocol !== TCP_PROTOCOL || state !== LISTENING_STATE || !localAddress.endsWith(localAddressSuffix)) {
46
+ continue;
47
+ }
48
+ const pid = Number.parseInt(rawPid, RADIX_DECIMAL);
49
+ if (Number.isNaN(pid) || pids.includes(pid)) {
50
+ continue;
51
+ }
52
+ pids.push(pid);
53
+ }
54
+ return pids;
55
+ }
56
+ // Annotate the CommonJS export names for ESM import in node:
57
+ 0 && (module.exports = {
58
+ parsePosixLsofPids,
59
+ parseWindowsNetstatPids
60
+ });
61
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3BvcnQtb3duZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBQdXJlIGhlbHBlcnMgZm9yIGFuc3dlcmluZyBcIndoaWNoIHByb2Nlc3MgaXMgc3RpbGwgaG9sZGluZyB0aGlzIHBvcnQ/XCIuXG4gKlxuICogQSB0ZWFyZG93biB0aGF0IGNhbm5vdCBhbnN3ZXIgdGhhdCBxdWVzdGlvbiBjYW4gb25seSByZS1pc3N1ZSB0aGUgc2FtZSBraWxsIGF0XG4gKiB0aGUgc2FtZSBQSUQsIHdoaWNoIGlzIG5vIGVzY2FsYXRpb24gYXQgYWxsOiB0aGUgUElEIHRoZSBoYXJuZXNzIGhvbGRzIGlzIHRoZVxuICogc2hlbGwgd3JhcHBlciBpdCBzcGF3bmVkLCBhbmQgd2hhdCBzdXJ2aXZlcyBpcyB3aGF0ZXZlciB0aGF0IHdyYXBwZXIncyB0cmVlXG4gKiB3YWxrIGZhaWxlZCB0byByZWFjaC4gVGhlIHBvcnQsIGJ5IGNvbnRyYXN0LCBpcyBkaXJlY3QgZXZpZGVuY2UgXHUyMDE0IGEgc29ja2V0XG4gKiBzdGlsbCBhbnN3ZXJpbmcgb24gNDcyMyBhZnRlciB0aGlzIHJ1biBraWxsZWQgdGhlIHNlcnZlciBpdCBzdGFydGVkIGJlbG9uZ3MgdG9cbiAqIHRoYXQgc2VydmVyLlxuICpcbiAqIEtlcHQgc2VwYXJhdGUgZnJvbSB0aGUgaW50ZWdyYXRpb24tb25seSBgdHJhbnNwb3J0LWZhY3RvcnlgIHNvIHRoZSBwYXJzaW5nXG4gKiBzdGF5cyB1bml0LXRlc3RhYmxlOyB0aGUgZmFjdG9yeSBzaGVsbHMgb3V0IHRvIGBuZXRzdGF0YCAvIGBsc29mYC5cbiAqL1xuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBwYXJzZVdpbmRvd3NOZXRzdGF0UGlkc30uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VXaW5kb3dzTmV0c3RhdFBpZHNQYXJhbXMge1xuICAvKipcbiAgUmF3IHN0ZG91dCBvZiBgbmV0c3RhdCAtYW5vYC5cbiAgICovXG4gIHJlYWRvbmx5IG5ldHN0YXRPdXRwdXQ6IHN0cmluZztcblxuICAvKipcbiAgVGhlIGxvY2FsIHBvcnQgd2hvc2UgbGlzdGVuZXIgaXMgd2FudGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xufVxuXG5jb25zdCBMSVNURU5JTkdfU1RBVEUgPSAnTElTVEVOSU5HJztcbmNvbnN0IFJBRElYX0RFQ0lNQUwgPSAxMDtcbmNvbnN0IFRDUF9QUk9UT0NPTCA9ICdUQ1AnO1xuY29uc3QgV0hJVEVTUEFDRV9QQVRURVJOID0gL1xccysvO1xuXG4vKipcbiAqIFBhcnNlcyBgbHNvZiAtdGkgdGNwOjxwb3J0PmAgb3V0cHV0LCB3aGljaCBpcyBhbHJlYWR5IG9uZSBQSUQgcGVyIGxpbmUuXG4gKlxuICogQHBhcmFtIGxzb2ZPdXRwdXQgLSBSYXcgc3Rkb3V0IG9mIHRoZSBgbHNvZmAgcXVlcnkuXG4gKiBAcmV0dXJucyBUaGUgZGlzdGluY3QgUElEcywgaW4gbGlzdGVkIG9yZGVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VQb3NpeExzb2ZQaWRzKGxzb2ZPdXRwdXQ6IHN0cmluZyk6IG51bWJlcltdIHtcbiAgY29uc3QgcGlkczogbnVtYmVyW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGxpbmUgb2YgbHNvZk91dHB1dC5zcGxpdCgnXFxuJykpIHtcbiAgICBjb25zdCBwaWQgPSBOdW1iZXIucGFyc2VJbnQobGluZS50cmltKCksIFJBRElYX0RFQ0lNQUwpO1xuICAgIGlmIChOdW1iZXIuaXNOYU4ocGlkKSB8fCBwaWRzLmluY2x1ZGVzKHBpZCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cblxuICAgIHBpZHMucHVzaChwaWQpO1xuICB9XG5cbiAgcmV0dXJuIHBpZHM7XG59XG5cbi8qKlxuICogUGFyc2VzIGBuZXRzdGF0IC1hbm9gIG91dHB1dCBmb3IgdGhlIFBJRHMgKipsaXN0ZW5pbmcqKiBvbiBhIHBvcnQuXG4gKlxuICogT25seSBgVENQYCByb3dzIGluIHRoZSBgTElTVEVOSU5HYCBzdGF0ZSBjb3VudDogYW4gZXN0YWJsaXNoZWQgY29ubmVjdGlvbiAqdG8qXG4gKiB0aGUgcG9ydCBiZWxvbmdzIHRvIGEgY2xpZW50LCBub3QgdG8gdGhlIHNlcnZlciB0aGF0IG11c3QgZGllLCBhbmQgdGhlIGBVRFBgXG4gKiByb3dzIGhhdmUgbm8gc3RhdGUgY29sdW1uIGF0IGFsbC4gVGhlIHNhbWUgc2VydmVyIGFwcGVhcnMgdHdpY2Ugd2hlbiBpdCBiaW5kc1xuICogYm90aCBJUHY0IGFuZCBJUHY2LCBzbyBQSURzIGFyZSBkZS1kdXBsaWNhdGVkLlxuICpcbiAqIEBwYXJhbSBwYXJhbXMgLSBUaGUgbGlzdGluZyBvdXRwdXQgYW5kIHRoZSBwb3J0IHRvIG1hdGNoLlxuICogQHJldHVybnMgVGhlIGRpc3RpbmN0IGxpc3RlbmluZyBQSURzLCBpbiBsaXN0ZWQgb3JkZXIuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVdpbmRvd3NOZXRzdGF0UGlkcyhwYXJhbXM6IFBhcnNlV2luZG93c05ldHN0YXRQaWRzUGFyYW1zKTogbnVtYmVyW10ge1xuICBjb25zdCBsb2NhbEFkZHJlc3NTdWZmaXggPSBgOiR7U3RyaW5nKHBhcmFtcy5wb3J0KX1gO1xuICBjb25zdCBwaWRzOiBudW1iZXJbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgcmF3TGluZSBvZiBwYXJhbXMubmV0c3RhdE91dHB1dC5zcGxpdCgnXFxuJykpIHtcbiAgICBjb25zdCBbcHJvdG9jb2wgPSAnJywgbG9jYWxBZGRyZXNzID0gJycsICwgc3RhdGUgPSAnJywgcmF3UGlkID0gJyddID0gcmF3TGluZS50cmltKCkuc3BsaXQoV0hJVEVTUEFDRV9QQVRURVJOKTtcbiAgICBpZiAocHJvdG9jb2wgIT09IFRDUF9QUk9UT0NPTCB8fCBzdGF0ZSAhPT0gTElTVEVOSU5HX1NUQVRFIHx8ICFsb2NhbEFkZHJlc3MuZW5kc1dpdGgobG9jYWxBZGRyZXNzU3VmZml4KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgY29uc3QgcGlkID0gTnVtYmVyLnBhcnNlSW50KHJhd1BpZCwgUkFESVhfREVDSU1BTCk7XG4gICAgaWYgKE51bWJlci5pc05hTihwaWQpIHx8IHBpZHMuaW5jbHVkZXMocGlkKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgcGlkcy5wdXNoKHBpZCk7XG4gIH1cblxuICByZXR1cm4gcGlkcztcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQStCQSxNQUFNLGtCQUFrQjtBQUN4QixNQUFNLGdCQUFnQjtBQUN0QixNQUFNLGVBQWU7QUFDckIsTUFBTSxxQkFBcUI7QUFRcEIsU0FBUyxtQkFBbUIsWUFBOEI7QUFDL0QsUUFBTSxPQUFpQixDQUFDO0FBRXhCLGFBQVcsUUFBUSxXQUFXLE1BQU0sSUFBSSxHQUFHO0FBQ3pDLFVBQU0sTUFBTSxPQUFPLFNBQVMsS0FBSyxLQUFLLEdBQUcsYUFBYTtBQUN0RCxRQUFJLE9BQU8sTUFBTSxHQUFHLEtBQUssS0FBSyxTQUFTLEdBQUcsR0FBRztBQUMzQztBQUFBLElBQ0Y7QUFFQSxTQUFLLEtBQUssR0FBRztBQUFBLEVBQ2Y7QUFFQSxTQUFPO0FBQ1Q7QUFhTyxTQUFTLHdCQUF3QixRQUFpRDtBQUN2RixRQUFNLHFCQUFxQixJQUFJLE9BQU8sT0FBTyxJQUFJLENBQUM7QUFDbEQsUUFBTSxPQUFpQixDQUFDO0FBRXhCLGFBQVcsV0FBVyxPQUFPLGNBQWMsTUFBTSxJQUFJLEdBQUc7QUFDdEQsVUFBTSxDQUFDLFdBQVcsSUFBSSxlQUFlLElBQUksRUFBRSxRQUFRLElBQUksU0FBUyxFQUFFLElBQUksUUFBUSxLQUFLLEVBQUUsTUFBTSxrQkFBa0I7QUFDN0csUUFBSSxhQUFhLGdCQUFnQixVQUFVLG1CQUFtQixDQUFDLGFBQWEsU0FBUyxrQkFBa0IsR0FBRztBQUN4RztBQUFBLElBQ0Y7QUFFQSxVQUFNLE1BQU0sT0FBTyxTQUFTLFFBQVEsYUFBYTtBQUNqRCxRQUFJLE9BQU8sTUFBTSxHQUFHLEtBQUssS0FBSyxTQUFTLEdBQUcsR0FBRztBQUMzQztBQUFBLElBQ0Y7QUFFQSxTQUFLLEtBQUssR0FBRztBQUFBLEVBQ2Y7QUFFQSxTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbXQp9Cg==
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Pure helpers for answering "which process is still holding this port?".
5
+ *
6
+ * A teardown that cannot answer that question can only re-issue the same kill at
7
+ * the same PID, which is no escalation at all: the PID the harness holds is the
8
+ * shell wrapper it spawned, and what survives is whatever that wrapper's tree
9
+ * walk failed to reach. The port, by contrast, is direct evidence — a socket
10
+ * still answering on 4723 after this run killed the server it started belongs to
11
+ * that server.
12
+ *
13
+ * Kept separate from the integration-only `transport-factory` so the parsing
14
+ * stays unit-testable; the factory shells out to `netstat` / `lsof`.
15
+ */
16
+ /**
17
+ * Parameters for {@link parseWindowsNetstatPids}.
18
+ */
19
+ export interface ParseWindowsNetstatPidsParams {
20
+ /**
21
+ Raw stdout of `netstat -ano`.
22
+ */
23
+ readonly netstatOutput: string;
24
+ /**
25
+ The local port whose listener is wanted.
26
+ */
27
+ readonly port: number;
28
+ }
29
+ /**
30
+ * Parses `lsof -ti tcp:<port>` output, which is already one PID per line.
31
+ *
32
+ * @param lsofOutput - Raw stdout of the `lsof` query.
33
+ * @returns The distinct PIDs, in listed order.
34
+ */
35
+ export declare function parsePosixLsofPids(lsofOutput: string): number[];
36
+ /**
37
+ * Parses `netstat -ano` output for the PIDs **listening** on a port.
38
+ *
39
+ * Only `TCP` rows in the `LISTENING` state count: an established connection *to*
40
+ * the port belongs to a client, not to the server that must die, and the `UDP`
41
+ * rows have no state column at all. The same server appears twice when it binds
42
+ * both IPv4 and IPv6, so PIDs are de-duplicated.
43
+ *
44
+ * @param params - The listing output and the port to match.
45
+ * @returns The distinct listening PIDs, in listed order.
46
+ */
47
+ export declare function parseWindowsNetstatPids(params: ParseWindowsNetstatPidsParams): number[];
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var process_capture_exports = {};
20
+ __export(process_capture_exports, {
21
+ attachProcessCapture: () => attachProcessCapture
22
+ });
23
+ module.exports = __toCommonJS(process_capture_exports);
24
+ function attachProcessCapture(child, params) {
25
+ const { maxOutputLengthInCharacters, onChunk } = params;
26
+ let capturedOutput = "";
27
+ let exitInfo;
28
+ let isCapturing = true;
29
+ attachStream(child.stdout, "stdout");
30
+ attachStream(child.stderr, "stderr");
31
+ child.once("exit", (code, signal) => {
32
+ exitInfo = { code, signal };
33
+ });
34
+ child.once("error", (error) => {
35
+ exitInfo = { code: null, signal: null, spawnError: error.message };
36
+ });
37
+ return {
38
+ readExitInfo: () => exitInfo,
39
+ readOutput: () => capturedOutput,
40
+ stopCapture: () => {
41
+ isCapturing = false;
42
+ }
43
+ };
44
+ function attachStream(stream, name) {
45
+ if (!stream) {
46
+ return;
47
+ }
48
+ stream.on("data", (chunk) => {
49
+ const text = chunk.toString();
50
+ onChunk?.({ stream: name, text });
51
+ if (isCapturing) {
52
+ capturedOutput = (capturedOutput + text).slice(-maxOutputLengthInCharacters);
53
+ }
54
+ });
55
+ stream.unref?.();
56
+ }
57
+ }
58
+ // Annotate the CommonJS export names for ESM import in node:
59
+ 0 && (module.exports = {
60
+ attachProcessCapture
61
+ });
62
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtY2FwdHVyZS50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLyoqXG4gKiBAZmlsZVxuICpcbiAqIEF0dGFjaGVzIG91dHB1dCBjYXB0dXJlIGFuZCBleGl0IG9ic2VydmF0aW9uIHRvIGEgc3Bhd25lZCBjaGlsZCBwcm9jZXNzLlxuICpcbiAqIEEgbG9uZy1ydW5uaW5nIGNoaWxkIHNwYXduZWQgd2l0aCBwaXBlZCBzdGRpbyBuZWVkcyB0aHJlZSB0aGluZ3MgZG9uZSB0byBpdCxcbiAqIGFuZCBnZXR0aW5nIGFueSBvZiB0aGVtIHdyb25nIGlzIGl0cyBvd24gYnVnOiBpdHMgcGlwZXMgbXVzdCBiZSAqKmRyYWluZWQqKlxuICogKGEgZnVsbCBPUyBwaXBlIGJ1ZmZlciBibG9ja3MgdGhlIHdyaXRlciBcdTIwMTQgYSBjaGF0dHkgcmVuZGVyZXIgd291bGQgaGFuZyB0aGVcbiAqIGFwcCBpdCBiZWxvbmdzIHRvKSwgaXRzIG91dHB1dCBtdXN0IGJlIGtlcHQgKipib3VuZGVkKiogKGFuIGhvdXIgb2YgbG9ncyBpc1xuICogbm90IGEgZGlhZ25vc3RpYyksIGFuZCBpdHMgYGV4aXRgIC8gYGVycm9yYCBtdXN0IGJlICoqcmVjb3JkZWQqKiBzbyBhIGNhbGxlclxuICogdGhhdCBsYXRlciBmaW5kcyB0aGUgcHJvY2VzcyB1bnJlYWNoYWJsZSBjYW4gc2F5IHdoeSBpbnN0ZWFkIG9mIGd1ZXNzaW5nLlxuICpcbiAqIEV4dHJhY3RlZCBzbyB0aGUgc3RhdGUgbWFjaGluZSBpcyB1bml0LXRlc3RhYmxlOiB0aGUgbGF1bmNoZXJzIHRoYXQgdXNlIGl0XG4gKiAoYG9ic2lkaWFuLWluc3RhbmNlLnRzYCwgYW5kIHRoZSBlbXVsYXRvci9BcHBpdW0gc3Bhd25zIGluXG4gKiBgdHJhbnNwb3J0LWZhY3RvcnkudHNgKSBhcmUgaW50ZWdyYXRpb24tdGltZSBnbHVlIGV4Y2x1ZGVkIGZyb20gdW5pdCB0ZXN0cyxcbiAqIHdoaWNoIGlzIGhvdyB0aGUgb3duZWQgT2JzaWRpYW4gaW5zdGFuY2UgY2FtZSB0byBiZSBzcGF3bmVkIGBzdGRpbzogJ2lnbm9yZSdgXG4gKiB3aXRoIG5vIGBleGl0YCBsaXN0ZW5lciBhdCBhbGwgXHUyMDE0IGl0cyBkZWF0aCB3YXMgdW5vYnNlcnZhYmxlIGJ5IGNvbnN0cnVjdGlvbi5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IENoaWxkUHJvY2VzcyB9IGZyb20gJ25vZGU6Y2hpbGRfcHJvY2Vzcyc7XG5pbXBvcnQgdHlwZSB7IFJlYWRhYmxlIH0gZnJvbSAnbm9kZTpzdHJlYW0nO1xuXG5pbXBvcnQgdHlwZSB7IFByb2Nlc3NFeGl0SW5mbyB9IGZyb20gJy4vcHJvY2Vzcy1leGl0LW1lc3NhZ2UuY2pzJztcblxuLyoqXG4gKiBQYXJhbWV0ZXJzIGZvciB7QGxpbmsgYXR0YWNoUHJvY2Vzc0NhcHR1cmV9LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF0dGFjaFByb2Nlc3NDYXB0dXJlUGFyYW1zIHtcbiAgLyoqXG4gICAqIEhvdyBtYW55IGNoYXJhY3RlcnMgb2YgdGhlIG1vc3QgcmVjZW50IG91dHB1dCB0byBrZWVwLiBPbGRlciBvdXRwdXQgaXNcbiAgICogZHJvcHBlZCBmcm9tIHRoZSBmcm9udCBhcyBuZXcgb3V0cHV0IGFycml2ZXMuXG4gICAqL1xuICByZWFkb25seSBtYXhPdXRwdXRMZW5ndGhJbkNoYXJhY3RlcnM6IG51bWJlcjtcblxuICAvKipcbiAgICogQ2FsbGVkIGZvciBldmVyeSBjaHVuayBhcyBpdCBhcnJpdmVzLCBmb3IgY2FsbGVycyB0aGF0IHdhbnQgdGhlIG91dHB1dFxuICAgKiAqKmxpdmUqKiAobG9nZ2VkIGFzIHRoZSBwcm9jZXNzIHJ1bnMpIHJhdGhlciB0aGFuIG9ubHkgYXMgYSBwb3N0LW1vcnRlbVxuICAgKiB0YWlsLiBGaXJlcyByZWdhcmRsZXNzIG9mIHtAbGluayBQcm9jZXNzQ2FwdHVyZS5zdG9wQ2FwdHVyZX0sIHdoaWNoIGZyZWV6ZXNcbiAgICogdGhlIHJldGFpbmVkIHRhaWwgYW5kIG5vdGhpbmcgZWxzZS5cbiAgICovXG4gIHJlYWRvbmx5IG9uQ2h1bms/OiAoKGNodW5rOiBQcm9jZXNzT3V0cHV0Q2h1bmspID0+IHZvaWQpIHwgdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEEgY2hpbGQgcHJvY2VzcydzIGNhcHR1cmVkIG91dHB1dCBhbmQgZXhpdCBzdGF0dXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0NhcHR1cmUge1xuICAvKipcbiAgUmV0dXJucyB0aGUgZXhpdCAvIHNwYXduLWZhaWx1cmUgZGV0YWlscyBvbmNlIHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLCBvdGhlcndpc2UgYHVuZGVmaW5lZGAuXG4gICAqL1xuICByZWFkRXhpdEluZm86ICgpID0+IFByb2Nlc3NFeGl0SW5mbyB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgUmV0dXJucyB0aGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciwgYm91bmRlZCB0byB0aGUgbW9zdCByZWNlbnQgb3V0cHV0LlxuICAgKi9cbiAgcmVhZE91dHB1dDogKCkgPT4gc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTdG9wcyBhY2N1bXVsYXRpbmcgb3V0cHV0LCBmcmVlemluZyB0aGUgdGFpbCBhdCB3aGF0IGhhcyBhcnJpdmVkIHNvIGZhci5cbiAgICogQ2FsbCBvbmNlIHN0YXJ0dXAgaGFzIHN1Y2NlZWRlZCBhbmQgdGhlIHRhaWwgaGFzIHNlcnZlZCBpdHMgcHVycG9zZS5cbiAgICpcbiAgICogVGhlIGBkYXRhYCBsaXN0ZW5lcnMgc3RheSBhdHRhY2hlZCBkZWxpYmVyYXRlbHksIHNvIHRoZSBwaXBlcyBrZWVwIGRyYWluaW5nXG4gICAqIGZvciB0aGUgcmVzdCBvZiB0aGUgcHJvY2VzcydzIGxpZmUuXG4gICAqL1xuICBzdG9wQ2FwdHVyZTogKCkgPT4gdm9pZDtcbn1cblxuLyoqXG4gKiBPbmUgY2h1bmsgb2YgYSBjaGlsZCBwcm9jZXNzJ3Mgb3V0cHV0LCBhbmQgd2hpY2ggc3RyZWFtIGl0IGNhbWUgZnJvbS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzT3V0cHV0Q2h1bmsge1xuICAvKipcbiAgVGhlIHN0cmVhbSB0aGUgY2h1bmsgd2FzIHdyaXR0ZW4gdG8uXG4gICAqL1xuICByZWFkb25seSBzdHJlYW06ICdzdGRlcnInIHwgJ3N0ZG91dCc7XG5cbiAgLyoqXG4gIFRoZSBjaHVuaydzIHRleHQuXG4gICAqL1xuICByZWFkb25seSB0ZXh0OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIGB1bnJlZmAgYSBwaXBlZCBzdGRpbyBzdHJlYW0gY2FycmllcyB0aHJvdWdoIGl0cyB1bmRlcmx5aW5nIHNvY2tldCwgd2hpY2hcbiAqIGBSZWFkYWJsZWAgYWxvbmUgZG9lcyBub3QgZGVjbGFyZS5cbiAqL1xuaW50ZXJmYWNlIFN0cmVhbVdpdGhVbnJlZiB7XG4gIHVucmVmOiAoKSA9PiB2b2lkO1xufVxuXG4vKipcbiAqIEF0dGFjaGVzIG91dHB1dCBjYXB0dXJlIGFuZCBleGl0IG9ic2VydmF0aW9uIHRvIGFuIGFscmVhZHktc3Bhd25lZCBwcm9jZXNzLlxuICpcbiAqIFRvbGVyYXRlcyBhIHByb2Nlc3Mgc3Bhd25lZCB3aXRob3V0IHBpcGVzIChgc3RkaW86ICdpZ25vcmUnYCBsZWF2ZXNcbiAqIGBzdGRvdXRgIC8gYHN0ZGVycmAgYG51bGxgKTogdGhlIGV4aXQgaGFsZiBzdGlsbCB3b3JrcywgYW5kIHRoZSBjYXB0dXJlZFxuICogb3V0cHV0IHN0YXlzIGVtcHR5LlxuICpcbiAqIEBwYXJhbSBjaGlsZCAtIFRoZSBzcGF3bmVkIHByb2Nlc3MuXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHRhaWwgYnVkZ2V0LCBhbmQgYW4gb3B0aW9uYWwgbGl2ZS1vdXRwdXQgY2FsbGJhY2suXG4gKiBAcmV0dXJucyBSZWFkZXJzIGZvciB0aGUgY2FwdHVyZWQgb3V0cHV0IGFuZCB0aGUgZXhpdCBzdGF0dXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhdHRhY2hQcm9jZXNzQ2FwdHVyZShjaGlsZDogQ2hpbGRQcm9jZXNzLCBwYXJhbXM6IEF0dGFjaFByb2Nlc3NDYXB0dXJlUGFyYW1zKTogUHJvY2Vzc0NhcHR1cmUge1xuICBjb25zdCB7IG1heE91dHB1dExlbmd0aEluQ2hhcmFjdGVycywgb25DaHVuayB9ID0gcGFyYW1zO1xuXG4gIGxldCBjYXB0dXJlZE91dHB1dCA9ICcnO1xuICBsZXQgZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyB8IHVuZGVmaW5lZDtcbiAgbGV0IGlzQ2FwdHVyaW5nID0gdHJ1ZTtcblxuICBhdHRhY2hTdHJlYW0oY2hpbGQuc3Rkb3V0LCAnc3Rkb3V0Jyk7XG4gIGF0dGFjaFN0cmVhbShjaGlsZC5zdGRlcnIsICdzdGRlcnInKTtcblxuICBjaGlsZC5vbmNlKCdleGl0JywgKGNvZGU6IG51bGwgfCBudW1iZXIsIHNpZ25hbDogTm9kZUpTLlNpZ25hbHMgfCBudWxsKSA9PiB7XG4gICAgZXhpdEluZm8gPSB7IGNvZGUsIHNpZ25hbCB9O1xuICB9KTtcblxuICAvKlxuICAgKiBBIHNwYXduIGZhaWx1cmUgKGUuZy4gRU5PRU5UIGZvciBhIG1pc3NpbmcgYmluYXJ5KSBlbWl0cyAnZXJyb3InLCBub3RcbiAgICogJ2V4aXQnLiBSZWNvcmQgaXQgYXMgYSBzeW50aGV0aWMgZXhpdCBzbyBhIGNhbGxlciBwb2xsaW5nIGZvciByZWFkaW5lc3MgY2FuXG4gICAqIGZhaWwgZmFzdCBpbnN0ZWFkIG9mIHNwaW5uaW5nIG91dCBpdHMgd2hvbGUgYnVkZ2V0IGFnYWluc3QgYSBwcm9jZXNzIHRoYXRcbiAgICogbmV2ZXIgZXhpc3RlZC5cbiAgICovXG4gIGNoaWxkLm9uY2UoJ2Vycm9yJywgKGVycm9yOiBFcnJvcikgPT4ge1xuICAgIGV4aXRJbmZvID0geyBjb2RlOiBudWxsLCBzaWduYWw6IG51bGwsIHNwYXduRXJyb3I6IGVycm9yLm1lc3NhZ2UgfTtcbiAgfSk7XG5cbiAgcmV0dXJuIHtcbiAgICByZWFkRXhpdEluZm86ICgpID0+IGV4aXRJbmZvLFxuICAgIHJlYWRPdXRwdXQ6ICgpID0+IGNhcHR1cmVkT3V0cHV0LFxuICAgIHN0b3BDYXB0dXJlOiAoKTogdm9pZCA9PiB7XG4gICAgICBpc0NhcHR1cmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfTtcblxuICBmdW5jdGlvbiBhdHRhY2hTdHJlYW0oc3RyZWFtOiBudWxsIHwgUmVhZGFibGUsIG5hbWU6IFByb2Nlc3NPdXRwdXRDaHVua1snc3RyZWFtJ10pOiB2b2lkIHtcbiAgICBpZiAoIXN0cmVhbSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHN0cmVhbS5vbignZGF0YScsIChjaHVuazogQnVmZmVyKSA9PiB7XG4gICAgICBjb25zdCB0ZXh0ID0gY2h1bmsudG9TdHJpbmcoKTtcbiAgICAgIG9uQ2h1bms/Lih7IHN0cmVhbTogbmFtZSwgdGV4dCB9KTtcbiAgICAgIGlmIChpc0NhcHR1cmluZykge1xuICAgICAgICBjYXB0dXJlZE91dHB1dCA9IChjYXB0dXJlZE91dHB1dCArIHRleHQpLnNsaWNlKC1tYXhPdXRwdXRMZW5ndGhJbkNoYXJhY3RlcnMpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLypcbiAgICAgKiBgY2hpbGQudW5yZWYoKWAgb25seSByZWxlYXNlcyB0aGUgcHJvY2VzcyBoYW5kbGU7IHRoZSBzdGRpbyBwaXBlcyBhcmVcbiAgICAgKiBzZXBhcmF0ZSBoYW5kbGVzIHRoYXQga2VlcCB0aGUgZXZlbnQgbG9vcCBhbGl2ZSBvbiB0aGVpciBvd24uIEEgaGFybmVzc1xuICAgICAqIHRoYXQgcGlwZXMgYSBkZXRhY2hlZCBjaGlsZCdzIG91dHB1dCB3b3VsZCB0aGVuIHJlZnVzZSB0byBleGl0IHVudGlsIHRoYXRcbiAgICAgKiBjaGlsZCBkaWVkIFx1MjAxNCB0aGUgb3Bwb3NpdGUgb2Ygd2hhdCBgZGV0YWNoZWRgICsgYHVucmVmYCB3YXMgYXNrZWQgZm9yLlxuICAgICAqXG4gICAgICogYHVucmVmYCBsaXZlcyBvbiB0aGUgdW5kZXJseWluZyBzb2NrZXQgcmF0aGVyIHRoYW4gb24gYFJlYWRhYmxlYCwgc28gaXQgaXNcbiAgICAgKiByZWFjaGVkIHN0cnVjdHVyYWxseTogYSBzdHJlYW0gdGhhdCBkb2VzIG5vdCBjYXJyeSBvbmUgc2ltcGx5IHNraXBzIHRoaXMuXG4gICAgICovXG4gICAgKHN0cmVhbSBhcyBQYXJ0aWFsPFN0cmVhbVdpdGhVbnJlZj4pLnVucmVmPy4oKTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXFHTyxTQUFTLHFCQUFxQixPQUFxQixRQUFvRDtBQUM1RyxRQUFNLEVBQUUsNkJBQTZCLFFBQVEsSUFBSTtBQUVqRCxNQUFJLGlCQUFpQjtBQUNyQixNQUFJO0FBQ0osTUFBSSxjQUFjO0FBRWxCLGVBQWEsTUFBTSxRQUFRLFFBQVE7QUFDbkMsZUFBYSxNQUFNLFFBQVEsUUFBUTtBQUVuQyxRQUFNLEtBQUssUUFBUSxDQUFDLE1BQXFCLFdBQWtDO0FBQ3pFLGVBQVcsRUFBRSxNQUFNLE9BQU87QUFBQSxFQUM1QixDQUFDO0FBUUQsUUFBTSxLQUFLLFNBQVMsQ0FBQyxVQUFpQjtBQUNwQyxlQUFXLEVBQUUsTUFBTSxNQUFNLFFBQVEsTUFBTSxZQUFZLE1BQU0sUUFBUTtBQUFBLEVBQ25FLENBQUM7QUFFRCxTQUFPO0FBQUEsSUFDTCxjQUFjLE1BQU07QUFBQSxJQUNwQixZQUFZLE1BQU07QUFBQSxJQUNsQixhQUFhLE1BQVk7QUFDdkIsb0JBQWM7QUFBQSxJQUNoQjtBQUFBLEVBQ0Y7QUFFQSxXQUFTLGFBQWEsUUFBeUIsTUFBMEM7QUFDdkYsUUFBSSxDQUFDLFFBQVE7QUFDWDtBQUFBLElBQ0Y7QUFFQSxXQUFPLEdBQUcsUUFBUSxDQUFDLFVBQWtCO0FBQ25DLFlBQU0sT0FBTyxNQUFNLFNBQVM7QUFDNUIsZ0JBQVUsRUFBRSxRQUFRLE1BQU0sS0FBSyxDQUFDO0FBQ2hDLFVBQUksYUFBYTtBQUNmLDBCQUFrQixpQkFBaUIsTUFBTSxNQUFNLENBQUMsMkJBQTJCO0FBQUEsTUFDN0U7QUFBQSxJQUNGLENBQUM7QUFXRCxJQUFDLE9BQW9DLFFBQVE7QUFBQSxFQUMvQztBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @file
3
+ *
4
+ * Attaches output capture and exit observation to a spawned child process.
5
+ *
6
+ * A long-running child spawned with piped stdio needs three things done to it,
7
+ * and getting any of them wrong is its own bug: its pipes must be **drained**
8
+ * (a full OS pipe buffer blocks the writer — a chatty renderer would hang the
9
+ * app it belongs to), its output must be kept **bounded** (an hour of logs is
10
+ * not a diagnostic), and its `exit` / `error` must be **recorded** so a caller
11
+ * that later finds the process unreachable can say why instead of guessing.
12
+ *
13
+ * Extracted so the state machine is unit-testable: the launchers that use it
14
+ * (`obsidian-instance.ts`, and the emulator/Appium spawns in
15
+ * `transport-factory.ts`) are integration-time glue excluded from unit tests,
16
+ * which is how the owned Obsidian instance came to be spawned `stdio: 'ignore'`
17
+ * with no `exit` listener at all — its death was unobservable by construction.
18
+ */
19
+ import type { ChildProcess } from 'node:child_process';
20
+ import type { ProcessExitInfo } from './process-exit-message.cjs';
21
+ /**
22
+ * Parameters for {@link attachProcessCapture}.
23
+ */
24
+ export interface AttachProcessCaptureParams {
25
+ /**
26
+ * How many characters of the most recent output to keep. Older output is
27
+ * dropped from the front as new output arrives.
28
+ */
29
+ readonly maxOutputLengthInCharacters: number;
30
+ /**
31
+ * Called for every chunk as it arrives, for callers that want the output
32
+ * **live** (logged as the process runs) rather than only as a post-mortem
33
+ * tail. Fires regardless of {@link ProcessCapture.stopCapture}, which freezes
34
+ * the retained tail and nothing else.
35
+ */
36
+ readonly onChunk?: ((chunk: ProcessOutputChunk) => void) | undefined;
37
+ }
38
+ /**
39
+ * A child process's captured output and exit status.
40
+ */
41
+ export interface ProcessCapture {
42
+ /**
43
+ Returns the exit / spawn-failure details once the process is no longer running, otherwise `undefined`.
44
+ */
45
+ readExitInfo: () => ProcessExitInfo | undefined;
46
+ /**
47
+ Returns the captured stdout+stderr, bounded to the most recent output.
48
+ */
49
+ readOutput: () => string;
50
+ /**
51
+ * Stops accumulating output, freezing the tail at what has arrived so far.
52
+ * Call once startup has succeeded and the tail has served its purpose.
53
+ *
54
+ * The `data` listeners stay attached deliberately, so the pipes keep draining
55
+ * for the rest of the process's life.
56
+ */
57
+ stopCapture: () => void;
58
+ }
59
+ /**
60
+ * One chunk of a child process's output, and which stream it came from.
61
+ */
62
+ export interface ProcessOutputChunk {
63
+ /**
64
+ The stream the chunk was written to.
65
+ */
66
+ readonly stream: 'stderr' | 'stdout';
67
+ /**
68
+ The chunk's text.
69
+ */
70
+ readonly text: string;
71
+ }
72
+ /**
73
+ * Attaches output capture and exit observation to an already-spawned process.
74
+ *
75
+ * Tolerates a process spawned without pipes (`stdio: 'ignore'` leaves
76
+ * `stdout` / `stderr` `null`): the exit half still works, and the captured
77
+ * output stays empty.
78
+ *
79
+ * @param child - The spawned process.
80
+ * @param params - The tail budget, and an optional live-output callback.
81
+ * @returns Readers for the captured output and the exit status.
82
+ */
83
+ export declare function attachProcessCapture(child: ChildProcess, params: AttachProcessCaptureParams): ProcessCapture;
@@ -18,18 +18,23 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var process_exit_message_exports = {};
20
20
  __export(process_exit_message_exports, {
21
+ appendProcessOutputTail: () => appendProcessOutputTail,
21
22
  buildProcessExitMessage: () => buildProcessExitMessage
22
23
  });
23
24
  module.exports = __toCommonJS(process_exit_message_exports);
25
+ function appendProcessOutputTail(message, params) {
26
+ const trimmedOutput = params.output.trim();
27
+ if (trimmedOutput.length === 0) {
28
+ return message;
29
+ }
30
+ return `${message}
31
+
32
+ ${params.outputLabel} (tail):
33
+ ${trimmedOutput}`;
34
+ }
24
35
  function buildProcessExitMessage(params) {
25
36
  const { exitInfo, output, outputLabel, subject } = params;
26
- const reason = resolveReason(exitInfo);
27
- const trimmedOutput = output.trim();
28
- const details = trimmedOutput.length > 0 ? `
29
-
30
- ${outputLabel} (tail):
31
- ${trimmedOutput}` : "";
32
- return `${subject} ${reason} during startup.${details}`;
37
+ return appendProcessOutputTail(`${subject} ${resolveReason(exitInfo)} during startup.`, { output, outputLabel });
33
38
  }
34
39
  function resolveReason(exitInfo) {
35
40
  if (exitInfo.spawnError !== void 0) {
@@ -42,6 +47,7 @@ function resolveReason(exitInfo) {
42
47
  }
43
48
  // Annotate the CommonJS export names for ESM import in node:
44
49
  0 && (module.exports = {
50
+ appendProcessOutputTail,
45
51
  buildProcessExitMessage
46
52
  });
47
- //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtZXhpdC1tZXNzYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBidWlsZGVyIGZvciB0aGUgZGlhZ25vc3RpYyBtZXNzYWdlIGRlc2NyaWJpbmcgYW4gYXV0by1zdGFydGVkIGNoaWxkXG4gKiBwcm9jZXNzICh0aGUgQW5kcm9pZCBlbXVsYXRvciBvciB0aGUgQXBwaXVtIHNlcnZlcikgdGhhdCBkaWVkIGR1cmluZyBzdGFydHVwLFxuICogYXBwZW5kaW5nIHRoZSBjYXB0dXJlZCBvdXRwdXQgdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCAoZXhjbHVkZWQgZnJvbVxuICogdW5pdCB0ZXN0cykgc28gdGhlIG1lc3NhZ2UgZm9ybWF0dGluZyBzdGF5cyB1bml0LXRlc3RhYmxlIFx1MjAxNCB0aGUgbGF1bmNoZXJzXG4gKiB0aGVtc2VsdmVzIHNwYXduIHJlYWwgcHJvY2Vzc2VzLlxuICovXG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZFByb2Nlc3NFeGl0TWVzc2FnZVBhcmFtcyB7XG4gIC8qKlxuICBUaGUgcHJvY2VzcydzIGV4aXQgLyBzcGF3bi1mYWlsdXJlIGRldGFpbHMuXG4gICAqL1xuICByZWFkb25seSBleGl0SW5mbzogUHJvY2Vzc0V4aXRJbmZvO1xuXG4gIC8qKlxuICBUaGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciB0YWlsIChlbXB0eSB3aGVuIG5vbmUgd2FzIGNhcHR1cmVkKS5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dDogc3RyaW5nO1xuXG4gIC8qKlxuICBMYWJlbCBmb3IgdGhlIGNhcHR1cmVkIG91dHB1dCBzZWN0aW9uIChlLmcuIGBcIkVtdWxhdG9yIG91dHB1dFwiYCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRMYWJlbDogc3RyaW5nO1xuXG4gIC8qKlxuICBIdW1hbi1yZWFkYWJsZSBzdWJqZWN0IG9mIHRoZSBwcm9jZXNzIChlLmcuIGBcIkFuZHJvaWQgZW11bGF0b3JcImApLlxuICAgKi9cbiAgcmVhZG9ubHkgc3ViamVjdDogc3RyaW5nO1xufVxuXG4vKipcbiAqIERldGFpbHMgb2YgYSBzcGF3bmVkIGNoaWxkIHByb2Nlc3MgdGhhdCBoYXMgZXhpdGVkIG9yIGZhaWxlZCB0byBzcGF3bi5cbiAqXG4gKiBBIG5vcm1hbCBleGl0IHNldHMgYGNvZGVgL2BzaWduYWxgIChleGFjdGx5IG9uZSBpcyBub24tYG51bGxgKTsgYSBzcGF3blxuICogZmFpbHVyZSAoZS5nLiBgRU5PRU5UYCBmb3IgYSBtaXNzaW5nIGJpbmFyeSkgbGVhdmVzIGJvdGggYG51bGxgIGFuZCBzZXRzXG4gKiBgc3Bhd25FcnJvcmAgdG8gdGhlIGZhaWx1cmUgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzRXhpdEluZm8ge1xuICAvKipcbiAgRXhpdCBjb2RlLCBvciBgbnVsbGAgd2hlbiB0ZXJtaW5hdGVkIGJ5IGEgc2lnbmFsIG9yIHdoZW4gaXQgZmFpbGVkIHRvIHNwYXduLlxuICAgKi9cbiAgcmVhZG9ubHkgY29kZTogbnVsbCB8IG51bWJlcjtcblxuICAvKipcbiAgVGVybWluYXRpbmcgc2lnbmFsLCBvciBgbnVsbGAgd2hlbiBpdCBleGl0ZWQgbm9ybWFsbHkgb3IgZmFpbGVkIHRvIHNwYXduLlxuICAgKi9cbiAgcmVhZG9ubHkgc2lnbmFsOiBOb2RlSlMuU2lnbmFscyB8IG51bGw7XG5cbiAgLyoqXG4gIFRoZSBzcGF3bi1mYWlsdXJlIG1lc3NhZ2Ugd2hlbiB0aGUgcHJvY2VzcyBuZXZlciBzdGFydGVkIChlLmcuIGBFTk9FTlRgKSwgb3RoZXJ3aXNlIGFic2VudC5cbiAgICovXG4gIHJlYWRvbmx5IHNwYXduRXJyb3I/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgZGVzY3JpcHRpdmUgZXJyb3IgbWVzc2FnZSBmb3IgYW4gYXV0by1zdGFydGVkIGNoaWxkIHByb2Nlc3MgdGhhdFxuICogZXhpdGVkIChvciBmYWlsZWQgdG8gc3Bhd24pIGR1cmluZyBzdGFydHVwLCBhcHBlbmRpbmcgdGhlIGNhcHR1cmVkIG91dHB1dFxuICogdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHN1YmplY3QsIGV4aXQgZGV0YWlscywgYW5kIGNhcHR1cmVkIG91dHB1dC5cbiAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlKHBhcmFtczogQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBjb25zdCB7IGV4aXRJbmZvLCBvdXRwdXQsIG91dHB1dExhYmVsLCBzdWJqZWN0IH0gPSBwYXJhbXM7XG5cbiAgY29uc3QgcmVhc29uID0gcmVzb2x2ZVJlYXNvbihleGl0SW5mbyk7XG4gIGNvbnN0IHRyaW1tZWRPdXRwdXQgPSBvdXRwdXQudHJpbSgpO1xuICBjb25zdCBkZXRhaWxzID0gdHJpbW1lZE91dHB1dC5sZW5ndGggPiAwXG4gICAgPyBgXFxuXFxuJHtvdXRwdXRMYWJlbH0gKHRhaWwpOlxcbiR7dHJpbW1lZE91dHB1dH1gXG4gICAgOiAnJztcbiAgcmV0dXJuIGAke3N1YmplY3R9ICR7cmVhc29ufSBkdXJpbmcgc3RhcnR1cC4ke2RldGFpbHN9YDtcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgd2h5IHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLlxuICpcbiAqIEBwYXJhbSBleGl0SW5mbyAtIFRoZSBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICogQHJldHVybnMgVGhlIHJlYXNvbiBjbGF1c2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZWFzb24oZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyk6IHN0cmluZyB7XG4gIGlmIChleGl0SW5mby5zcGF3bkVycm9yICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYGZhaWxlZCB0byBzdGFydCAoJHtleGl0SW5mby5zcGF3bkVycm9yfSlgO1xuICB9XG4gIGlmIChleGl0SW5mby5zaWduYWwgIT09IG51bGwpIHtcbiAgICByZXR1cm4gYHdhcyB0ZXJtaW5hdGVkIGJ5IHNpZ25hbCAke2V4aXRJbmZvLnNpZ25hbH1gO1xuICB9XG4gIHJldHVybiBgZXhpdGVkIHByZW1hdHVyZWx5IHdpdGggY29kZSAke2V4aXRJbmZvLmNvZGUgPT09IG51bGwgPyAnKG51bGwpJyA6IFN0cmluZyhleGl0SW5mby5jb2RlKX1gO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQXFFTyxTQUFTLHdCQUF3QixRQUErQztBQUNyRixRQUFNLEVBQUUsVUFBVSxRQUFRLGFBQWEsUUFBUSxJQUFJO0FBRW5ELFFBQU0sU0FBUyxjQUFjLFFBQVE7QUFDckMsUUFBTSxnQkFBZ0IsT0FBTyxLQUFLO0FBQ2xDLFFBQU0sVUFBVSxjQUFjLFNBQVMsSUFDbkM7QUFBQTtBQUFBLEVBQU8sV0FBVztBQUFBLEVBQWEsYUFBYSxLQUM1QztBQUNKLFNBQU8sR0FBRyxPQUFPLElBQUksTUFBTSxtQkFBbUIsT0FBTztBQUN2RDtBQVFBLFNBQVMsY0FBYyxVQUFtQztBQUN4RCxNQUFJLFNBQVMsZUFBZSxRQUFXO0FBQ3JDLFdBQU8sb0JBQW9CLFNBQVMsVUFBVTtBQUFBLEVBQ2hEO0FBQ0EsTUFBSSxTQUFTLFdBQVcsTUFBTTtBQUM1QixXQUFPLDRCQUE0QixTQUFTLE1BQU07QUFBQSxFQUNwRDtBQUNBLFNBQU8sZ0NBQWdDLFNBQVMsU0FBUyxPQUFPLFdBQVcsT0FBTyxTQUFTLElBQUksQ0FBQztBQUNsRzsiLAogICJuYW1lcyI6IFtdCn0K
53
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtZXhpdC1tZXNzYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKipcbiAqIEBmaWxlXG4gKlxuICogUHVyZSBidWlsZGVycyBmb3IgdGhlIGRpYWdub3N0aWMgbWVzc2FnZSBkZXNjcmliaW5nIGFuIGF1dG8tc3RhcnRlZCBjaGlsZFxuICogcHJvY2VzcyAodGhlIEFuZHJvaWQgZW11bGF0b3Igb3IgdGhlIEFwcGl1bSBzZXJ2ZXIpIHRoYXQgZmFpbGVkIGR1cmluZ1xuICogc3RhcnR1cCwgYXBwZW5kaW5nIHRoZSBjYXB0dXJlZCBvdXRwdXQgdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBBIHN0YXJ0dXAgZmFpbHMgdHdvIHdheXMgXHUyMDE0IHRoZSBwcm9jZXNzICoqZGllcyoqLCBvciBpdCAqKmhhbmdzKiogcGFzdCBhXG4gKiBidWRnZXQgXHUyMDE0IGFuZCB0aGUgY2FwdHVyZWQgdGFpbCBpcyBlcXVhbGx5IHRoZSBleHBsYW5hdGlvbiBpbiBib3RoLiBTbyB0aGVcbiAqIHRhaWwtYXBwZW5kaW5nIGhhbGYgaXMgaXRzIG93biBleHBvcnQsIHVzZWQgYnkgdGhlIHRpbWVvdXQgdGhyb3dzIHRoYXQgb25jZVxuICogcmVwb3J0ZWQgb25seSB0aGUgYnVkZ2V0IHRoZXkgYmxldy5cbiAqXG4gKiBLZXB0IHNlcGFyYXRlIGZyb20gdGhlIGludGVncmF0aW9uLW9ubHkgYHRyYW5zcG9ydC1mYWN0b3J5YCAoZXhjbHVkZWQgZnJvbVxuICogdW5pdCB0ZXN0cykgc28gdGhlIG1lc3NhZ2UgZm9ybWF0dGluZyBzdGF5cyB1bml0LXRlc3RhYmxlIFx1MjAxNCB0aGUgbGF1bmNoZXJzXG4gKiB0aGVtc2VsdmVzIHNwYXduIHJlYWwgcHJvY2Vzc2VzLlxuICovXG5cbi8qKlxuICogUGFyYW1ldGVycyBmb3Ige0BsaW5rIGFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBcHBlbmRQcm9jZXNzT3V0cHV0VGFpbFBhcmFtcyB7XG4gIC8qKlxuICBUaGUgY2FwdHVyZWQgc3Rkb3V0K3N0ZGVyciB0YWlsIChlbXB0eSB3aGVuIG5vbmUgd2FzIGNhcHR1cmVkKS5cbiAgICovXG4gIHJlYWRvbmx5IG91dHB1dDogc3RyaW5nO1xuXG4gIC8qKlxuICBMYWJlbCBmb3IgdGhlIGNhcHR1cmVkIG91dHB1dCBzZWN0aW9uIChlLmcuIGBcIkVtdWxhdG9yIG91dHB1dFwiYCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRMYWJlbDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgZm9yIHtAbGluayBidWlsZFByb2Nlc3NFeGl0TWVzc2FnZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMge1xuICAvKipcbiAgVGhlIHByb2Nlc3MncyBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbztcblxuICAvKipcbiAgVGhlIGNhcHR1cmVkIHN0ZG91dCtzdGRlcnIgdGFpbCAoZW1wdHkgd2hlbiBub25lIHdhcyBjYXB0dXJlZCkuXG4gICAqL1xuICByZWFkb25seSBvdXRwdXQ6IHN0cmluZztcblxuICAvKipcbiAgTGFiZWwgZm9yIHRoZSBjYXB0dXJlZCBvdXRwdXQgc2VjdGlvbiAoZS5nLiBgXCJFbXVsYXRvciBvdXRwdXRcImApLlxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0TGFiZWw6IHN0cmluZztcblxuICAvKipcbiAgSHVtYW4tcmVhZGFibGUgc3ViamVjdCBvZiB0aGUgcHJvY2VzcyAoZS5nLiBgXCJBbmRyb2lkIGVtdWxhdG9yXCJgKS5cbiAgICovXG4gIHJlYWRvbmx5IHN1YmplY3Q6IHN0cmluZztcbn1cblxuLyoqXG4gKiBEZXRhaWxzIG9mIGEgc3Bhd25lZCBjaGlsZCBwcm9jZXNzIHRoYXQgaGFzIGV4aXRlZCBvciBmYWlsZWQgdG8gc3Bhd24uXG4gKlxuICogQSBub3JtYWwgZXhpdCBzZXRzIGBjb2RlYC9gc2lnbmFsYCAoZXhhY3RseSBvbmUgaXMgbm9uLWBudWxsYCk7IGEgc3Bhd25cbiAqIGZhaWx1cmUgKGUuZy4gYEVOT0VOVGAgZm9yIGEgbWlzc2luZyBiaW5hcnkpIGxlYXZlcyBib3RoIGBudWxsYCBhbmQgc2V0c1xuICogYHNwYXduRXJyb3JgIHRvIHRoZSBmYWlsdXJlIG1lc3NhZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc0V4aXRJbmZvIHtcbiAgLyoqXG4gIEV4aXQgY29kZSwgb3IgYG51bGxgIHdoZW4gdGVybWluYXRlZCBieSBhIHNpZ25hbCBvciB3aGVuIGl0IGZhaWxlZCB0byBzcGF3bi5cbiAgICovXG4gIHJlYWRvbmx5IGNvZGU6IG51bGwgfCBudW1iZXI7XG5cbiAgLyoqXG4gIFRlcm1pbmF0aW5nIHNpZ25hbCwgb3IgYG51bGxgIHdoZW4gaXQgZXhpdGVkIG5vcm1hbGx5IG9yIGZhaWxlZCB0byBzcGF3bi5cbiAgICovXG4gIHJlYWRvbmx5IHNpZ25hbDogTm9kZUpTLlNpZ25hbHMgfCBudWxsO1xuXG4gIC8qKlxuICBUaGUgc3Bhd24tZmFpbHVyZSBtZXNzYWdlIHdoZW4gdGhlIHByb2Nlc3MgbmV2ZXIgc3RhcnRlZCAoZS5nLiBgRU5PRU5UYCksIG90aGVyd2lzZSBhYnNlbnQuXG4gICAqL1xuICByZWFkb25seSBzcGF3bkVycm9yPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEFwcGVuZHMgYSBwcm9jZXNzJ3MgY2FwdHVyZWQgb3V0cHV0IHRhaWwgdG8gYSBtZXNzYWdlLCB3aGVuIHRoZXJlIGlzIG9uZS5cbiAqXG4gKiBTcGxpdCBvdXQgb2Yge0BsaW5rIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlfSBzbyB0aGUgKip0aW1lb3V0KiogZmFpbHVyZXMgY2FuXG4gKiBjYXJyeSB0aGUgdGFpbCB0b28uIEEgcHJvY2VzcyB0aGF0IGRpZXMgZ2V0cyBpdHMgb3V0cHV0IGF0dGFjaGVkOyBvbmUgdGhhdFxuICogaGFuZ3MgdXNlZCB0byBnZXQgYE5vIG5ldyBlbXVsYXRvciBkZXZpY2UgYXBwZWFyZWQgd2l0aGluIDMwMDAwMG1zLmAgYW5kXG4gKiBub3RoaW5nIGVsc2UgXHUyMDE0IGV2ZW4gdGhvdWdoIHRoZSBsaW5lIHRoYXQgZXhwbGFpbnMgaXQgKGBGQVRBTCB8IFJ1bm5pbmdcbiAqIG11bHRpcGxlIGVtdWxhdG9ycyB3aXRoIHRoZSBzYW1lIEFWRCBpcyBhbiBleHBlcmltZW50YWwgZmVhdHVyZWApIGhhZCBhbHJlYWR5XG4gKiBiZWVuIGNhcHR1cmVkLiBUaGUgZW11bGF0b3Igd3JpdGluZyBpdHMgb3duIGRpYWdub3NpcyBpcyB3b3J0aCBub3RoaW5nIGlmIHRoZVxuICogaGFybmVzcyByZWFkcyBpdCBvbiBvbmx5IG9uZSBvZiB0aGUgdHdvIHdheXMgYSBzdGFydHVwIGNhbiBmYWlsLlxuICpcbiAqIEBwYXJhbSBtZXNzYWdlIC0gVGhlIGZhaWx1cmUgbWVzc2FnZSB0byBleHRlbmQuXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIGNhcHR1cmVkIHRhaWwgYW5kIGl0cyBsYWJlbC5cbiAqIEByZXR1cm5zIFRoZSBtZXNzYWdlLCB3aXRoIHRoZSB0YWlsIGFwcGVuZGVkIHdoZW4gbm9uLWVtcHR5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwZW5kUHJvY2Vzc091dHB1dFRhaWwobWVzc2FnZTogc3RyaW5nLCBwYXJhbXM6IEFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsUGFyYW1zKTogc3RyaW5nIHtcbiAgY29uc3QgdHJpbW1lZE91dHB1dCA9IHBhcmFtcy5vdXRwdXQudHJpbSgpO1xuICBpZiAodHJpbW1lZE91dHB1dC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIHJldHVybiBgJHttZXNzYWdlfVxcblxcbiR7cGFyYW1zLm91dHB1dExhYmVsfSAodGFpbCk6XFxuJHt0cmltbWVkT3V0cHV0fWA7XG59XG5cbi8qKlxuICogQnVpbGRzIGEgZGVzY3JpcHRpdmUgZXJyb3IgbWVzc2FnZSBmb3IgYW4gYXV0by1zdGFydGVkIGNoaWxkIHByb2Nlc3MgdGhhdFxuICogZXhpdGVkIChvciBmYWlsZWQgdG8gc3Bhd24pIGR1cmluZyBzdGFydHVwLCBhcHBlbmRpbmcgdGhlIGNhcHR1cmVkIG91dHB1dFxuICogdGFpbCB3aGVuIGF2YWlsYWJsZS5cbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHN1YmplY3QsIGV4aXQgZGV0YWlscywgYW5kIGNhcHR1cmVkIG91dHB1dC5cbiAqIEByZXR1cm5zIEEgaHVtYW4tcmVhZGFibGUgZXJyb3IgbWVzc2FnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkUHJvY2Vzc0V4aXRNZXNzYWdlKHBhcmFtczogQnVpbGRQcm9jZXNzRXhpdE1lc3NhZ2VQYXJhbXMpOiBzdHJpbmcge1xuICBjb25zdCB7IGV4aXRJbmZvLCBvdXRwdXQsIG91dHB1dExhYmVsLCBzdWJqZWN0IH0gPSBwYXJhbXM7XG5cbiAgcmV0dXJuIGFwcGVuZFByb2Nlc3NPdXRwdXRUYWlsKGAke3N1YmplY3R9ICR7cmVzb2x2ZVJlYXNvbihleGl0SW5mbyl9IGR1cmluZyBzdGFydHVwLmAsIHsgb3V0cHV0LCBvdXRwdXRMYWJlbCB9KTtcbn1cblxuLyoqXG4gKiBEZXNjcmliZXMgd2h5IHRoZSBwcm9jZXNzIGlzIG5vIGxvbmdlciBydW5uaW5nLlxuICpcbiAqIEBwYXJhbSBleGl0SW5mbyAtIFRoZSBleGl0IC8gc3Bhd24tZmFpbHVyZSBkZXRhaWxzLlxuICogQHJldHVybnMgVGhlIHJlYXNvbiBjbGF1c2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVSZWFzb24oZXhpdEluZm86IFByb2Nlc3NFeGl0SW5mbyk6IHN0cmluZyB7XG4gIGlmIChleGl0SW5mby5zcGF3bkVycm9yICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gYGZhaWxlZCB0byBzdGFydCAoJHtleGl0SW5mby5zcGF3bkVycm9yfSlgO1xuICB9XG4gIGlmIChleGl0SW5mby5zaWduYWwgIT09IG51bGwpIHtcbiAgICByZXR1cm4gYHdhcyB0ZXJtaW5hdGVkIGJ5IHNpZ25hbCAke2V4aXRJbmZvLnNpZ25hbH1gO1xuICB9XG4gIHJldHVybiBgZXhpdGVkIHByZW1hdHVyZWx5IHdpdGggY29kZSAke2V4aXRJbmZvLmNvZGUgPT09IG51bGwgPyAnKG51bGwpJyA6IFN0cmluZyhleGl0SW5mby5jb2RlKX1gO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZ0dPLFNBQVMsd0JBQXdCLFNBQWlCLFFBQStDO0FBQ3RHLFFBQU0sZ0JBQWdCLE9BQU8sT0FBTyxLQUFLO0FBQ3pDLE1BQUksY0FBYyxXQUFXLEdBQUc7QUFDOUIsV0FBTztBQUFBLEVBQ1Q7QUFFQSxTQUFPLEdBQUcsT0FBTztBQUFBO0FBQUEsRUFBTyxPQUFPLFdBQVc7QUFBQSxFQUFhLGFBQWE7QUFDdEU7QUFVTyxTQUFTLHdCQUF3QixRQUErQztBQUNyRixRQUFNLEVBQUUsVUFBVSxRQUFRLGFBQWEsUUFBUSxJQUFJO0FBRW5ELFNBQU8sd0JBQXdCLEdBQUcsT0FBTyxJQUFJLGNBQWMsUUFBUSxDQUFDLG9CQUFvQixFQUFFLFFBQVEsWUFBWSxDQUFDO0FBQ2pIO0FBUUEsU0FBUyxjQUFjLFVBQW1DO0FBQ3hELE1BQUksU0FBUyxlQUFlLFFBQVc7QUFDckMsV0FBTyxvQkFBb0IsU0FBUyxVQUFVO0FBQUEsRUFDaEQ7QUFDQSxNQUFJLFNBQVMsV0FBVyxNQUFNO0FBQzVCLFdBQU8sNEJBQTRCLFNBQVMsTUFBTTtBQUFBLEVBQ3BEO0FBQ0EsU0FBTyxnQ0FBZ0MsU0FBUyxTQUFTLE9BQU8sV0FBVyxPQUFPLFNBQVMsSUFBSSxDQUFDO0FBQ2xHOyIsCiAgIm5hbWVzIjogW10KfQo=
@@ -1,14 +1,32 @@
1
1
  /**
2
2
  * @file
3
3
  *
4
- * Pure builder for the diagnostic message describing an auto-started child
5
- * process (the Android emulator or the Appium server) that died during startup,
6
- * appending the captured output tail when available.
4
+ * Pure builders for the diagnostic message describing an auto-started child
5
+ * process (the Android emulator or the Appium server) that failed during
6
+ * startup, appending the captured output tail when available.
7
+ *
8
+ * A startup fails two ways — the process **dies**, or it **hangs** past a
9
+ * budget — and the captured tail is equally the explanation in both. So the
10
+ * tail-appending half is its own export, used by the timeout throws that once
11
+ * reported only the budget they blew.
7
12
  *
8
13
  * Kept separate from the integration-only `transport-factory` (excluded from
9
14
  * unit tests) so the message formatting stays unit-testable — the launchers
10
15
  * themselves spawn real processes.
11
16
  */
17
+ /**
18
+ * Parameters for {@link appendProcessOutputTail}.
19
+ */
20
+ export interface AppendProcessOutputTailParams {
21
+ /**
22
+ The captured stdout+stderr tail (empty when none was captured).
23
+ */
24
+ readonly output: string;
25
+ /**
26
+ Label for the captured output section (e.g. `"Emulator output"`).
27
+ */
28
+ readonly outputLabel: string;
29
+ }
12
30
  /**
13
31
  * Parameters for {@link buildProcessExitMessage}.
14
32
  */
@@ -51,6 +69,22 @@ export interface ProcessExitInfo {
51
69
  */
52
70
  readonly spawnError?: string;
53
71
  }
72
+ /**
73
+ * Appends a process's captured output tail to a message, when there is one.
74
+ *
75
+ * Split out of {@link buildProcessExitMessage} so the **timeout** failures can
76
+ * carry the tail too. A process that dies gets its output attached; one that
77
+ * hangs used to get `No new emulator device appeared within 300000ms.` and
78
+ * nothing else — even though the line that explains it (`FATAL | Running
79
+ * multiple emulators with the same AVD is an experimental feature`) had already
80
+ * been captured. The emulator writing its own diagnosis is worth nothing if the
81
+ * harness reads it on only one of the two ways a startup can fail.
82
+ *
83
+ * @param message - The failure message to extend.
84
+ * @param params - The captured tail and its label.
85
+ * @returns The message, with the tail appended when non-empty.
86
+ */
87
+ export declare function appendProcessOutputTail(message: string, params: AppendProcessOutputTailParams): string;
54
88
  /**
55
89
  * Builds a descriptive error message for an auto-started child process that
56
90
  * exited (or failed to spawn) during startup, appending the captured output
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var process_liveness_exports = {};
30
+ __export(process_liveness_exports, {
31
+ checkIsProcessAlive: () => checkIsProcessAlive
32
+ });
33
+ module.exports = __toCommonJS(process_liveness_exports);
34
+ var import_node_process = __toESM(require("node:process"), 1);
35
+ const PROCESS_EXISTENCE_PROBE_SIGNAL = 0;
36
+ function checkIsProcessAlive(pid) {
37
+ try {
38
+ import_node_process.default.kill(pid, PROCESS_EXISTENCE_PROBE_SIGNAL);
39
+ return true;
40
+ } catch (error) {
41
+ return getErrorCode(error) === "EPERM";
42
+ }
43
+ }
44
+ function getErrorCode(error) {
45
+ return typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0;
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ checkIsProcessAlive
50
+ });
51
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vLi4vc3JjL3Byb2Nlc3MtbGl2ZW5lc3MudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbIi8qKlxuICogQGZpbGVcbiAqXG4gKiBDaGVhcCwgc3luY2hyb25vdXMgXCJpcyB0aGlzIFBJRCBzdGlsbCBydW5uaW5nP1wiIHByb2JlLlxuICpcbiAqIFNpZ25hbCBgMGAgcGVyZm9ybXMgdGhlIHBlcm1pc3Npb24gYW5kIGV4aXN0ZW5jZSBjaGVja3Mgd2l0aG91dCBkZWxpdmVyaW5nIGFcbiAqIHNpZ25hbCwgb24gV2luZG93cyBhcyB3ZWxsIGFzIFBPU0lYLCBzbyBpdCBjb3N0cyBub3RoaW5nIGF0IHRlYXJkb3duLXBvbGxcbiAqIGZyZXF1ZW5jeS4gYEVQRVJNYCBtZWFucyB0aGUgcHJvY2VzcyBleGlzdHMgYnV0IGlzIG93bmVkIGJ5IGFub3RoZXIgdXNlciBcdTIwMTRcbiAqIHN0aWxsIGFsaXZlLCBhbmQgdGhlIGRpc3RpbmN0aW9uIG1hdHRlcnM6IHJlYWRpbmcgaXQgYXMgZGVhZCBpcyBob3cgYVxuICogdGVhcmRvd24gY29udmluY2VzIGl0c2VsZiBhIHByb2Nlc3MgaXQgY291bGQgbm90IHRvdWNoIGlzIGdvbmUuXG4gKi9cblxuaW1wb3J0IHByb2Nlc3MgZnJvbSAnbm9kZTpwcm9jZXNzJztcblxuY29uc3QgUFJPQ0VTU19FWElTVEVOQ0VfUFJPQkVfU0lHTkFMID0gMDtcblxuLyoqXG4gKiBDaGVja3Mgd2hldGhlciBhIHByb2Nlc3MgaXMgc3RpbGwgcnVubmluZy5cbiAqXG4gKiBAcGFyYW0gcGlkIC0gVGhlIFBJRCB0byBwcm9iZS5cbiAqIEByZXR1cm5zIGB0cnVlYCB3aGVuIHRoZSBwcm9jZXNzIGV4aXN0cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrSXNQcm9jZXNzQWxpdmUocGlkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgdHJ5IHtcbiAgICBwcm9jZXNzLmtpbGwocGlkLCBQUk9DRVNTX0VYSVNURU5DRV9QUk9CRV9TSUdOQUwpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnJvcjogdW5rbm93bikge1xuICAgIHJldHVybiBnZXRFcnJvckNvZGUoZXJyb3IpID09PSAnRVBFUk0nO1xuICB9XG59XG5cbmZ1bmN0aW9uIGdldEVycm9yQ29kZShlcnJvcjogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiB0eXBlb2YgZXJyb3IgPT09ICdvYmplY3QnICYmIGVycm9yICE9PSBudWxsICYmICdjb2RlJyBpbiBlcnJvciA/IFN0cmluZyhlcnJvci5jb2RlKSA6IHVuZGVmaW5lZDtcbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBWUEsMEJBQW9CO0FBRXBCLE1BQU0saUNBQWlDO0FBUWhDLFNBQVMsb0JBQW9CLEtBQXNCO0FBQ3hELE1BQUk7QUFDRix3QkFBQUEsUUFBUSxLQUFLLEtBQUssOEJBQThCO0FBQ2hELFdBQU87QUFBQSxFQUNULFNBQVMsT0FBZ0I7QUFDdkIsV0FBTyxhQUFhLEtBQUssTUFBTTtBQUFBLEVBQ2pDO0FBQ0Y7QUFFQSxTQUFTLGFBQWEsT0FBb0M7QUFDeEQsU0FBTyxPQUFPLFVBQVUsWUFBWSxVQUFVLFFBQVEsVUFBVSxRQUFRLE9BQU8sTUFBTSxJQUFJLElBQUk7QUFDL0Y7IiwKICAibmFtZXMiOiBbInByb2Nlc3MiXQp9Cg==