quickwin 2.2.0 → 2.3.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 (111) hide show
  1. package/README.en.md +7 -7
  2. package/README.md +7 -7
  3. package/constants.ts +1063 -0
  4. package/enum_map.d.ts +129 -0
  5. package/examples/PdfCanvas.js +2 -2
  6. package/examples/PdfCanvas.tsx +3 -2
  7. package/examples/{execd.js → execd/main.js} +563 -122
  8. package/examples/execd/tray.js +192 -0
  9. package/examples/{execd_worker.js → execd/worker.js} +7 -7
  10. package/examples/pdf_preview2.js +46 -46
  11. package/examples/pdf_preview2.ts +55 -54
  12. package/examples/pdf_viewer.js +34 -19
  13. package/examples/pdf_viewer.tsx +6 -5
  14. package/examples/test_gallery.js +35 -20
  15. package/examples/test_gallery.tsx +9 -8
  16. package/examples/test_react_lazy.js +34 -19
  17. package/examples/test_react_lazy.tsx +7 -6
  18. package/examples/test_react_listbox.js +34 -19
  19. package/examples/test_react_listbox.tsx +8 -7
  20. package/examples/test_root_window.js +34 -19
  21. package/examples/test_root_window.tsx +5 -5
  22. package/examples/test_tab.js +34 -19
  23. package/examples/test_tab.tsx +7 -6
  24. package/examples/tray_demo.js +8 -8
  25. package/examples/tray_demo.tsx +9 -8
  26. package/lib/dumpRects.js +2 -2
  27. package/lib/dumpRects.ts +3 -2
  28. package/lib/fetch.js +15 -15
  29. package/lib/fetch.ts +16 -15
  30. package/lib/ffi/bind.js +3 -3
  31. package/lib/ffi/bind.ts +3 -3
  32. package/lib/http-server.js +4 -4
  33. package/lib/http-server.ts +5 -4
  34. package/lib/react-qw/components/Button.js +2 -2
  35. package/lib/react-qw/components/CheckBox.js +4 -4
  36. package/lib/react-qw/components/ComboBox.js +10 -10
  37. package/lib/react-qw/components/DateTimePicker.js +12 -12
  38. package/lib/react-qw/components/Input.js +7 -7
  39. package/lib/react-qw/components/Link.js +4 -4
  40. package/lib/react-qw/components/ListBox.js +12 -12
  41. package/lib/react-qw/components/ListView.js +35 -35
  42. package/lib/react-qw/components/PathPicker.js +3 -3
  43. package/lib/react-qw/components/ProgressBar.js +4 -4
  44. package/lib/react-qw/components/RadioButton.js +4 -4
  45. package/lib/react-qw/components/ScrollView.js +28 -28
  46. package/lib/react-qw/components/Slider.js +11 -11
  47. package/lib/react-qw/components/Tab.js +10 -10
  48. package/lib/react-qw/components/Tooltip.js +8 -8
  49. package/lib/react-qw/components/TreeView.js +20 -20
  50. package/lib/react-qw/index.js +5 -5
  51. package/lib/react-qw/index.ts +6 -5
  52. package/lib/react-qw/props.js +4 -4
  53. package/lib/react-qw/props.ts +5 -4
  54. package/lib/react-qw/reconciler.js +10 -10
  55. package/lib/react-qw/reconciler.ts +11 -10
  56. package/lib/text-measure.js +3 -3
  57. package/lib/text-measure.ts +4 -3
  58. package/lib/websocket.js +17 -17
  59. package/lib/websocket.ts +18 -17
  60. package/lib/windows/advapi32.js +7 -7
  61. package/lib/windows/advapi32.ts +7 -7
  62. package/lib/windows/gdi32.js +16 -16
  63. package/lib/windows/gdi32.ts +16 -16
  64. package/lib/windows/kernel32.js +41 -2
  65. package/lib/windows/kernel32.ts +45 -2
  66. package/lib/windows/shell32.js +24 -3
  67. package/lib/windows/shell32.ts +27 -4
  68. package/lib/windows/structs.js +54 -0
  69. package/lib/windows/structs.ts +63 -1
  70. package/lib/windows/user32.js +18 -6
  71. package/lib/windows/user32.ts +18 -6
  72. package/lib/windows/winspool.js +3 -3
  73. package/lib/windows/winspool.ts +3 -3
  74. package/package.json +4 -3
  75. package/quickwin.d.ts +32 -10
  76. package/qwin-nowasm-x86.exe +0 -0
  77. package/qwin-nowasm.exe +0 -0
  78. package/qwin-x86.exe +0 -0
  79. package/qwin.exe +0 -0
  80. package/test/test_ffi_bind.js +7 -7
  81. package/test/test_ffi_bind.ts +8 -8
  82. package/test/test_ffi_struct.js +2 -2
  83. package/test/test_ffi_struct.ts +3 -3
  84. package/test/test_ffi_windows.js +1 -1
  85. package/test/test_ffi_windows.ts +1 -1
  86. package/test/test_files.js +7 -7
  87. package/test/test_files.ts +8 -8
  88. package/test/test_gdi_draw.js +51 -51
  89. package/test/test_gdi_draw.ts +57 -57
  90. package/test/test_http_server.js +3 -3
  91. package/test/test_http_server.ts +4 -3
  92. package/test/test_ipv6.js +3 -3
  93. package/test/test_ipv6.ts +4 -3
  94. package/test/test_net_event.js +3 -3
  95. package/test/test_net_event.ts +4 -3
  96. package/test/test_printer.js +4 -4
  97. package/test/test_printer.ts +5 -5
  98. package/test/test_react_complex.js +36 -21
  99. package/test/test_react_counter.js +34 -19
  100. package/test/test_react_flex.js +36 -21
  101. package/test/test_react_hidden.js +34 -19
  102. package/test/test_react_listview_link.js +35 -20
  103. package/test/test_react_notify.js +52 -37
  104. package/test/test_react_render.js +34 -19
  105. package/test/test_registry.js +6 -6
  106. package/test/test_registry.ts +8 -8
  107. package/test/test_wolfssl_read.js +8 -8
  108. package/test/test_wolfssl_read.ts +9 -8
  109. package/examples/execd.tsx +0 -798
  110. package/examples/execd_worker.ts +0 -127
  111. package/quickwin_const.d.ts +0 -1063
@@ -1367,9 +1367,9 @@ var require_scheduler_development = __commonJS({
1367
1367
  }
1368
1368
  return first;
1369
1369
  }
1370
- function compare(a2, b7) {
1371
- var diff = a2.sortIndex - b7.sortIndex;
1372
- return 0 !== diff ? diff : a2.id - b7.id;
1370
+ function compare(a2, b8) {
1371
+ var diff = a2.sortIndex - b8.sortIndex;
1372
+ return 0 !== diff ? diff : a2.id - b8.id;
1373
1373
  }
1374
1374
  function advanceTimers(currentTime) {
1375
1375
  for (var timer = peek(timerQueue); null !== timer; ) {
@@ -1667,14 +1667,14 @@ var require_react_reconciler_development = __commonJS({
1667
1667
  throw Error("Unable to find node on an unmounted component.");
1668
1668
  return alternate !== fiber ? null : fiber;
1669
1669
  }
1670
- for (var a2 = fiber, b7 = alternate; ; ) {
1670
+ for (var a2 = fiber, b8 = alternate; ; ) {
1671
1671
  var parentA = a2.return;
1672
1672
  if (null === parentA) break;
1673
1673
  var parentB = parentA.alternate;
1674
1674
  if (null === parentB) {
1675
- b7 = parentA.return;
1676
- if (null !== b7) {
1677
- a2 = b7;
1675
+ b8 = parentA.return;
1676
+ if (null !== b8) {
1677
+ a2 = b8;
1678
1678
  continue;
1679
1679
  }
1680
1680
  break;
@@ -1682,23 +1682,23 @@ var require_react_reconciler_development = __commonJS({
1682
1682
  if (parentA.child === parentB.child) {
1683
1683
  for (parentB = parentA.child; parentB; ) {
1684
1684
  if (parentB === a2) return assertIsMounted(parentA), fiber;
1685
- if (parentB === b7) return assertIsMounted(parentA), alternate;
1685
+ if (parentB === b8) return assertIsMounted(parentA), alternate;
1686
1686
  parentB = parentB.sibling;
1687
1687
  }
1688
1688
  throw Error("Unable to find node on an unmounted component.");
1689
1689
  }
1690
- if (a2.return !== b7.return) a2 = parentA, b7 = parentB;
1690
+ if (a2.return !== b8.return) a2 = parentA, b8 = parentB;
1691
1691
  else {
1692
1692
  for (var didFindChild = false, _child = parentA.child; _child; ) {
1693
1693
  if (_child === a2) {
1694
1694
  didFindChild = true;
1695
1695
  a2 = parentA;
1696
- b7 = parentB;
1696
+ b8 = parentB;
1697
1697
  break;
1698
1698
  }
1699
- if (_child === b7) {
1699
+ if (_child === b8) {
1700
1700
  didFindChild = true;
1701
- b7 = parentA;
1701
+ b8 = parentA;
1702
1702
  a2 = parentB;
1703
1703
  break;
1704
1704
  }
@@ -1709,12 +1709,12 @@ var require_react_reconciler_development = __commonJS({
1709
1709
  if (_child === a2) {
1710
1710
  didFindChild = true;
1711
1711
  a2 = parentB;
1712
- b7 = parentA;
1712
+ b8 = parentA;
1713
1713
  break;
1714
1714
  }
1715
- if (_child === b7) {
1715
+ if (_child === b8) {
1716
1716
  didFindChild = true;
1717
- b7 = parentB;
1717
+ b8 = parentB;
1718
1718
  a2 = parentA;
1719
1719
  break;
1720
1720
  }
@@ -1726,7 +1726,7 @@ var require_react_reconciler_development = __commonJS({
1726
1726
  );
1727
1727
  }
1728
1728
  }
1729
- if (a2.alternate !== b7)
1729
+ if (a2.alternate !== b8)
1730
1730
  throw Error(
1731
1731
  "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue."
1732
1732
  );
@@ -15071,10 +15071,10 @@ var require_react_reconciler_development = __commonJS({
15071
15071
  setCurrentUpdatePriority(previousPriority), ReactSharedInternals.T = prevTransition;
15072
15072
  }
15073
15073
  };
15074
- exports2.discreteUpdates = function(fn, a2, b7, c2, d2) {
15074
+ exports2.discreteUpdates = function(fn, a2, b8, c2, d2) {
15075
15075
  var prevTransition = ReactSharedInternals.T, previousPriority = getCurrentUpdatePriority();
15076
15076
  try {
15077
- return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2, b7, c2, d2);
15077
+ return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2, b8, c2, d2);
15078
15078
  } finally {
15079
15079
  setCurrentUpdatePriority(previousPriority), ReactSharedInternals.T = prevTransition, executionContext === NoContext && (workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS);
15080
15080
  }
@@ -15353,7 +15353,7 @@ var require_constants = __commonJS({
15353
15353
  }
15354
15354
  });
15355
15355
 
15356
- // _build/examples/execd.js
15356
+ // _build/examples/execd/main.js
15357
15357
  var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
15358
15358
 
15359
15359
  // _build/lib/polyfill.js
@@ -15514,7 +15514,7 @@ var URLSearchParamsImpl = class {
15514
15514
  this._list.push([key, value]);
15515
15515
  }
15516
15516
  sort() {
15517
- this._list.sort(([a2], [b7]) => a2 < b7 ? -1 : a2 > b7 ? 1 : 0);
15517
+ this._list.sort(([a2], [b8]) => a2 < b8 ? -1 : a2 > b8 ? 1 : 0);
15518
15518
  }
15519
15519
  forEach(fn) {
15520
15520
  for (const [k2, v2] of this._list)
@@ -15564,43 +15564,43 @@ var URLImpl = class _URLImpl {
15564
15564
  }
15565
15565
  if (base === void 0)
15566
15566
  throw new TypeError("Invalid URL");
15567
- const b7 = new _URLImpl(base);
15567
+ const b8 = new _URLImpl(base);
15568
15568
  if (p2.host) {
15569
- p2.scheme = b7._scheme;
15569
+ p2.scheme = b8._scheme;
15570
15570
  this._apply(p2);
15571
15571
  return;
15572
15572
  }
15573
15573
  if (!p2.path && !p2.query) {
15574
15574
  this._apply({
15575
- scheme: b7._scheme,
15576
- user: b7._username,
15577
- pass: b7._password,
15578
- host: b7._hostname,
15579
- port: b7._port,
15580
- path: b7._pathname,
15581
- query: b7._query,
15575
+ scheme: b8._scheme,
15576
+ user: b8._username,
15577
+ pass: b8._password,
15578
+ host: b8._hostname,
15579
+ port: b8._port,
15580
+ path: b8._pathname,
15581
+ query: b8._query,
15582
15582
  fragment: p2.fragment || ""
15583
15583
  });
15584
15584
  return;
15585
15585
  }
15586
- p2.scheme = b7._scheme;
15586
+ p2.scheme = b8._scheme;
15587
15587
  if (!p2.user)
15588
- p2.user = b7._username;
15588
+ p2.user = b8._username;
15589
15589
  if (!p2.pass)
15590
- p2.pass = b7._password;
15590
+ p2.pass = b8._password;
15591
15591
  if (!p2.host)
15592
- p2.host = b7._hostname;
15592
+ p2.host = b8._hostname;
15593
15593
  if (!p2.port)
15594
- p2.port = b7._port;
15594
+ p2.port = b8._port;
15595
15595
  if (!p2.fragment)
15596
15596
  p2.fragment = "";
15597
15597
  if (p2.path && !p2.path.startsWith("/")) {
15598
- const bd = b7._pathname.substring(0, b7._pathname.lastIndexOf("/") + 1);
15598
+ const bd = b8._pathname.substring(0, b8._pathname.lastIndexOf("/") + 1);
15599
15599
  p2.path = _normalizePath(bd + p2.path);
15600
15600
  } else if (!p2.path) {
15601
- p2.path = b7._pathname;
15601
+ p2.path = b8._pathname;
15602
15602
  if (!p2.query)
15603
- p2.query = b7._query;
15603
+ p2.query = b8._query;
15604
15604
  }
15605
15605
  this._apply(p2);
15606
15606
  }
@@ -15705,19 +15705,19 @@ function _normalizeLabel(label) {
15705
15705
  function _decodeUTF8(buf, fatal) {
15706
15706
  let out = "";
15707
15707
  for (let i2 = 0; i2 < buf.length; ) {
15708
- const b7 = buf[i2++];
15709
- if (b7 < 128) {
15710
- out += String.fromCharCode(b7);
15708
+ const b8 = buf[i2++];
15709
+ if (b8 < 128) {
15710
+ out += String.fromCharCode(b8);
15711
15711
  continue;
15712
15712
  }
15713
- if (b7 < 192) {
15713
+ if (b8 < 192) {
15714
15714
  out += fatal ? (() => {
15715
15715
  throw new TypeError("unexpected continuation byte");
15716
15716
  })() : "\uFFFD";
15717
15717
  continue;
15718
15718
  }
15719
15719
  let c2, min;
15720
- if (b7 < 224) {
15720
+ if (b8 < 224) {
15721
15721
  if (i2 >= buf.length) {
15722
15722
  out += fatal ? (() => {
15723
15723
  throw new TypeError("incomplete utf-8");
@@ -15729,9 +15729,9 @@ function _decodeUTF8(buf, fatal) {
15729
15729
  out += "\uFFFD";
15730
15730
  continue;
15731
15731
  }
15732
- c2 = (b7 & 31) << 6 | b22 & 63;
15732
+ c2 = (b8 & 31) << 6 | b22 & 63;
15733
15733
  min = 128;
15734
- } else if (b7 < 240) {
15734
+ } else if (b8 < 240) {
15735
15735
  if (i2 + 1 >= buf.length) {
15736
15736
  out += fatal ? (() => {
15737
15737
  throw new TypeError("incomplete utf-8");
@@ -15744,9 +15744,9 @@ function _decodeUTF8(buf, fatal) {
15744
15744
  out += "\uFFFD";
15745
15745
  continue;
15746
15746
  }
15747
- c2 = (b7 & 15) << 12 | (b22 & 63) << 6 | b32 & 63;
15747
+ c2 = (b8 & 15) << 12 | (b22 & 63) << 6 | b32 & 63;
15748
15748
  min = 2048;
15749
- } else if (b7 < 248) {
15749
+ } else if (b8 < 248) {
15750
15750
  if (i2 + 2 >= buf.length) {
15751
15751
  out += fatal ? (() => {
15752
15752
  throw new TypeError("incomplete utf-8");
@@ -15760,7 +15760,7 @@ function _decodeUTF8(buf, fatal) {
15760
15760
  out += "\uFFFD";
15761
15761
  continue;
15762
15762
  }
15763
- c2 = (b7 & 7) << 18 | (b22 & 63) << 12 | (b32 & 63) << 6 | b42 & 63;
15763
+ c2 = (b8 & 7) << 18 | (b22 & 63) << 12 | (b32 & 63) << 6 | b42 & 63;
15764
15764
  min = 65536;
15765
15765
  } else {
15766
15766
  out += fatal ? (() => {
@@ -15940,31 +15940,31 @@ function sha1Bytes(bytes) {
15940
15940
  for (let t2 = 16; t2 < 80; t2++) {
15941
15941
  w2[t2] = rotl(w2[t2 - 3] ^ w2[t2 - 8] ^ w2[t2 - 14] ^ w2[t2 - 16], 1);
15942
15942
  }
15943
- let a2 = h0, b7 = h1, c2 = h2, d2 = h3, e2 = h4;
15943
+ let a2 = h0, b8 = h1, c2 = h2, d2 = h3, e2 = h4;
15944
15944
  for (let t2 = 0; t2 < 80; t2++) {
15945
15945
  let f2, k2;
15946
15946
  if (t2 < 20) {
15947
- f2 = b7 & c2 | ~b7 & d2;
15947
+ f2 = b8 & c2 | ~b8 & d2;
15948
15948
  k2 = 1518500249;
15949
15949
  } else if (t2 < 40) {
15950
- f2 = b7 ^ c2 ^ d2;
15950
+ f2 = b8 ^ c2 ^ d2;
15951
15951
  k2 = 1859775393;
15952
15952
  } else if (t2 < 60) {
15953
- f2 = b7 & c2 | b7 & d2 | c2 & d2;
15953
+ f2 = b8 & c2 | b8 & d2 | c2 & d2;
15954
15954
  k2 = 2400959708;
15955
15955
  } else {
15956
- f2 = b7 ^ c2 ^ d2;
15956
+ f2 = b8 ^ c2 ^ d2;
15957
15957
  k2 = 3395469782;
15958
15958
  }
15959
15959
  const temp = rotl(a2, 5) + f2 + e2 + k2 + w2[t2] >>> 0;
15960
15960
  e2 = d2;
15961
15961
  d2 = c2;
15962
- c2 = rotl(b7, 30);
15963
- b7 = a2;
15962
+ c2 = rotl(b8, 30);
15963
+ b8 = a2;
15964
15964
  a2 = temp;
15965
15965
  }
15966
15966
  h0 = h0 + a2 >>> 0;
15967
- h1 = h1 + b7 >>> 0;
15967
+ h1 = h1 + b8 >>> 0;
15968
15968
  h2 = h2 + c2 >>> 0;
15969
15969
  h3 = h3 + d2 >>> 0;
15970
15970
  h4 = h4 + e2 >>> 0;
@@ -17513,7 +17513,7 @@ function Er(e2) {
17513
17513
  function Wr(e2, t2) {
17514
17514
  return Oe(e2._readableStreamController) ? (function(e3) {
17515
17515
  let t3, r2, o2, n2, i2, a2 = V(e3), s2 = false, l2 = false, d2 = false, f2 = false, h2 = false;
17516
- const b7 = u((e4) => {
17516
+ const b8 = u((e4) => {
17517
17517
  i2 = e4;
17518
17518
  });
17519
17519
  function m2(e4) {
@@ -17583,14 +17583,14 @@ function Wr(e2, t2) {
17583
17583
  const o4 = le([t3, r2]), n3 = Mr(e3, o4);
17584
17584
  i2(n3);
17585
17585
  }
17586
- return b7;
17586
+ return b8;
17587
17587
  }
17588
17588
  function R2(o3) {
17589
17589
  if (h2 = true, r2 = o3, f2) {
17590
17590
  const o4 = le([t3, r2]), n3 = Mr(e3, o4);
17591
17591
  i2(n3);
17592
17592
  }
17593
- return b7;
17593
+ return b8;
17594
17594
  }
17595
17595
  function T2() {
17596
17596
  }
@@ -17601,14 +17601,14 @@ function Wr(e2, t2) {
17601
17601
  const h2 = u((e4) => {
17602
17602
  a2 = e4;
17603
17603
  });
17604
- function b7() {
17604
+ function b8() {
17605
17605
  if (s2) return l2 = true, c(void 0);
17606
17606
  s2 = true;
17607
17607
  return te(t3, { _chunkSteps: (e4) => {
17608
17608
  y(() => {
17609
17609
  l2 = false;
17610
17610
  const t4 = e4, r3 = e4;
17611
- d2 || Rr(n2._readableStreamController, t4), f2 || Rr(i2._readableStreamController, r3), s2 = false, l2 && b7();
17611
+ d2 || Rr(n2._readableStreamController, t4), f2 || Rr(i2._readableStreamController, r3), s2 = false, l2 && b8();
17612
17612
  });
17613
17613
  }, _closeSteps: () => {
17614
17614
  s2 = false, d2 || wr(n2._readableStreamController), f2 || wr(i2._readableStreamController), d2 && f2 || a2(void 0);
@@ -17632,7 +17632,7 @@ function Wr(e2, t2) {
17632
17632
  }
17633
17633
  function S2() {
17634
17634
  }
17635
- return n2 = Dr(S2, b7, m2), i2 = Dr(S2, b7, p2), _(t3._closedPromise, (e4) => (Tr(n2._readableStreamController, e4), Tr(i2._readableStreamController, e4), d2 && f2 || a2(void 0), null)), [n2, i2];
17635
+ return n2 = Dr(S2, b8, m2), i2 = Dr(S2, b8, p2), _(t3._closedPromise, (e4) => (Tr(n2._readableStreamController, e4), Tr(i2._readableStreamController, e4), d2 && f2 || a2(void 0), null)), [n2, i2];
17636
17636
  })(e2);
17637
17637
  }
17638
17638
  function Or(r2) {
@@ -17941,7 +17941,7 @@ var TransformStream = class {
17941
17941
  if (void 0 !== i2.readableType) throw new RangeError("Invalid readableType specified");
17942
17942
  if (void 0 !== i2.writableType) throw new RangeError("Invalid writableType specified");
17943
17943
  const a2 = mt(n2, 0), s2 = pt(n2), l2 = mt(o2, 1), f2 = pt(o2);
17944
- let b7;
17944
+ let b8;
17945
17945
  !(function(e3, t3, r3, o3, n3, i3) {
17946
17946
  function a3() {
17947
17947
  return t3;
@@ -18005,7 +18005,7 @@ var TransformStream = class {
18005
18005
  return Ct(a4), Nt(a4, Object.create(WritableStreamDefaultController.prototype), e4, t4, r4, o4, n4, i4), a4;
18006
18006
  })(a3, s3, c2, l3, r3, o3), e3._readable = Dr(a3, d2, f3, n3, i3), e3._backpressure = void 0, e3._backpressureChangePromise = void 0, e3._backpressureChangePromise_resolve = void 0, ao(e3, true), e3._transformStreamController = void 0;
18007
18007
  })(this, u((e3) => {
18008
- b7 = e3;
18008
+ b8 = e3;
18009
18009
  }), l2, f2, a2, s2), (function(e3, t3) {
18010
18010
  const r3 = Object.create(TransformStreamDefaultController.prototype);
18011
18011
  let o3, n3, i3;
@@ -18021,7 +18021,7 @@ var TransformStream = class {
18021
18021
  !(function(e4, t4, r4, o4, n4) {
18022
18022
  t4._controlledTransformStream = e4, e4._transformStreamController = t4, t4._transformAlgorithm = r4, t4._flushAlgorithm = o4, t4._cancelAlgorithm = n4, t4._finishPromise = void 0, t4._finishPromise_resolve = void 0, t4._finishPromise_reject = void 0;
18023
18023
  })(e3, r3, o3, n3, i3);
18024
- })(this, i2), void 0 !== i2.start ? b7(i2.start(this._transformStreamController)) : b7(void 0);
18024
+ })(this, i2), void 0 !== i2.start ? b8(i2.start(this._transformStreamController)) : b8(void 0);
18025
18025
  }
18026
18026
  get readable() {
18027
18027
  if (!ro(this)) throw _o("readable");
@@ -19044,10 +19044,10 @@ async function sendResponse(c2, method, res) {
19044
19044
  await writeStreamingBody(c2, res.body, chunked, chunked && trailerDeclared ? res.trailers : void 0);
19045
19045
  }
19046
19046
 
19047
- // _build/examples/execd.js
19048
- import * as os6 from "os";
19047
+ // _build/examples/execd/main.js
19048
+ import * as os7 from "os";
19049
19049
  import * as std2 from "std";
19050
- import * as gui18 from "gui";
19050
+ import * as gui19 from "gui";
19051
19051
 
19052
19052
  // _build/lib/exec-log.js
19053
19053
  var RequestLog = class {
@@ -19566,13 +19566,13 @@ function lower(v2) {
19566
19566
  type: { tag: "array", elementType: el.type, elementSize: el.size }
19567
19567
  };
19568
19568
  }
19569
- const b7 = /^([A-Za-z_]\w*):(\d+)$/.exec(v2);
19570
- if (b7) {
19571
- const rawUnit = b7[1];
19569
+ const b8 = /^([A-Za-z_]\w*):(\d+)$/.exec(v2);
19570
+ if (b8) {
19571
+ const rawUnit = b8[1];
19572
19572
  const unit = normToken(rawUnit);
19573
19573
  if (!isCNumberToken(unit) || unit === "f32" || unit === "f64")
19574
19574
  throw new Error(`ffi-struct: bitfield unit must be an integer type, got "${rawUnit}"`);
19575
- const width = Number(b7[2]);
19575
+ const width = Number(b8[2]);
19576
19576
  const s3 = SizeAlign[unit];
19577
19577
  const cap = s3 * 8;
19578
19578
  if (!Number.isInteger(width) || width < 1)
@@ -19888,10 +19888,53 @@ function buildDecl(kind, member, pack) {
19888
19888
  decl[k2] = v2;
19889
19889
  return decl;
19890
19890
  }
19891
- function struct(a2, b7, c2) {
19891
+ function structArray(def) {
19892
+ const { fields, size } = def;
19893
+ const readN = (dv, n2) => {
19894
+ const out = [];
19895
+ for (let i2 = 0; i2 < n2; i2++)
19896
+ out.push(doDecode(dv, i2 * size, fields));
19897
+ return out;
19898
+ };
19899
+ return {
19900
+ encode: (els) => {
19901
+ if (!Array.isArray(els) || els.length === 0)
19902
+ throw new Error(`ffi-struct: structArray(def).encode(els) requires a non-empty element array (pass NULL for an empty pointer position)`);
19903
+ const out = def.alloc(els.length);
19904
+ for (let i2 = 0; i2 < els.length; i2++)
19905
+ def.encode(els[i2], out, i2 * def.size);
19906
+ return out;
19907
+ },
19908
+ decode: ((p2, count) => {
19909
+ if (count !== void 0 && (!Number.isInteger(count) || count < 0))
19910
+ throw new Error(`ffi-struct: structArray.decode(p, count) requires a non-negative integer count, got ${count}`);
19911
+ if (typeof p2 === "number") {
19912
+ if (count === void 0)
19913
+ throw new Error(`ffi-struct: structArray.decode(address, count) requires an explicit count (a bare address carries no length)`);
19914
+ if (count === 0)
19915
+ return [];
19916
+ return readN(new DataView(ffi2.readBytes(p2, count * size)), count);
19917
+ }
19918
+ let n2;
19919
+ if (count !== void 0) {
19920
+ n2 = count;
19921
+ if (n2 * size > p2.byteLength)
19922
+ throw new Error(`ffi-struct: structArray.decode: count ${n2} \xD7 size ${size} = ${n2 * size} exceeds buffer byteLength ${p2.byteLength}`);
19923
+ } else {
19924
+ if (p2.byteLength % size !== 0)
19925
+ throw new Error(`ffi-struct: structArray.decode: byteLength ${p2.byteLength} is not a multiple of size ${size} (mixed buffer? pass count explicitly)`);
19926
+ n2 = p2.byteLength / size;
19927
+ }
19928
+ if (n2 === 0)
19929
+ return [];
19930
+ return readN(new DataView(p2), n2);
19931
+ })
19932
+ };
19933
+ }
19934
+ function struct(a2, b8, c2) {
19892
19935
  const isNamed = typeof a2 === "string";
19893
- const raw = isNamed ? b7 : a2;
19894
- const opts = isNamed ? c2 : b7;
19936
+ const raw = isNamed ? b8 : a2;
19937
+ const opts = isNamed ? c2 : b8;
19895
19938
  return createStruct(buildDecl("struct", raw, opts?.pack));
19896
19939
  }
19897
19940
 
@@ -20185,6 +20228,41 @@ var DEVMODEW_DECL = {
20185
20228
  dmPanningHeight: "u32"
20186
20229
  };
20187
20230
  var DEVMODEW = /* @__PURE__ */ struct("DEVMODEW", DEVMODEW_DECL);
20231
+ var MOUSEINPUT_DECL = {
20232
+ "#": "struct",
20233
+ dx: "i32",
20234
+ dy: "i32",
20235
+ mouseData: "u32",
20236
+ dwFlags: "u32",
20237
+ time: "u32",
20238
+ dwExtraInfo: "<>ptr"
20239
+ };
20240
+ var KEYBDINPUT_DECL = {
20241
+ "#": "struct",
20242
+ wVk: "u16",
20243
+ wScan: "u16",
20244
+ dwFlags: "u32",
20245
+ time: "u32",
20246
+ dwExtraInfo: "<>ptr"
20247
+ };
20248
+ var INPUT_DECL = {
20249
+ "#": "struct",
20250
+ type: "u32",
20251
+ data: {
20252
+ "#": "union",
20253
+ mi: MOUSEINPUT_DECL,
20254
+ ki: KEYBDINPUT_DECL
20255
+ }
20256
+ };
20257
+ var INPUT = /* @__PURE__ */ struct("INPUT", INPUT_DECL);
20258
+ var NOTIFYICONIDENTIFIER_DECL = {
20259
+ "#": "struct",
20260
+ cbSize: "u32",
20261
+ hWnd: "<HWND>ptr",
20262
+ uID: "u32",
20263
+ guidItem: "u32[4]"
20264
+ };
20265
+ var NOTIFYICONIDENTIFIER = /* @__PURE__ */ struct("NOTIFYICONIDENTIFIER", NOTIFYICONIDENTIFIER_DECL);
20188
20266
 
20189
20267
  // _build/lib/windows/user32.js
20190
20268
  var b2 = (name, sig, encoders) => bind2("user32.dll", name, sig, encoders);
@@ -20193,13 +20271,17 @@ var LONG_PTR_SYM = os4.arch === "x64" ? "PtrW" : "W";
20193
20271
  var SetWindowPos = /* @__PURE__ */ b2("SetWindowPos", "<HWND>ptr <>ptr@SetWindowPosHwnd i32 i32 i32 i32 u32 -> i32");
20194
20272
  var GetWindowRect = /* @__PURE__ */ b2("GetWindowRect", "<HWND>ptr <RECT>ptr -> i32");
20195
20273
  var GetClientRect = /* @__PURE__ */ b2("GetClientRect", "<HWND>ptr <RECT>ptr -> i32");
20274
+ var IsWindow = /* @__PURE__ */ b2("IsWindow", "<HWND>ptr -> i32");
20196
20275
  var IsWindowVisible = /* @__PURE__ */ b2("IsWindowVisible", "<HWND>ptr -> i32");
20197
20276
  var IsIconic = /* @__PURE__ */ b2("IsIconic", "<HWND>ptr -> i32");
20277
+ var FindWindow = /* @__PURE__ */ b2("FindWindowW", "<WCHAR>ptr <WCHAR>ptr -> <HWND>ptr");
20278
+ var FindWindowEx = /* @__PURE__ */ b2("FindWindowExW", "<HWND>ptr <HWND>ptr <WCHAR>ptr <WCHAR>ptr -> <HWND>ptr");
20198
20279
  var GetWindowText = /* @__PURE__ */ b2("GetWindowTextW", "<HWND>ptr <BYTE>ptr i32 -> i32");
20199
20280
  var SetWindowText = /* @__PURE__ */ b2("SetWindowTextW", "<HWND>ptr <WCHAR>ptr -> i32");
20200
20281
  var GetClassName = /* @__PURE__ */ b2("GetClassNameW", "<HWND>ptr <BYTE>ptr i32 -> i32");
20201
20282
  var GetWindowLongPtr = /* @__PURE__ */ b2("GetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp -> <>ptr");
20202
20283
  var SetWindowLongPtr = /* @__PURE__ */ b2("SetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp <>ptr -> <>ptr");
20284
+ var GetWindowThreadProcessId = /* @__PURE__ */ b2("GetWindowThreadProcessId", "<HWND>ptr <BYTE>ptr -> u32");
20203
20285
  var EnableWindow = /* @__PURE__ */ b2("EnableWindow", "<HWND>ptr i32 -> i32");
20204
20286
  var SetParent = /* @__PURE__ */ b2("SetParent", "<HWND>ptr <HWND>ptr -> <HWND>ptr");
20205
20287
  var DefWindowProc = /* @__PURE__ */ b2("DefWindowProcW", "<HWND>ptr u32@AnyMsg <>ptr <>ptr -> <>ptr");
@@ -20214,6 +20296,8 @@ var LoadCursor = /* @__PURE__ */ b2("LoadCursorW", "<HMODULE>ptr <>ptr -> <HCURS
20214
20296
  var GetCursorPos = /* @__PURE__ */ b2("GetCursorPos", "<POINT>ptr -> i32");
20215
20297
  var ScreenToClient = /* @__PURE__ */ b2("ScreenToClient", "<HWND>ptr <POINT>ptr -> i32");
20216
20298
  var ClientToScreen = /* @__PURE__ */ b2("ClientToScreen", "<HWND>ptr <POINT>ptr -> i32");
20299
+ var INPUTArr = /* @__PURE__ */ structArray(INPUT);
20300
+ var SendInput = /* @__PURE__ */ b2("SendInput", "u32 <INPUT>ptr i32 -> u32", { INPUT: INPUTArr });
20217
20301
  var ShowScrollBar = /* @__PURE__ */ b2("ShowScrollBar", "<HWND>ptr u32 i32 -> i32");
20218
20302
  var GetSystemMetrics = /* @__PURE__ */ b2("GetSystemMetrics", "i32 -> i32");
20219
20303
  var EnumWindows = /* @__PURE__ */ b2("EnumWindows", "<>ptr <>ptr -> i32");
@@ -20266,14 +20350,14 @@ function applyProps(instance, newProps, _oldProps) {
20266
20350
  gui.ShowWindow(
20267
20351
  hwnd,
20268
20352
  newProps.hidden ? 0 : 5
20269
- /* gui.ShowWindowCmd.SHOW */
20353
+ /* ShowWindowCmd.SHOW */
20270
20354
  );
20271
20355
  }
20272
20356
  if ("visible" in newProps) {
20273
20357
  gui.ShowWindow(
20274
20358
  hwnd,
20275
20359
  newProps.visible ? 5 : 0
20276
- /* gui.ShowWindowCmd.HIDE */
20360
+ /* ShowWindowCmd.HIDE */
20277
20361
  );
20278
20362
  }
20279
20363
  }
@@ -20369,7 +20453,7 @@ function measureText(hdc, text, maxWidth) {
20369
20453
  -1,
20370
20454
  r2.ptr,
20371
20455
  1024
20372
- /* gui.DrawTextFlag.CALCRECT */
20456
+ /* DrawTextFlag.CALCRECT */
20373
20457
  );
20374
20458
  const { right, bottom } = RECT.decode(r2);
20375
20459
  return { width: right, height: bottom };
@@ -20417,7 +20501,7 @@ function setupWindowProc(instance, hwnd) {
20417
20501
  const oldProc = GetWindowLongPtr(
20418
20502
  hwnd,
20419
20503
  -4
20420
- /* gui.Gwlp.WNDPROC */
20504
+ /* Gwlp.WNDPROC */
20421
20505
  );
20422
20506
  instancesByHwnd.set(hwnd, instance);
20423
20507
  gui3.SetWindowProc(hwnd, (hwnd2, msg, wParam, lParam) => {
@@ -20505,7 +20589,7 @@ function runFlexLayout(inst) {
20505
20589
  r2.width * scaleFactor,
20506
20590
  r2.height * scaleFactor,
20507
20591
  64
20508
- /* gui.SetWindowPosFlag.SWP_SHOWWINDOW */
20592
+ /* SetWindowPosFlag.SWP_SHOWWINDOW */
20509
20593
  );
20510
20594
  InvalidateRect(child.hwnd, NULL, 1);
20511
20595
  child.lastRect = { x: r2.x, y: r2.y, w: r2.width, h: r2.height };
@@ -20661,7 +20745,7 @@ var hostConfig = {
20661
20745
  gui3.ShowWindow(
20662
20746
  instance.hwnd,
20663
20747
  0
20664
- /* gui.ShowWindowCmd.HIDE */
20748
+ /* ShowWindowCmd.HIDE */
20665
20749
  );
20666
20750
  },
20667
20751
  hideTextInstance(instance) {
@@ -20669,7 +20753,7 @@ var hostConfig = {
20669
20753
  gui3.ShowWindow(
20670
20754
  instance.hwnd,
20671
20755
  0
20672
- /* gui.ShowWindowCmd.HIDE */
20756
+ /* ShowWindowCmd.HIDE */
20673
20757
  );
20674
20758
  },
20675
20759
  unhideInstance(instance, _props) {
@@ -20677,7 +20761,7 @@ var hostConfig = {
20677
20761
  gui3.ShowWindow(
20678
20762
  instance.hwnd,
20679
20763
  5
20680
- /* gui.ShowWindowCmd.SHOW */
20764
+ /* ShowWindowCmd.SHOW */
20681
20765
  );
20682
20766
  },
20683
20767
  unhideTextInstance(instance, _text) {
@@ -20685,7 +20769,7 @@ var hostConfig = {
20685
20769
  gui3.ShowWindow(
20686
20770
  instance.hwnd,
20687
20771
  5
20688
- /* gui.ShowWindowCmd.SHOW */
20772
+ /* ShowWindowCmd.SHOW */
20689
20773
  );
20690
20774
  },
20691
20775
  shouldSetTextContent(_type, props) {
@@ -21113,7 +21197,7 @@ function getCellFont(hwnd, style) {
21113
21197
  ...base,
21114
21198
  ...style.bold ? {
21115
21199
  lfWeight: 700
21116
- /* gui.FontWeight.BOLD */
21200
+ /* FontWeight.BOLD */
21117
21201
  } : {},
21118
21202
  ...style.italic ? { lfItalic: 1 } : {},
21119
21203
  ...style.underline ? { lfUnderline: 1 } : {}
@@ -21171,7 +21255,7 @@ function resolveCellStyle(columns, data, row, colIndex) {
21171
21255
  }
21172
21256
  function makeLVItem(i2, sub, text, image) {
21173
21257
  const textBuf = WCHAR.encode(text);
21174
- const b7 = LVITEMW.encode({
21258
+ const b8 = LVITEMW.encode({
21175
21259
  mask: 1 | (image !== void 0 ? 2 : 0),
21176
21260
  iItem: i2,
21177
21261
  iSubItem: sub,
@@ -21188,8 +21272,8 @@ function makeLVItem(i2, sub, text, image) {
21188
21272
  piColFmt: 0,
21189
21273
  iGroup: 0
21190
21274
  });
21191
- b7.__textBuf = textBuf;
21192
- return b7;
21275
+ b8.__textBuf = textBuf;
21276
+ return b8;
21193
21277
  }
21194
21278
  var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, data, style, icons, iconSize, getIcon }, ref) {
21195
21279
  const lvRef = (0, import_react9.useRef)(null);
@@ -21235,7 +21319,7 @@ var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, d
21235
21319
  4150,
21236
21320
  0,
21237
21321
  32 | 1 | 65536
21238
- /* gui.LvExStyle.DOUBLEBUFFER */
21322
+ /* LvExStyle.DOUBLEBUFFER */
21239
21323
  );
21240
21324
  const n2 = columns.length;
21241
21325
  for (let j2 = 0; j2 < n2; j2++) {
@@ -21280,7 +21364,7 @@ var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, d
21280
21364
  4126,
21281
21365
  j2,
21282
21366
  -2
21283
- /* gui.LvColumnWidthCmd.AUTOSIZE_USEHEADER */
21367
+ /* LvColumnWidthCmd.AUTOSIZE_USEHEADER */
21284
21368
  );
21285
21369
  }
21286
21370
  }
@@ -21422,7 +21506,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21422
21506
  natW,
21423
21507
  natH,
21424
21508
  4
21425
- /* gui.SetWindowPosFlag.SWP_NOZORDER */
21509
+ /* SetWindowPosFlag.SWP_NOZORDER */
21426
21510
  );
21427
21511
  forceFlexLayout(content);
21428
21512
  if (natW > svW) {
@@ -21461,7 +21545,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21461
21545
  0,
21462
21546
  0,
21463
21547
  1 | 4
21464
- /* gui.SetWindowPosFlag.SWP_NOZORDER */
21548
+ /* SetWindowPosFlag.SWP_NOZORDER */
21465
21549
  );
21466
21550
  gui12.SetScrollInfo(sv, bar, { pos: newPos }, true);
21467
21551
  }
@@ -21527,7 +21611,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21527
21611
  handleScroll(
21528
21612
  e2,
21529
21613
  1
21530
- /* gui.ScrollBar.VERT */
21614
+ /* ScrollBar.VERT */
21531
21615
  );
21532
21616
  return 0;
21533
21617
  }
@@ -21535,7 +21619,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21535
21619
  handleScroll(
21536
21620
  e2,
21537
21621
  0
21538
- /* gui.ScrollBar.HORZ */
21622
+ /* ScrollBar.HORZ */
21539
21623
  );
21540
21624
  return 0;
21541
21625
  }
@@ -21699,7 +21783,7 @@ function deleteAllItems(hTree) {
21699
21783
  4353,
21700
21784
  1,
21701
21785
  -65536
21702
- /* gui.TvInsertAfter.ROOT */
21786
+ /* TvInsertAfter.ROOT */
21703
21787
  );
21704
21788
  }
21705
21789
  var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onSelect, defaultSelectedKey, selectedKey: controlledKey, style }, ref) {
@@ -21731,7 +21815,7 @@ var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onS
21731
21815
  4396,
21732
21816
  0,
21733
21817
  4
21734
- /* gui.TvExStyle.DOUBLEBUFFER */
21818
+ /* TvExStyle.DOUBLEBUFFER */
21735
21819
  );
21736
21820
  }, []);
21737
21821
  (0, import_react16.useEffect)(() => {
@@ -21773,9 +21857,16 @@ var b4 = (name, sig) => bind2("comdlg32.dll", name, sig);
21773
21857
  var GetOpenFileName = /* @__PURE__ */ b4("GetOpenFileNameW", "<OPENFILENAMEW>ptr -> u32");
21774
21858
 
21775
21859
  // _build/lib/windows/shell32.js
21776
- var b5 = (name, sig) => bind2("shell32.dll", name, sig);
21860
+ var b5 = (name, sig, encoders) => bind2("shell32.dll", name, sig, encoders);
21777
21861
  var SHBrowseForFolder = /* @__PURE__ */ b5("SHBrowseForFolderW", "<BROWSEINFOW>ptr -> <>ptr");
21778
21862
  var SHGetPathFromIDList = /* @__PURE__ */ b5("SHGetPathFromIDListW", "<>ptr <BYTE>ptr -> u32");
21863
+ var Shell_NotifyIconGetRect = (() => {
21864
+ try {
21865
+ return b5("Shell_NotifyIconGetRect", "<NOTIFYICONIDENTIFIER>ptr <RECT>ptr -> i32", { NOTIFYICONIDENTIFIER });
21866
+ } catch {
21867
+ return null;
21868
+ }
21869
+ })();
21779
21870
 
21780
21871
  // _build/lib/windows/ole32.js
21781
21872
  var b6 = (name, sig) => bind2("ole32.dll", name, sig);
@@ -21928,28 +22019,183 @@ function createRoot(container) {
21928
22019
  };
21929
22020
  }
21930
22021
 
21931
- // _build/examples/execd.js
22022
+ // _build/examples/execd/main.js
21932
22023
  var import_react18 = __toESM(require_react(), 1);
22024
+
22025
+ // _build/examples/execd/tray.js
22026
+ import * as os6 from "os";
22027
+ import * as gui18 from "gui";
22028
+
22029
+ // _build/lib/windows/kernel32.js
22030
+ var b7 = (name, sig, encoders) => bind2("kernel32.dll", name, sig, encoders);
22031
+ var CloseHandle = /* @__PURE__ */ b7("CloseHandle", "<>ptr -> i32");
22032
+ var OpenProcess = /* @__PURE__ */ b7("OpenProcess", "u32 i32 u32 -> <HPROCESS>ptr");
22033
+ var GetCurrentProcess = /* @__PURE__ */ b7("GetCurrentProcess", " -> <HPROCESS>ptr");
22034
+ var VirtualAllocEx = /* @__PURE__ */ b7("VirtualAllocEx", "<HPROCESS>ptr <>ptr <>ptr u32 u32 -> <>ptr");
22035
+ var VirtualFreeEx = /* @__PURE__ */ b7("VirtualFreeEx", "<HPROCESS>ptr <>ptr <>ptr u32 -> i32");
22036
+ var ReadProcessMemory = /* @__PURE__ */ b7("ReadProcessMemory", "<HPROCESS>ptr <>ptr <BYTE>ptr <>ptr <>ptr -> i32");
22037
+ var IsWow64Process = /* @__PURE__ */ b7("IsWow64Process", "<HPROCESS>ptr <BYTE>ptr -> i32");
22038
+
22039
+ // _build/examples/execd/tray.js
22040
+ var TB_GETBUTTON = 1047;
22041
+ var TB_BUTTONCOUNT = 1048;
22042
+ var TB_GETITEMRECT = 1053;
22043
+ var CLS_BUF = 512;
22044
+ var OS64 = os6.arch === "x64" || (() => {
22045
+ const wow = new PtrArrayBuffer(4);
22046
+ return IsWow64Process(GetCurrentProcess(), wow) !== 0 && new Uint32Array(wow)[0] !== 0;
22047
+ })();
22048
+ var TBBUTTON_DWDATA = OS64 ? 16 : 12;
22049
+ var TBBUTTON_ISTRING = OS64 ? 24 : 16;
22050
+ var TBBUTTON_SZ = OS64 ? 32 : 20;
22051
+ var TRAYDATA_UID = OS64 ? 8 : 4;
22052
+ var REMOTE_BUF = 256;
22053
+ function findToolbars(root) {
22054
+ const out = [];
22055
+ const cls = WCHAR.alloc(CLS_BUF);
22056
+ const walk = (parent) => {
22057
+ let child = FindWindowEx(parent, NULL, NULL, NULL);
22058
+ while (child) {
22059
+ const n2 = GetClassName(child, cls, CLS_BUF);
22060
+ if (n2 > 0 && WCHAR.decode(cls) === "ToolbarWindow32")
22061
+ out.push(child);
22062
+ walk(child);
22063
+ child = FindWindowEx(parent, child, NULL, NULL);
22064
+ }
22065
+ };
22066
+ walk(root);
22067
+ return out;
22068
+ }
22069
+ function readToolbar(tb, area, out) {
22070
+ const count = gui18.SendMessage(tb, TB_BUTTONCOUNT, 0, 0);
22071
+ if (!Number.isInteger(count) || count <= 0 || count > 512)
22072
+ return;
22073
+ const pidBuf = BYTE.alloc(4);
22074
+ if (GetWindowThreadProcessId(tb, pidBuf) === 0)
22075
+ return;
22076
+ const pid = new Uint32Array(pidBuf)[0];
22077
+ const proc = OpenProcess(56, 0, pid);
22078
+ if (!proc)
22079
+ throw new Error("OpenProcess(explorer " + pid + ") failed");
22080
+ const remote = VirtualAllocEx(proc, NULL, REMOTE_BUF, 12288, 4);
22081
+ if (!remote) {
22082
+ CloseHandle(proc);
22083
+ throw new Error("VirtualAllocEx failed");
22084
+ }
22085
+ try {
22086
+ const tbBuf = BYTE.alloc(REMOTE_BUF), trBuf = BYTE.alloc(REMOTE_BUF), tipBuf = BYTE.alloc(REMOTE_BUF);
22087
+ const dvTb = new DataView(tbBuf), dvTr = new DataView(trBuf);
22088
+ for (let i2 = 0; i2 < count; i2++) {
22089
+ if (!gui18.SendMessage(tb, TB_GETBUTTON, i2, remote))
22090
+ continue;
22091
+ if (!ReadProcessMemory(proc, remote, tbBuf, TBBUTTON_SZ, NULL))
22092
+ continue;
22093
+ const dwData = OS64 ? Number(dvTb.getBigUint64(TBBUTTON_DWDATA, true)) : dvTb.getUint32(TBBUTTON_DWDATA, true);
22094
+ if (dwData < 65536)
22095
+ continue;
22096
+ if (!ReadProcessMemory(proc, dwData, trBuf, TRAYDATA_UID + 4, NULL))
22097
+ continue;
22098
+ const hWnd = OS64 ? Number(dvTr.getBigUint64(0, true)) : dvTr.getUint32(0, true);
22099
+ const uID = dvTr.getUint32(TRAYDATA_UID, true);
22100
+ if (!hWnd || !IsWindow(hWnd))
22101
+ continue;
22102
+ let rect = null;
22103
+ if (gui18.SendMessage(tb, TB_GETITEMRECT, i2, remote) && ReadProcessMemory(proc, remote, trBuf, 16, NULL)) {
22104
+ const L2 = dvTr.getInt32(0, true), T2 = dvTr.getInt32(4, true);
22105
+ const R2 = dvTr.getInt32(8, true), B2 = dvTr.getInt32(12, true);
22106
+ if (!(L2 === 0 && T2 === 0 && R2 === 0 && B2 === 0)) {
22107
+ const tl = POINT.encode({ x: L2, y: T2 }), br2 = POINT.encode({ x: R2, y: B2 });
22108
+ if (ClientToScreen(tb, tl.ptr) && ClientToScreen(tb, br2.ptr)) {
22109
+ const a2 = POINT.decode(tl), b8 = POINT.decode(br2);
22110
+ rect = { left: a2.x, top: a2.y, right: b8.x, bottom: b8.y };
22111
+ }
22112
+ }
22113
+ }
22114
+ const iStr = OS64 ? Number(dvTb.getBigUint64(TBBUTTON_ISTRING, true)) : dvTb.getUint32(TBBUTTON_ISTRING, true);
22115
+ let tooltip = null;
22116
+ if (iStr >= 65536 && ReadProcessMemory(proc, iStr, tipBuf, 256, NULL)) {
22117
+ const dvTip = new DataView(tipBuf);
22118
+ let s2 = "";
22119
+ for (let off = 0; off < 256; off += 2) {
22120
+ const c2 = dvTip.getUint16(off, true);
22121
+ if (c2 === 0)
22122
+ break;
22123
+ s2 += String.fromCharCode(c2);
22124
+ }
22125
+ tooltip = s2 === "" ? null : s2;
22126
+ }
22127
+ out.push({ area, index: i2, hWnd, uID, tooltip, rect });
22128
+ }
22129
+ } finally {
22130
+ VirtualFreeEx(proc, remote, 0, 32768);
22131
+ CloseHandle(proc);
22132
+ }
22133
+ }
22134
+ function collectArea(root, area, out) {
22135
+ for (const tb of findToolbars(root))
22136
+ readToolbar(tb, area, out);
22137
+ }
22138
+ function collectVisible(root, out) {
22139
+ let main = null;
22140
+ let mainRight = -Infinity;
22141
+ for (const tb of findToolbars(root)) {
22142
+ const rc2 = RECT.alloc();
22143
+ if (!GetWindowRect(tb, rc2.ptr))
22144
+ continue;
22145
+ const right = RECT.decode(rc2).right;
22146
+ if (right > mainRight) {
22147
+ mainRight = right;
22148
+ main = tb;
22149
+ }
22150
+ }
22151
+ if (main)
22152
+ readToolbar(main, "visible", out);
22153
+ }
22154
+ function listTrayIcons() {
22155
+ const icons = [];
22156
+ const tray = FindWindow("Shell_TrayWnd", NULL);
22157
+ if (tray) {
22158
+ const notifyArea = FindWindowEx(tray, NULL, "TrayNotifyWnd", NULL);
22159
+ collectVisible(notifyArea ? notifyArea : tray, icons);
22160
+ }
22161
+ const overflow = FindWindow("NotifyIconOverflowWindow", NULL);
22162
+ if (overflow)
22163
+ collectArea(overflow, "overflow", icons);
22164
+ return icons;
22165
+ }
22166
+ function probeTrayIcon(hWnd, uID) {
22167
+ if (!Shell_NotifyIconGetRect)
22168
+ return { hr: -1, hrName: "unsupported", rect: null };
22169
+ const rc2 = RECT.alloc();
22170
+ const hr2 = Shell_NotifyIconGetRect({ cbSize: NOTIFYICONIDENTIFIER.size, hWnd, uID }, rc2.ptr);
22171
+ const hrName = hr2 === 0 ? "found" : hr2 === 1 ? "hidden" : hr2 === -2147467259 ? "not_found" : "hr=0x" + (hr2 >>> 0).toString(16);
22172
+ if (hr2 !== 0)
22173
+ return { hr: hr2, hrName, rect: null };
22174
+ const r2 = RECT.decode(rc2);
22175
+ return { hr: hr2, hrName, rect: { left: r2.left, top: r2.top, right: r2.right, bottom: r2.bottom } };
22176
+ }
22177
+
22178
+ // _build/examples/execd/main.js
21933
22179
  function parseArgs() {
21934
- let gui19 = true;
22180
+ let gui20 = true;
21935
22181
  let token = null;
21936
22182
  const args = typeof scriptArgs === "undefined" ? [] : scriptArgs;
21937
22183
  const normToken2 = (v2) => v2 === "" ? null : v2;
21938
22184
  for (let i2 = 0; i2 < args.length; i2++) {
21939
22185
  const a2 = args[i2] ?? "";
21940
22186
  if (a2 === "--nogui") {
21941
- gui19 = false;
22187
+ gui20 = false;
21942
22188
  } else if (a2 === "--gui") {
21943
- gui19 = (args[++i2] ?? "") !== "0";
22189
+ gui20 = (args[++i2] ?? "") !== "0";
21944
22190
  } else if (a2.startsWith("--gui=")) {
21945
- gui19 = a2.slice(6) !== "0";
22191
+ gui20 = a2.slice(6) !== "0";
21946
22192
  } else if (a2 === "--token") {
21947
22193
  token = normToken2(args[++i2] ?? "");
21948
22194
  } else if (a2.startsWith("--token=")) {
21949
22195
  token = normToken2(a2.slice(8));
21950
22196
  }
21951
22197
  }
21952
- return { gui: gui19, token };
22198
+ return { gui: gui20, token };
21953
22199
  }
21954
22200
  var cfg = parseArgs();
21955
22201
  var log = new RequestLog(100);
@@ -21983,7 +22229,7 @@ function formatInfo() {
21983
22229
  function refreshGui() {
21984
22230
  if (!guiUpdater || guiTimer !== null)
21985
22231
  return;
21986
- guiTimer = os6.setTimeout(() => {
22232
+ guiTimer = os7.setTimeout(() => {
21987
22233
  guiTimer = null;
21988
22234
  const u2 = guiUpdater;
21989
22235
  if (u2)
@@ -22013,10 +22259,10 @@ function initGui() {
22013
22259
  height: 420
22014
22260
  });
22015
22261
  root.render((0, import_jsx_runtime16.jsx)(LogPanel, {}));
22016
- gui18.ShowWindow(
22262
+ gui19.ShowWindow(
22017
22263
  root.hwnd,
22018
22264
  9
22019
- /* gui.ShowWindowCmd.RESTORE */
22265
+ /* ShowWindowCmd.RESTORE */
22020
22266
  );
22021
22267
  } catch (ex) {
22022
22268
  console.error("[execd] gui init failed (fallback headless):", ex);
@@ -22045,7 +22291,7 @@ function authCheck(req) {
22045
22291
  }
22046
22292
  function runInWorker(cmd, signal, timeoutMs) {
22047
22293
  const spawnCmd = cmd;
22048
- const worker = new os6.Worker("data:text/javascript;base64,aW1wb3J0KmFzIE90IGZyb20ib3MiO2ltcG9ydCphcyBMdCBmcm9tInN0ZCI7aW1wb3J0KmFzIGIgZnJvbSJmZmkiO2ltcG9ydCphcyBkdCBmcm9tIm9zIjtpbXBvcnQqYXMgbXQgZnJvbSJzdGQiO2ltcG9ydCphcyAkIGZyb20id2luIjt2YXIgUHQ9eyJ1dGYtOCI6InV0Zi04Iix1dGY4OiJ1dGYtOCIsInVuaWNvZGUtMS0xLXV0Zi04IjoidXRmLTgiLCJ1dGYtMTYiOiJ1dGYtMTZsZSIsInV0Zi0xNmxlIjoidXRmLTE2bGUiLCJ1dGYtMTZiZSI6InV0Zi0xNmJlIn07ZnVuY3Rpb24gc3QodCl7aWYoIXQpcmV0dXJuInV0Zi04IjtsZXQgZT1QdFt0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXTtpZihlKXJldHVybiBlO3Rocm93IG5ldyBSYW5nZUVycm9yKGBUaGUgZW5jb2RpbmcgbGFiZWwgIiR7dH0iIGlzIG5vdCBzdXBwb3J0ZWRgKX1mdW5jdGlvbiBNdCh0LGUpe2xldCByPSIiO2ZvcihsZXQgbj0wO248dC5sZW5ndGg7KXtsZXQgbz10W24rK107aWYobzwxMjgpe3IrPVN0cmluZy5mcm9tQ2hhckNvZGUobyk7Y29udGludWV9aWYobzwxOTIpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCBjb250aW51YXRpb24gYnl0ZSIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1sZXQgaSxjO2lmKG88MjI0KXtpZihuPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbisrXTtpZigocyYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShvJjMxKTw8NnxzJjYzLGM9MTI4fWVsc2UgaWYobzwyNDApe2lmKG4rMT49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W24rK10sdT10W24rK107aWYoKHMmMTkyKSE9PTEyOHx8KHUmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obyYxNSk8PDEyfChzJjYzKTw8Nnx1JjYzLGM9MjA0OH1lbHNlIGlmKG88MjQ4KXtpZihuKzI+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtuKytdLHU9dFtuKytdLHA9dFtuKytdO2lmKChzJjE5MikhPT0xMjh8fCh1JjE5MikhPT0xMjh8fChwJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG8mNyk8PDE4fChzJjYzKTw8MTJ8KHUmNjMpPDw2fHAmNjMsYz02NTUzNn1lbHNle3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBzdGFydCIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1pZihpPGN8fGk+PTU1Mjk2JiZpPD01NzM0M3x8aT4xMTE0MTExKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgdXRmLTggY29kZXBvaW50Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWk8PTY1NTM1P3IrPVN0cmluZy5mcm9tQ2hhckNvZGUoaSk6KGktPTY1NTM2LHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8aT4+MTAsNTYzMjB8aSYxMDIzKSl9cmV0dXJuIHJ9ZnVuY3Rpb24gV3QodCxlLHIpe2xldCBuPW5ldyBEYXRhVmlldyh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKSxvPSIiO2ZvcihsZXQgaT0wO2krMTx0Lmxlbmd0aDtpKz0yKXtsZXQgYz1uLmdldFVpbnQxNihpLGUpO2lmKGM+PTU1Mjk2JiZjPD01NjMxOSl7aWYoaSs9MixpKzE+PXQubGVuZ3RoKXtvKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInRydW5jYXRlZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz1uLmdldFVpbnQxNihpLGUpO3M+PTU2MzIwJiZzPD01NzM0Mz9vKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMscyk6KG8rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIixpLT0yKX1lbHNlIGM+PTU2MzIwJiZjPD01NzM0Mz9vKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInVuZXhwZWN0ZWQgdHJhaWxpbmcgc3Vycm9nYXRlIil9KSgpOiJcdUZGRkQiOm8rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyl9cmV0dXJuIG99dmFyIFk9Y2xhc3N7X2VuY29kaW5nO19mYXRhbDtfaWdub3JlQk9NO2NvbnN0cnVjdG9yKGUscil7dGhpcy5fZW5jb2Rpbmc9c3QoZSksdGhpcy5fZmF0YWw9cj8uZmF0YWw/PyExLHRoaXMuX2lnbm9yZUJPTT1yPy5pZ25vcmVCT00/PyExfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31nZXQgZmF0YWwoKXtyZXR1cm4gdGhpcy5fZmF0YWx9Z2V0IGlnbm9yZUJPTSgpe3JldHVybiB0aGlzLl9pZ25vcmVCT019ZGVjb2RlKGUpe2lmKCFlKXJldHVybiIiO2xldCByPWUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP25ldyBVaW50OEFycmF5KGUpOm5ldyBVaW50OEFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCxlLmJ5dGVMZW5ndGgpO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04IilyZXR1cm4gTXQocix0aGlzLl9mYXRhbCk7bGV0IG49dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG89MDtpZihyLmxlbmd0aD49MiYmIXRoaXMuX2lnbm9yZUJPTSl7bGV0IGk9bj9yWzBdOnJbMV0scz0obj9yWzFdOnJbMF0pPDw4fGk7KHM9PT02NTI3OXx8cz09PTY1NTM0KSYmKG89Mil9cmV0dXJuIFd0KHIuc2xpY2Uobyksbix0aGlzLl9mYXRhbCl9fSx2PWNsYXNze19lbmNvZGluZztjb25zdHJ1Y3RvcihlKXt0aGlzLl9lbmNvZGluZz1zdChlKX1nZXQgZW5jb2RpbmcoKXtyZXR1cm4gdGhpcy5fZW5jb2Rpbmd9ZW5jb2RlKGUpe2lmKCFlKXJldHVybiBuZXcgVWludDhBcnJheSgwKTtpZih0aGlzLl9lbmNvZGluZz09PSJ1dGYtOCIpe2xldCBpPVtdO2ZvcihsZXQgYz0wO2M8ZS5sZW5ndGg7YysrKXtsZXQgcz1lLmNoYXJDb2RlQXQoYyk7aWYoczwxMjgpaS5wdXNoKHMpO2Vsc2UgaWYoczwyMDQ4KWkucHVzaCgxOTJ8cz4+NiwxMjh8cyY2Myk7ZWxzZSBpZihzPDU1Mjk2fHxzPj01NzM0NClpLnB1c2goMjI0fHM+PjEyLDEyOHxzPj42JjYzLDEyOHxzJjYzKTtlbHNle2MrKztsZXQgdT1lLmNoYXJDb2RlQXQoYyk7cz02NTUzNisoKHMmMTAyMyk8PDEwKXx1JjEwMjMsaS5wdXNoKDI0MHxzPj4xOCwxMjh8cz4+MTImNjMsMTI4fHM+PjYmNjMsMTI4fHMmNjMpfX1yZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaSl9bGV0IHI9dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG49bmV3IEFycmF5QnVmZmVyKGUubGVuZ3RoKjIpLG89bmV3IERhdGFWaWV3KG4pO2ZvcihsZXQgaT0wO2k8ZS5sZW5ndGg7aSsrKW8uc2V0VWludDE2KGkqMixlLmNoYXJDb2RlQXQoaSkscik7cmV0dXJuIG5ldyBVaW50OEFycmF5KG4pfX07dHlwZW9mIGdsb2JhbFRoaXMuVGV4dERlY29kZXI+InUiJiYoZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj1ZKTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RW5jb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHRFbmNvZGVyPXYpO2ltcG9ydHtidWZmZXJQdHIgYXMgUnR9ZnJvbSJmZmkiO2ltcG9ydCphcyBjdCBmcm9tIm9zIjt2YXIga3Q9WyJ2b2lkIiwidTgiLCJpOCIsInUxNiIsImkxNiIsInUzMiIsImkzMiIsInU2NCIsImk2NCIsImYzMiIsImY2NCIsInB0ciJdLGo9L148KFtBLVphLXpfXVx3KnwpPnB0cighfEBbQS1aYS16X11cdyopPyQvO2Z1bmN0aW9uIHkodCl7cmV0dXJuIGoudGVzdCh0KX12YXIgdXQ9L148KFtBLVphLXpfXVx3Kik+JC87ZnVuY3Rpb24gTih0KXtyZXR1cm4gdXQudGVzdCh0KX1mdW5jdGlvbiBXKHQpe3JldHVybiB1dC5leGVjKHQpPy5bMV18fCIifWZ1bmN0aW9uIFgodCl7cmV0dXJuIGouZXhlYyh0KT8uWzFdfHwiIn12YXIgYXQ9dD0+e2lmKHkodCkpcmV0dXJuInB0ciI7aWYoTih0KSl0aHJvdyBuZXcgRXJyb3IoYGZmaTogY1Rva2VuVG9UeXBlOiBieS12YWx1ZSB0b2tlbiAiJHt0fSIgaGFzIG5vIHNjYWxhciBzbG90IHR5cGVgKTtyZXR1cm4gdH0sRD1jdC5hcmNoPT09Ing2NCI/ODo0LFI9e3U4OjEsaTg6MSx1MTY6MixpMTY6Mix1MzI6NCxpMzI6NCx1NjQ6OCxpNjQ6OCxmMzI6NCxmNjQ6OH0sTz0wO2Z1bmN0aW9uIGsodCl7aWYoeSh0KSl7bGV0IG89ai5leGVjKHQpLGk9bz8uWzFdfHwiIjtyZXR1cm4gbz8uWzJdPy5zdGFydHNXaXRoKCJAIik/YDwke2l9PnB0cmA6dH1pZihOKHQpKXJldHVybiB0O2xldCBlPXQuaW5kZXhPZigiQCIpLHI9ZT49MD90LnNsaWNlKDAsZSk6dDtpZigoZTwwfHwvXltBLVphLXpfXVx3KiQvLnRlc3QodC5zbGljZShlKzEpKSkmJnIhPT0icHRyIiYma3QuaW5jbHVkZXMocikpcmV0dXJuIHI7dGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHRva2VuOiAiK3QpfWZ1bmN0aW9uIHoodCxlLHIpe3N3aXRjaChyKXtjYXNlInU4IjpyZXR1cm4gdC5nZXRVaW50OChlKTtjYXNlImk4IjpyZXR1cm4gdC5nZXRJbnQ4KGUpO2Nhc2UidTE2IjpyZXR1cm4gdC5nZXRVaW50MTYoZSwhMCk7Y2FzZSJpMTYiOnJldHVybiB0LmdldEludDE2KGUsITApO2Nhc2UidTMyIjpyZXR1cm4gdC5nZXRVaW50MzIoZSwhMCk7Y2FzZSJpMzIiOnJldHVybiB0LmdldEludDMyKGUsITApO2Nhc2UidTY0IjpyZXR1cm4gdC5nZXRCaWdVaW50NjQoZSwhMCk7Y2FzZSJpNjQiOnJldHVybiB0LmdldEJpZ0ludDY0KGUsITApO2Nhc2UiZjMyIjpyZXR1cm4gdC5nZXRGbG9hdDMyKGUsITApO2Nhc2UiZjY0IjpyZXR1cm4gdC5nZXRGbG9hdDY0KGUsITApO2Nhc2UicHRyIjpyZXR1cm4gRD09PTg/TnVtYmVyKHQuZ2V0QmlnSW50NjQoZSwhMCkpOnQuZ2V0SW50MzIoZSwhMCl9fWZ1bmN0aW9uIFoodCxlLHtrOnIsdjpufSl7c3dpdGNoKHIpe2Nhc2UidTgiOnQuc2V0VWludDgoZSxOdW1iZXIobikpO2JyZWFrO2Nhc2UiaTgiOnQuc2V0SW50OChlLE51bWJlcihuKSk7YnJlYWs7Y2FzZSJ1MTYiOnQuc2V0VWludDE2KGUsTnVtYmVyKG4pLCEwKTticmVhaztjYXNlImkxNiI6dC5zZXRJbnQxNihlLE51bWJlcihuKSwhMCk7YnJlYWs7Y2FzZSJ1MzIiOnQuc2V0VWludDMyKGUsbj4+PjAsITApO2JyZWFrO2Nhc2UiaTMyIjp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVhaztjYXNlInU2NCI6dC5zZXRCaWdVaW50NjQoZSxuLCEwKTticmVhaztjYXNlImk2NCI6dC5zZXRCaWdJbnQ2NChlLG4sITApO2JyZWFrO2Nhc2UiZjMyIjp0LnNldEZsb2F0MzIoZSxuLCEwKTticmVhaztjYXNlImY2NCI6dC5zZXRGbG9hdDY0KGUsbiwhMCk7YnJlYWs7Y2FzZSJwdHIiOntpZihuPT1udWxsKXRocm93IG5ldyBFcnJvcigiZmZpOiBnb3QgbnVsbC91bmRlZmluZWQgZm9yIGEgcHRyIHNsb3Q7IHBhc3MgdGhlIGltcG9ydGVkIE5VTEwgY29uc3RhbnQgZm9yIGVtcHR5Iik7RD09PTg/dC5zZXRCaWdVaW50NjQoZSxCaWdJbnQuYXNVaW50Tig2NCxCaWdJbnQobikpLCEwKTp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVha319fWZ1bmN0aW9uIF8odCxlLHIpe2xldHtrOm4sdjpvfT1yO2lmKG49PT0idTgifHxuPT09Imk4Inx8bj09PSJ1MTYifHxuPT09ImkxNiIpe3Quc2V0VWludDMyKGUsTnVtYmVyKG8pPj4+MCwhMCk7cmV0dXJufVoodCxlLHIpfXZhciBoPWNsYXNzIGV4dGVuZHMgQXJyYXlCdWZmZXJ7cHRyO2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpLHRoaXMucHRyPVJ0KHRoaXMpfX07ZnVuY3Rpb24gcSh0LGUpe3JldHVybiBlW3RdfXZhciBwdD1uZXcgTWFwO2Z1bmN0aW9uIF90KHQpe2xldCBlPXB0LmdldCh0KTtpZihlIT09dm9pZCAwKXJldHVybiBlO2xldCByPSQuTG9hZExpYnJhcnkodCk7aWYoIXIpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogTG9hZExpYnJhcnkoIiR7dH0iKSBmYWlsZWRgKTtyZXR1cm4gcHQuc2V0KHQscikscn1mdW5jdGlvbiBCdCh0KXtsZXQgZT10LnNwbGl0KCIgLT4gIik7aWYoZS5sZW5ndGghPT0yKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IGludmFsaWQgc2lnbmF0dXJlICIke3R9IiAoZXhwZWN0ZWQgImFyZzEgYXJnMiAtPiByZXQiKWApO2xldCByPWVbMF0uc3BsaXQoIiAiKS5maWx0ZXIoaT0+aSE9PSIiKSxuPVtdO2ZvcihsZXQgaSBvZiByKXtsZXQgYz1rKGkpO2lmKGM9PT0idm9pZCIpdGhyb3cgbmV3IEVycm9yKCJWb2lkIGNhbiBub3QgaW4gYXJncyIpO24ucHVzaChjKX1sZXQgbz1rKGVbMV0pO2lmKE4obykpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogIiR7dH0iOiBieS12YWx1ZSBzdHJ1Y3QgYXQgdGhlIHJldHVybiBwb3NpdGlvbiAoPCR7VyhvKX0+KSBpcyBub3Qgc3VwcG9ydGVkIFx1MjAxNCBhcmd1bWVudCBwb3NpdGlvbnMgb25seTsgcGFzcyBhIHN0cnVjdCBvdXQgdGhyb3VnaCBhbiBvdXQtcGFyYW0gc2xvdCBpbnN0ZWFkICg8Tj5wdHIgKyBjYWxsZXIgYnVmZmVyKWApO3JldHVybnthcmdUb2tlbnM6bixyZXRUb2tlbjpvLHNpZzp0fX1mdW5jdGlvbiBVdCh0LGUscixuKXtsZXQgbz1CdChlKTtmb3IobGV0IGkgb2Ygby5hcmdUb2tlbnMpe2lmKCFOKGkpKWNvbnRpbnVlO2xldCBjPVcoaSkscz1xKGMscik7aWYoIXN8fHR5cGVvZiBzLmVuY29kZSE9ImZ1bmN0aW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0IChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMocikuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZih0eXBlb2Ygcy5zaXplIT0ibnVtYmVyInx8cy5zaXplPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtlfTogYnktdmFsdWUgcG9zaXRpb24gPCR7Y30+IHJlcXVpcmVzIGEgc3RydWN0IGxheW91dCB3aXRoIHNpemUgPj0gMSAoZ290ICR7cy5zaXplfTsgbm9uLXN0cnVjdCBjb2RlY3MgZXhwb3NlIG5vIHNpemUpYCl9cmV0dXJuKC4uLmkpPT56dCh0LG8saSxyLG4pfXZhciBIdD17dTg6NCxpODo0LHUxNjo0LGkxNjo0LHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4LHB0cjpEfSxmdD00O2Z1bmN0aW9uIHp0KHQse2FyZ1Rva2VuczplLHJldFRva2VuOnIsc2lnOm59LG8saSxjKXtsZXQgcz1kdC5hcmNoPT09Ing2NCIsdT0oYSxkKT0+e2lmKE4oYSkpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogZ2V0V2lkdGg6IGJ5LXZhbHVlIHRva2VuICIke2F9IiAoZGlzcGF0Y2hlZCBieSB3aWR0aE9mKWApO3JldHVybiBkPzg6eShhKT9EOkh0W2FdfSxwPWE9PntpZihOKGEpKXtpZihzKXJldHVybiA4O2xldCBkPXEoVyhhKSxpKTtpZighZCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtXKGEpfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7bGV0IG09ZC5zaXplO3JldHVybiBtJTQ9PT0wP206bSs0LW0lNH1yZXR1cm4gdShhLHMpfSx4PTA7Zm9yKGxldCBhIG9mIGUpeCs9cChhKTtzJiZlLmxlbmd0aDxmdCYmKHg9ZnQqOCk7bGV0IEY9bmV3IEFycmF5QnVmZmVyKHgpLGc9bmV3IERhdGFWaWV3KEYpLFQ9W10sRT0wO2ZvcihsZXQgYT0wO2E8ZS5sZW5ndGg7YSsrKXtsZXQgZD1lW2FdLG09ZC5lbmRzV2l0aCgiISIpLGY9b1thXTtpZih5KGQpKXtsZXQgbD1YKGQpO2lmKHR5cGVvZiBmPT0ibnVtYmVyIil7aWYobSYmZj09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtufTogYXJnIyR7YSsxfSA8JHtsfT5wdHIhIGdvdCAwIChudWxsIHBvaW50ZXIgZm9yYmlkZGVuIGhlcmU7IHRoZSB0b2tlbiBtYXJrcyB0aGlzIHBvc2l0aW9uIG5vbi1udWxsKWApO18oZyxFLHtrOiJwdHIiLHY6Zn0pfWVsc2V7aWYoZj09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtsfT5wdHIgZ290ICR7U3RyaW5nKGYpfTsgcGFzcyB0aGUgaW1wb3J0ZWQgTlVMTCBjb25zdGFudCBmb3IgYW4gZW1wdHkgcG9pbnRlcmApO2xldCBDPWlbbF07aWYoIUMpdGhyb3cgbmV3IEVycm9yKGw9PT0iIj9gZmZpLWJpbmQ6IDw+cHRyIGV4cGVjdHMgbnVtYmVyIChOVUxMIHwgUHRyKSwgZ290ICR7dHlwZW9mIGZ9OyB1c2UgPEJZVEU+cHRyIHdpdGggYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pKSwgb3IgZmZpLmJ1ZmZlclB0cihidWYpIGZvciBhbiBhZGRyZXNzYDpgZmZpLWJpbmQ6IHVua25vd24gbGF5b3V0ICI8JHtsfT5wdHIiIChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMoaSkuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZighQy5lbmNvZGUpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+cHRyIGhhcyBubyBlbmNvZGVyIChvdXQtb25seSBjb2RlYylgKTtsZXQgQT1DLmVuY29kZShmKTtULnB1c2goQSk7bGV0IFA9QS5wdHI7aWYodHlwZW9mIFAhPSJudW1iZXIiKXRocm93IG5ldyBFcnJvcigiZmZpLWJpbmQ6IGNvZGVjLmVuY29kZSBtdXN0IHJldHVybiBhIFB0ckFycmF5QnVmZmVyLCBnb3QgcGxhaW4gQXJyYXlCdWZmZXIiKTtpZihtJiZQPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiBhcmcjJHthKzF9IDwke2x9PnB0ciEgZW5jb2RlIHByb2R1Y2VkIDAgKG51bGwgcG9pbnRlciBmb3JiaWRkZW4gaGVyZSlgKTtfKGcsRSx7azoicHRyIix2OlB9KX19ZWxzZSBpZihOKGQpKXtsZXQgbD1XKGQpLEM9cShsLGkpO2lmKCFDKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7bn06IGFyZyMke2ErMX0gPCR7bH0+IGJ5LXZhbHVlIHBvc2l0aW9uIGhhcyBubyByZWdpc3RlcmVkIGxheW91dGApO2lmKGY9PW51bGwpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+IHZhbHVlIHBvc2l0aW9uIGdvdCAke1N0cmluZyhmKX07IHBhc3MgYSBzdHJ1Y3Qgb2JqZWN0ICh1c2UgPCR7bH0+cHRyIHRvIHBhc3MgYSBwb2ludGVyKWApO2xldCBBPUMuc2l6ZTtpZighc3x8QTw9OCYmKEEmQS0xKT09PTApQy5lbmNvZGUoZixGLEUpO2Vsc2V7bGV0IFA9bmV3IEFycmF5QnVmZmVyKEErMTUpLG90PWIuYnVmZmVyUHRyKFApLGl0PSgxNi1vdCUxNiklMTY7Qy5lbmNvZGUoZixQLGl0KSxULnB1c2goUCksXyhnLEUse2s6InB0ciIsdjpvdCtpdH0pfX1lbHNlIF8oZyxFLHtrOmQsdjpmfSk7RSs9cChkKX1sZXQgTD1uZXcgQXJyYXlCdWZmZXIoOCk7Yi5mZmlDYWxsKHQsRixMLHI9PT0iZjMyInx8cj09PSJmNjQiPzE6MCk7bGV0IFM9JHQoYXQociksTCk7aWYoci5lbmRzV2l0aCgiISIpJiZTPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiByZXR1cm4gJHtyfSBnb3QgMCAodGhlIHRva2VuIHByb21pc2VzIEMgbmV2ZXIgcmV0dXJucyBudWxsIGhlcmUpYCk7aWYoeShyKSYmUyE9PTApe2xldCBhPVgocik7aWYoYSE9PSIiKXtsZXQgZD1jW2FdO2lmKGQ/LmRlY29kZSlyZXR1cm4gZC5kZWNvZGUoUyl9fXJldHVybiBTfWZ1bmN0aW9uICR0KHQsZSl7aWYodCE9PSJ2b2lkIilyZXR1cm4geihuZXcgRGF0YVZpZXcoZSksMCx0KX12YXIgRz17ZW5jb2RlOnQ9PntsZXQgZT1uZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIikuZW5jb2RlKHQrIlwwIikscj1uZXcgaChlLmJ5dGVMZW5ndGgpO3JldHVybiBuZXcgVWludDhBcnJheShyKS5zZXQoZSkscn0sZGVjb2RlOnQ9PntpZih0eXBlb2YgdD09Im51bWJlciIpe2xldCBvPSIiLGk9dCxjPWk7Zm9yKDs7KXtsZXQgcz1iLnJlYWRCeXRlKGkpLHU9Yi5yZWFkQnl0ZShpKzEpO2lmKHM9PT0wJiZ1PT09MClyZXR1cm4gbztpZihvKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHN8dTw8OCksaSs9MixpLWM+MTw8MjEpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogV0NIQVIgZGVjb2RlIGV4Y2VlZGVkIDRNaUIgd2l0aG91dCBOVUwiKX19bGV0IGU9bmV3IFVpbnQ4QXJyYXkodCkscj1lLmxlbmd0aCYtMixuPSIiO2ZvcihsZXQgbz0wO288cjtvKz0yKXtsZXQgaT1lW29dfGVbbysxXTw8ODtpZihpPT09MClyZXR1cm4gbjtuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpfXJldHVybiBufSxhbGxvYzoodD0yNTYpPT5uZXcgaCh0KjIpfSxHdD17ZW5jb2RlOnQ9PntpZighKHQgaW5zdGFuY2VvZiBoKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiA8QllURT5wdHIgd2FudHMgYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pIC8gQllURS5hbGxvYyAvIHN0cnVjdC5lbmNvZGUpLCBub3QgYSBwbGFpbiBBcnJheUJ1ZmZlciIpO3JldHVybiB0fSxhbGxvYzp0PT5uZXcgaCh0KX0sbHQ9e1dDSEFSOkcsQllURTpHdH07ZnVuY3Rpb24gRXQodCxlLHIsbixvKXtsZXQgaT0kLkdldFByb2NBZGRyZXNzKF90KHQpLGUpO2lmKCFpKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IHByb2MgIiR7ZX0iIG5vdCBmb3VuZCBpbiAke3R9YCk7bGV0IGM9bz8/bjtyZXR1cm4gVXQoaSxyLHsuLi5sdCwuLi5ufSx7Li4ubHQsLi4uYz8/e319KX12YXIgZmU9bmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KHQ9PnttdC5wcmludGYoYFtmZmldIGNsb3N1cmUgbGVha2VkIChHQ2VkIHdpdGhvdXQgZGlzcG9zZSk6IHNpZz0iJXMiIHB0cj0weCV4CmAsdC5zaWcsdC5wdHIpfSk7aW1wb3J0KmFzIHh0IGZyb20iZmZpIjtmdW5jdGlvbiBCKHQsZSl7cmV0dXJuIHQrZS0xJn4oZS0xKX12YXIgaHQ9dD0+Ult0XSE9PXZvaWQgMDtmdW5jdGlvbiBRKHQpe2lmKHR5cGVvZiB0PT0ic3RyaW5nIil7bGV0IGU9L14odTh8dTE2KVxbKFxkKylcXUAodXRmLTh8dXRmLTE2bGUpJC8uZXhlYyh0KTtpZihlKXtsZXQgYz1OdW1iZXIoZVsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cmluZyBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke2N9YCk7bGV0IHM9ZVsxXT09PSJ1OCI/MToyO3JldHVybntzaXplOnMqYyxhbGlnbjpzLHR5cGU6e3RhZzoic3RyaW5nIixlbmNvZGluZzplWzNdfX19bGV0IHI9L14oW15cW1xdXSspXFsoXGQrKVxdJC8uZXhlYyh0KTtpZihyKXtsZXQgYz1OdW1iZXIoclsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFycmF5IGxlbmd0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7Y31gKTtsZXQgcz1RKHJbMV0pO2lmKHMudHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOnMuc2l6ZSpjLGFsaWduOnMuYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6cy50eXBlLGVsZW1lbnRTaXplOnMuc2l6ZX19fWxldCBuPS9eKFtBLVphLXpfXVx3Kik6KFxkKykkLy5leGVjKHQpO2lmKG4pe2xldCBjPW5bMV0scz1rKGMpO2lmKCFodChzKXx8cz09PSJmMzIifHxzPT09ImY2NCIpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB1bml0IG11c3QgYmUgYW4gaW50ZWdlciB0eXBlLCBnb3QgIiR7Y30iYCk7bGV0IHU9TnVtYmVyKG5bMl0pLHA9UltzXSx4PXAqODtpZighTnVtYmVyLmlzSW50ZWdlcih1KXx8dTwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke3V9YCk7aWYodT54KXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggJHt1fSBleGNlZWRzIHVuaXQgd2lkdGggJHt4fWApO3JldHVybntzaXplOnAsYWxpZ246cCx0eXBlOnt0YWc6ImJpdGZpZWxkIix1bml0OnMsYml0OjAsd2lkdGg6dX19fWxldCBvPWsodCk7aWYoeShvKSlyZXR1cm57c2l6ZTpELGFsaWduOkQsdHlwZTp7dGFnOiJiYXNpYyIsa2luZDoicHRyIn19O2lmKCFodChvKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHVua25vd24ga2luZCAiJHt0fSJgKTtsZXQgaT1SW29dO3JldHVybntzaXplOmksYWxpZ246aSx0eXBlOnt0YWc6ImJhc2ljIixraW5kOm99fX1pZih0JiZ0eXBlb2YgdD09Im9iamVjdCIpe2xldCBlPXQscj1lWyIjIl07aWYocj09PXZvaWQgMCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IG5lc3RlZCBvYmplY3QgdmFsdWUgcmVxdWlyZXMgYSAnIycga2V5ICgnc3RydWN0JyB8ICd1bmlvbicgfCAnYXJyYXknKSIpO2lmKHI9PT0iYXJyYXkiJiYiI3BhY2siaW4gZSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICcjcGFjaycgaXMgb25seSBhbGxvd2VkIG9uIHN0cnVjdC91bmlvbiwgZ290ICcke3J9J2ApO2lmKHI9PT0iYXJyYXkiKXtsZXQgbj1lLmxlbmd0aDtpZighTnVtYmVyLmlzSW50ZWdlcihuKXx8bjwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYXJyYXkgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtTdHJpbmcobil9YCk7bGV0IG89UShlLmVsZW1lbnQpO2lmKG8udHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOm8uc2l6ZSpuLGFsaWduOm8uYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6by50eXBlLGVsZW1lbnRTaXplOm8uc2l6ZX19fWlmKHI9PT0ic3RydWN0Inx8cj09PSJ1bmlvbiIpe2xldCBuPXd0KHQpO3JldHVybntzaXplOm4uc2l6ZSxhbGlnbjpuLm1heEVmZmVjdGl2ZUFsaWduLHR5cGU6e3RhZzpyLGZpZWxkczpuLmZpZWxkc319fXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biAnIycgZGVjbGFyYXRpb24gJHtKU09OLnN0cmluZ2lmeShTdHJpbmcocikpfWApfXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogaW52YWxpZCBtZW1iZXIgdmFsdWU6ICR7U3RyaW5nKHQpfWApfWZ1bmN0aW9uIHd0KHQpe2xldCBlPXRbIiMiXT09PSJzdHJ1Y3QiLHI9dFsiI3BhY2siXT8/OCxuPTEsbz0wLGk9W10sYz0wLHM9LTEsdT0wLHA9MCx4PSgpPT57czwwfHwoYz1CKHMrTWF0aC5jZWlsKHUvOCkscCkscz0tMSl9O2ZvcihsZXRbRixnXW9mIE9iamVjdC5lbnRyaWVzKHQpKXtpZihGLnN0YXJ0c1dpdGgoIiMiKSljb250aW51ZTtsZXQgVD0vXihbXkBdKylAKFxkKykkLy5leGVjKEYpLEU9VD9UWzFdOkYsTD1UP051bWJlcihUWzJdKTowLHtzaXplOncsYWxpZ246Uyx0eXBlOmF9PVEoZyksZD10eXBlb2YgZz09InN0cmluZyImJmcuZW5kc1dpdGgoIiEiKSxtPVM7aWYocj4wJiYobT1NYXRoLm1pbihyLG0pKSxMJiYobT1NYXRoLm1heChtLEwpKSxhLnRhZz09PSJiaXRmaWVsZCIpe2lmKEUuc3RhcnRzV2l0aCgiJCIpKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGQgbWVtYmVycyBtdXN0IGJlIG5hbWVkIik7aWYoIWUpe2kucHVzaCh7bmFtZTpFLG9mZnNldDowLHNpemU6dyx0eXBlOnsuLi5hLGJpdDowfX0pLG49TWF0aC5tYXgobixtKSxvPU1hdGgubWF4KG8sdyk7Y29udGludWV9bGV0IGw9YS53aWR0aDsoczwwfHx3IT09cHx8dStsPnAqOCkmJihzPj0wJiZ4KCkscz1CKGMsbSksdT0wLHA9dyksaS5wdXNoKHtuYW1lOkUsb2Zmc2V0OnMsc2l6ZTp3LHR5cGU6ey4uLmEsYml0OnV9fSksdSs9bCxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpO2NvbnRpbnVlfXgoKTtsZXQgZj1CKGMsbSk7aWYoIUUuc3RhcnRzV2l0aCgiJCIpKWkucHVzaCh7bmFtZTpFLG9mZnNldDpmLHNpemU6dyx0eXBlOmEsLi4uZD97bm9ubnVsbDohMH06e319KTtlbHNle2lmKGEudGFnIT09InN0cnVjdCImJmEudGFnIT09InVuaW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFub255bW91cyBtZW1iZXIgIiR7RX0iIG11c3QgYmUgYSBzdHJ1Y3QvdW5pb25gKTtmb3IobGV0IGwgb2YgYS5maWVsZHMpaS5wdXNoKHsuLi5sLG9mZnNldDpsLm9mZnNldCtmfSl9ZSYmKGM9Zit3KSxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpfXJldHVybiB4KCkse3NpemU6QihlP2M6byxuKSxtYXhFZmZlY3RpdmVBbGlnbjpuLGZpZWxkczppfX1mdW5jdGlvbiBndCh0LGUscil7bGV0IG49UltyXTtyZXR1cm4gbj09PTE/QmlnSW50KHQuZ2V0VWludDgoZSkpOm49PT0yP0JpZ0ludCh0LmdldFVpbnQxNihlLCEwKSk6bj09PTQ/QmlnSW50KHQuZ2V0VWludDMyKGUsITApKTp0LmdldEJpZ1VpbnQ2NChlLCEwKX1mdW5jdGlvbiBWdCh0LGUscixuKXtsZXQgbz1SW3JdO2lmKG89PT0xKXt0LnNldFVpbnQ4KGUsTnVtYmVyKG4mMHhmZm4pKTtyZXR1cm59aWYobz09PTIpe3Quc2V0VWludDE2KGUsTnVtYmVyKG4mMHhmZmZmbiksITApO3JldHVybn1pZihvPT09NCl7dC5zZXRVaW50MzIoZSxOdW1iZXIobiYweGZmZmZmZmZmbiksITApO3JldHVybn10LnNldEJpZ1VpbnQ2NChlLG4mMHhmZmZmZmZmZmZmZmZmZmZmbiwhMCl9ZnVuY3Rpb24gWXQodCxlLHIpe2xldCBuPUJpZ0ludChyLndpZHRoKSxvPWd0KHQsZSxyLnVuaXQpPj5CaWdJbnQoci5iaXQpJigxbjw8biktMW47cmV0dXJuIHIudW5pdFswXT09PSJpIiYmbyYxbjw8bi0xbiYmKG8tPTFuPDxuKSxyLndpZHRoPjUzP286TnVtYmVyKG8pfWZ1bmN0aW9uIHZ0KHQsZSxyLG4pe2xldCBvPUJpZ0ludChyLndpZHRoKSxpPUJpZ0ludChyLmJpdCksYz0oMW48PG8pLTFuLHM9Yzw8aSx1PWd0KHQsZSxyLnVuaXQpLHA9KHR5cGVvZiBuPT0iYmlnaW50Ij9uOkJpZ0ludChNYXRoLnRydW5jKG4pKSkmYztWdCh0LGUsci51bml0LHUmfnN8cDw8aSl9dmFyIGp0PXsidXRmLTgiOm5ldyBUZXh0RW5jb2RlcigidXRmLTgiKSwidXRmLTE2bGUiOm5ldyBUZXh0RW5jb2RlcigidXRmLTE2bGUiKX0sWHQ9eyJ1dGYtOCI6bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2lnbm9yZUJPTTohMH0pLCJ1dGYtMTZsZSI6bmV3IFRleHREZWNvZGVyKCJ1dGYtMTZsZSIse2lnbm9yZUJPTTohMH0pfTtmdW5jdGlvbiBadCh0LGUscixuKXtsZXQgbz1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKSxpPW49PT0idXRmLTE2bGUiPzI6MSxjPXI7Zm9yKGxldCBzPTA7cytpPD1yO3MrPWkpaWYob1tzXT09PTAmJihpPT09MXx8b1tzKzFdPT09MCkpe2M9czticmVha31yZXR1cm4gWHRbbl0uZGVjb2RlKG8uc3ViYXJyYXkoMCxjKSl9ZnVuY3Rpb24gcXQodCxlLHIsbixvKXtsZXQgaT1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKTtpLmZpbGwoMCk7bGV0IHM9ci0obj09PSJ1dGYtMTZsZSI/MjoxKTtpZihzPD0wKXJldHVybjtsZXQgdT1qdFtuXS5lbmNvZGUoU3RyaW5nKG8/PyIiKSk7aS5zZXQodS5zdWJhcnJheSgwLE1hdGgubWluKHUubGVuZ3RoLHMpKSl9ZnVuY3Rpb24gUXQodCxlLHIsbil7bGV0IG89bi5lbGVtZW50U2l6ZT4wP3Ivbi5lbGVtZW50U2l6ZTowLGk9W107Zm9yKGxldCBjPTA7YzxvO2MrKylpLnB1c2goVHQodCxlK2Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUpKTtyZXR1cm4gaX1mdW5jdGlvbiBLdCh0LGUscixuLG8pe2xldCBpPW4uZWxlbWVudFNpemU+MD9yL24uZWxlbWVudFNpemU6MCxjPW8/P1tdO2ZvcihsZXQgcz0wO3M8aTtzKyspRnQodCxlK3Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUsY1tzXSl9ZnVuY3Rpb24gVHQodCxlLHIsbil7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpyZXR1cm4geih0LGUsci5raW5kKTtjYXNlImJpdGZpZWxkIjpyZXR1cm4gWXQodCxlLHIpO2Nhc2Uic3RyaW5nIjpyZXR1cm4gWnQodCxlLG4sci5lbmNvZGluZyk7Y2FzZSJzdHJ1Y3QiOmNhc2UidW5pb24iOnJldHVybiBLKHQsZSxyLmZpZWxkcyk7Y2FzZSJhcnJheSI6cmV0dXJuIFF0KHQsZSxuLHIpfX1mdW5jdGlvbiBGdCh0LGUscixuLG8pe3N3aXRjaChyLnRhZyl7Y2FzZSJiYXNpYyI6Wih0LGUse2s6ci5raW5kLHY6b30pO2JyZWFrO2Nhc2UiYml0ZmllbGQiOnZ0KHQsZSxyLG8/PzApO2JyZWFrO2Nhc2Uic3RyaW5nIjpxdCh0LGUsbixyLmVuY29kaW5nLG8pO2JyZWFrO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjpTdCh0LGUsci5maWVsZHMsbz8/e30pO2JyZWFrO2Nhc2UiYXJyYXkiOkt0KHQsZSxuLHIsbyk7YnJlYWt9fWZ1bmN0aW9uIEsodCxlLHIpe2xldCBuPXt9O2ZvcihsZXQgbyBvZiByKXtsZXQgaT1UdCh0LGUrby5vZmZzZXQsby50eXBlLG8uc2l6ZSk7aWYoby5ub25udWxsJiZpPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGRlY29kZTogJyEnIGZpZWxkICIke28ubmFtZX0iIGdvdCAwIChDIGRpZCBub3QgZmlsbCBpdCwgb3IgZGVjb2RlIHdhcyBjYWxsZWQgb24gYW4gdW5maWxsZWQgc2xvdClgKTtuW28ubmFtZV09aX1yZXR1cm4gbn1mdW5jdGlvbiBTdCh0LGUscixuKXtmb3IobGV0IG8gb2YgciluW28ubmFtZV0hPT12b2lkIDAmJkZ0KHQsZStvLm9mZnNldCxvLnR5cGUsby5zaXplLG5bby5uYW1lXSl9ZnVuY3Rpb24gSnQodCl7bGV0e2ZpZWxkczplLHNpemU6cixtYXhFZmZlY3RpdmVBbGlnbjpufT13dCh0KTtyZXR1cm57ZmllbGRzOmUsc2l6ZTpyLHN0cnVjdEFsaWduOm4sZGVjb2RlOm89PksodHlwZW9mIG89PSJudW1iZXIiP25ldyBEYXRhVmlldyh4dC5yZWFkQnl0ZXMobyxyKSk6bmV3IERhdGFWaWV3KG8pLDAsZSksYWxsb2M6KG89PntpZihvIT09dm9pZCAwJiYoIU51bWJlci5pc0ludGVnZXIobyl8fG88MSkpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBhbGxvYyhuKSByZXF1aXJlcyBhbiBpbnRlZ2VyIG4gPj0gMSAoUEFCKDApIG5ldmVyIGVzY2FwZXMgXHUyMDE0IHBhc3MgTlVMTCBmb3IgYW4gZW1wdHkgcG9pbnRlciBwb3NpdGlvbikiKTtyZXR1cm4gbmV3IGgocioobz8/MSkpfSksZW5jb2RlOigobyxpLGMpPT57aWYobz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGVuY29kZSh2KSByZXF1aXJlcyBhbiBhcmd1bWVudDsgdXNlIGFsbG9jKCkgZm9yIGEgemVyb2VkIG91dC1wYXJhbSBzbG90Iik7bGV0IHM9aT8/bmV3IGgocik7cmV0dXJuIFN0KG5ldyBEYXRhVmlldyhzKSxjPz8wLGUsbyksc30pLG9mZnNldE9mOm89Pntmb3IobGV0IGkgb2YgZSlpZihpLm5hbWU9PT1vKXJldHVybiBpLm9mZnNldDt0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IG5vIGZpZWxkICIke299ImApfX19ZnVuY3Rpb24gdGUodCxlLHIpe2xldCBuPWVbIiMiXTtpZihuIT09dm9pZCAwJiZuIT09dCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICR7dH0oKSByZWNlaXZlZCBhICcke1N0cmluZyhuKX0nIGRlY2xhcmF0aW9uIChraW5kIG1pc21hdGNoIFx1MjAxNCB1c2UgJHtufSgpIGZvciBpdClgKTtsZXQgbz1lWyIjcGFjayJdO2lmKHI9PT12b2lkIDAmJm8hPT12b2lkIDApcj1vO2Vsc2UgaWYociE9PXZvaWQgMCYmbyE9PXZvaWQgMCYmciE9PW8pdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiAjcGFjayBjb25mbGljdDogb3B0cy5wYWNrPSR7cn0gdnMgZGVjbGFyYXRpb24gJHtTdHJpbmcobyl9YCk7bGV0IGk9eyIjIjp0fTtyIT09dm9pZCAwJiYoaVsiI3BhY2siXT1yKTtmb3IobGV0W2Msc11vZiBPYmplY3QuZW50cmllcyhlKSljLnN0YXJ0c1dpdGgoIiMiKXx8KGlbY109cyk7cmV0dXJuIGl9ZnVuY3Rpb24gVSh0LGUscil7bGV0IG49dHlwZW9mIHQ9PSJzdHJpbmciO3JldHVybiBKdCh0ZSgic3RydWN0IixuP2U6dCwobj9yOmUpPy5wYWNrKSl9dmFyIGVlPXsiIyI6InN0cnVjdCIsY2I6InUzMiIsbHBSZXNlcnZlZDoiPD5wdHIiLGxwRGVza3RvcDoiPD5wdHIiLGxwVGl0bGU6Ijw+cHRyIixkd1g6InUzMiIsZHdZOiJ1MzIiLGR3WFNpemU6InUzMiIsZHdZU2l6ZToidTMyIixkd1hDb3VudENoYXJzOiJ1MzIiLGR3WUNvdW50Q2hhcnM6InUzMiIsZHdGaWxsQXR0cmlidXRlOiJ1MzIiLGR3RmxhZ3M6InUzMiIsd1Nob3dXaW5kb3c6InUxNkBTaG93V2luZG93Q21kIixjYlJlc2VydmVkMjoidTE2IixscFJlc2VydmVkMjoiPD5wdHIiLGhTdGRJbnB1dDoiPEhGSUxFPnB0ciIsaFN0ZE91dHB1dDoiPEhGSUxFPnB0ciIsaFN0ZEVycm9yOiI8SEZJTEU+cHRyIn0sVj1VKCJTVEFSVFVQSU5GT1ciLGVlKSxyZT17IiMiOiJzdHJ1Y3QiLGhQcm9jZXNzOiI8SFBST0NFU1M+cHRyISIsaFRocmVhZDoiPEhUSFJFQUQ+cHRyISIsZHdQcm9jZXNzSWQ6InUzMiIsZHdUaHJlYWRJZDoidTMyIn0sSj1VKCJQUk9DRVNTX0lORk9STUFUSU9OIixyZSk7dmFyIEk9KHQsZSxyKT0+RXQoImtlcm5lbDMyLmRsbCIsdCxlLHIpLEN0PUkoIkNyZWF0ZVBpcGUiLCI8PnB0ciA8PnB0ciA8PnB0ciB1MzIgLT4gaTMyIiksdHQ9SSgiU2V0SGFuZGxlSW5mb3JtYXRpb24iLCI8SEZJTEU+cHRyISB1MzIgdTMyIC0+IGkzMiIpLGJ0PUkoIkNyZWF0ZVByb2Nlc3NXIiwiPFdDSEFSPnB0ciA8V0NIQVI+cHRyIDw+cHRyIDw+cHRyIGkzMiB1MzIgPD5wdHIgPFdDSEFSPnB0ciA8U1RBUlRVUElORk9XPnB0ciA8UFJPQ0VTU19JTkZPUk1BVElPTj5wdHIgLT4gaTMyIix7U1RBUlRVUElORk9XOlZ9KSxJdD1JKCJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwiPD5wdHIgdTMyIC0+IHUzMiIpLHl0PUkoIkdldEV4aXRDb2RlUHJvY2VzcyIsIjxIUFJPQ0VTUz5wdHIhIDxCWVRFPnB0ciAtPiBpMzIiKSxNPUkoIkNsb3NlSGFuZGxlIiwiPD5wdHIgLT4gaTMyIik7dmFyIE50PUkoIlJlYWRGaWxlIiwiPEhGSUxFPnB0ciEgPEJZVEU+cHRyIHUzMiA8QllURT5wdHIgPD5wdHIgLT4gaTMyIik7dmFyIGV0PUkoIkdldExhc3RFcnJvciIsIiAtPiB1MzIiKSxEdD1JKCJHZXRTeXN0ZW1EaXJlY3RvcnlXIiwiPEJZVEU+cHRyIHUzMiAtPiB1MzIiKTt2YXIgbmU9dD0+e3RyeXtsZXQgZT1MdC5vcGVuKCJkaWFnLmxvZyIsImEiKTtlJiYoZS5wdXRzKGAke0RhdGUubm93KCl9ICR7dH0KYCksZS5jbG9zZSgpKX1jYXRjaHt9fSxydD0xLG9lPTI1NixpZT00Mjk0OTY3Mjk1LEg9T3QuV29ya2VyLnBhcmVudCxBdD0iQzpcXFdpbmRvd3NcXFN5c3RlbTMyIjt0cnl7bGV0IHQ9Ry5hbGxvYygyNTYpLHI9RHQodCwyNTYpPjA/Ry5kZWNvZGUodCk6IiI7ciYmKEF0PXIpfWNhdGNoKHQpe25lKCJTWVMtRElSLUZBSUw6ICIrU3RyaW5nKHQpKX12YXIgbnQ9VSgiUElQRV9IQU5ETEVTIix7aFJlYWQ6IjxIRklMRT5wdHIhIixoV3JpdGU6IjxIRklMRT5wdHIhIn0pO2Z1bmN0aW9uIHNlKHQsZSl7bGV0IHI9bnQuYWxsb2MoKTtpZighQ3Qoci5wdHIsci5wdHIrbnQub2Zmc2V0T2YoImhXcml0ZSIpLE8sMCkpdGhyb3cgbmV3IEVycm9yKCJDcmVhdGVQaXBlIGVycj0iK2V0KCkpO2xldHtoUmVhZDpuLGhXcml0ZTpvfT1udC5kZWNvZGUocik7dHQobyxydCxydCksdHQobixydCwwKTtsZXQgaT1KLmFsbG9jKCksYz1gJHtBdH1cXGNtZC5leGUgL3UgL2MgJHtlfWA7aWYoIWJ0KE8sYyxPLE8sMSwwLE8sTyx7Y2I6Vi5zaXplLGR3RmxhZ3M6b2UsaFN0ZE91dHB1dDpvLGhTdGRFcnJvcjpvfSxpLnB0cikpdGhyb3cgTShuKSxNKG8pLG5ldyBFcnJvcigiQ3JlYXRlUHJvY2Vzc1cgZXJyPSIrZXQoKSsiIGNtZD0iK2MpO2xldHtoUHJvY2VzczpzLGhUaHJlYWQ6dSxkd1Byb2Nlc3NJZDpwfT1KLmRlY29kZShpKTtNKHUpLE0obyksSC5wb3N0TWVzc2FnZSh7dHlwZToiaW5mbyIsaWQ6dCxwaWQ6cH0pO2xldCB4PW5ldyBoKDQwOTYpLEY9bmV3IFVpbnQ4QXJyYXkoeCksZz1uZXcgaCg0KSxUPW5ldyBVaW50MzJBcnJheShnKTtmb3IoO1RbMF09MCwhIU50KG4seCw0MDk2LGcsTyk7KXtsZXQgUz1UWzBdO2lmKFM9PT0wKWJyZWFrO0gucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6Ri5zbGljZSgwLFMpfSl9SXQocyxpZSk7bGV0IEU9bmV3IGgoNCksTD1uZXcgSW50MzJBcnJheShFKTt5dChzLEUpO2xldCB3PUxbMF07cmV0dXJuIE0obiksTShzKSx3fUgub25tZXNzYWdlPXQ9PntsZXQgZT10LmRhdGE7aWYoZS50eXBlPT09InJ1biImJnR5cGVvZiBlLmNtZD09InN0cmluZyIpe2xldCByPS0xLG49bnVsbDt0cnl7cj1zZShlLmlkLGUuY21kKX1jYXRjaChvKXtuPVN0cmluZyhvKX1ILnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOmUuaWQsY29kZTpyLGVycm9yOm59KX1ILm9ubWVzc2FnZT1udWxsfTsK");
22294
+ const worker = new os7.Worker("data:text/javascript;base64,aW1wb3J0KmFzIE90IGZyb20ib3MiO2ltcG9ydCphcyBQdCBmcm9tInN0ZCI7aW1wb3J0KmFzIEMgZnJvbSJmZmkiO2ltcG9ydCphcyBkdCBmcm9tIm9zIjtpbXBvcnQqYXMgbXQgZnJvbSJzdGQiO2ltcG9ydCphcyAkIGZyb20id2luIjt2YXIgQXQ9eyJ1dGYtOCI6InV0Zi04Iix1dGY4OiJ1dGYtOCIsInVuaWNvZGUtMS0xLXV0Zi04IjoidXRmLTgiLCJ1dGYtMTYiOiJ1dGYtMTZsZSIsInV0Zi0xNmxlIjoidXRmLTE2bGUiLCJ1dGYtMTZiZSI6InV0Zi0xNmJlIn07ZnVuY3Rpb24gc3QodCl7aWYoIXQpcmV0dXJuInV0Zi04IjtsZXQgZT1BdFt0LnRyaW0oKS50b0xvd2VyQ2FzZSgpXTtpZihlKXJldHVybiBlO3Rocm93IG5ldyBSYW5nZUVycm9yKGBUaGUgZW5jb2RpbmcgbGFiZWwgIiR7dH0iIGlzIG5vdCBzdXBwb3J0ZWRgKX1mdW5jdGlvbiBNdCh0LGUpe2xldCByPSIiO2ZvcihsZXQgbj0wO248dC5sZW5ndGg7KXtsZXQgbz10W24rK107aWYobzwxMjgpe3IrPVN0cmluZy5mcm9tQ2hhckNvZGUobyk7Y29udGludWV9aWYobzwxOTIpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCBjb250aW51YXRpb24gYnl0ZSIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1sZXQgaSxjO2lmKG88MjI0KXtpZihuPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbisrXTtpZigocyYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShvJjMxKTw8NnxzJjYzLGM9MTI4fWVsc2UgaWYobzwyNDApe2lmKG4rMT49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W24rK10sdT10W24rK107aWYoKHMmMTkyKSE9PTEyOHx8KHUmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obyYxNSk8PDEyfChzJjYzKTw8Nnx1JjYzLGM9MjA0OH1lbHNlIGlmKG88MjQ4KXtpZihuKzI+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtuKytdLHU9dFtuKytdLHA9dFtuKytdO2lmKChzJjE5MikhPT0xMjh8fCh1JjE5MikhPT0xMjh8fChwJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG8mNyk8PDE4fChzJjYzKTw8MTJ8KHUmNjMpPDw2fHAmNjMsYz02NTUzNn1lbHNle3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBzdGFydCIpfSkoKToiXHVGRkZEIjtjb250aW51ZX1pZihpPGN8fGk+PTU1Mjk2JiZpPD01NzM0M3x8aT4xMTE0MTExKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImludmFsaWQgdXRmLTggY29kZXBvaW50Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWk8PTY1NTM1P3IrPVN0cmluZy5mcm9tQ2hhckNvZGUoaSk6KGktPTY1NTM2LHIrPVN0cmluZy5mcm9tQ2hhckNvZGUoNTUyOTZ8aT4+MTAsNTYzMjB8aSYxMDIzKSl9cmV0dXJuIHJ9ZnVuY3Rpb24gV3QodCxlLHIpe2xldCBuPW5ldyBEYXRhVmlldyh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQsdC5ieXRlTGVuZ3RoKSxvPSIiO2ZvcihsZXQgaT0wO2krMTx0Lmxlbmd0aDtpKz0yKXtsZXQgYz1uLmdldFVpbnQxNihpLGUpO2lmKGM+PTU1Mjk2JiZjPD01NjMxOSl7aWYoaSs9MixpKzE+PXQubGVuZ3RoKXtvKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInRydW5jYXRlZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz1uLmdldFVpbnQxNihpLGUpO3M+PTU2MzIwJiZzPD01NzM0Mz9vKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGMscyk6KG8rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCBzdXJyb2dhdGUgcGFpciIpfSkoKToiXHVGRkZEIixpLT0yKX1lbHNlIGM+PTU2MzIwJiZjPD01NzM0Mz9vKz1yPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoInVuZXhwZWN0ZWQgdHJhaWxpbmcgc3Vycm9nYXRlIil9KSgpOiJcdUZGRkQiOm8rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyl9cmV0dXJuIG99dmFyIFY9Y2xhc3N7X2VuY29kaW5nO19mYXRhbDtfaWdub3JlQk9NO2NvbnN0cnVjdG9yKGUscil7dGhpcy5fZW5jb2Rpbmc9c3QoZSksdGhpcy5fZmF0YWw9cj8uZmF0YWw/PyExLHRoaXMuX2lnbm9yZUJPTT1yPy5pZ25vcmVCT00/PyExfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31nZXQgZmF0YWwoKXtyZXR1cm4gdGhpcy5fZmF0YWx9Z2V0IGlnbm9yZUJPTSgpe3JldHVybiB0aGlzLl9pZ25vcmVCT019ZGVjb2RlKGUpe2lmKCFlKXJldHVybiIiO2xldCByPWUgaW5zdGFuY2VvZiBVaW50OEFycmF5P2U6ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyP25ldyBVaW50OEFycmF5KGUpOm5ldyBVaW50OEFycmF5KGUuYnVmZmVyLGUuYnl0ZU9mZnNldCxlLmJ5dGVMZW5ndGgpO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04IilyZXR1cm4gTXQocix0aGlzLl9mYXRhbCk7bGV0IG49dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG89MDtpZihyLmxlbmd0aD49MiYmIXRoaXMuX2lnbm9yZUJPTSl7bGV0IGk9bj9yWzBdOnJbMV0scz0obj9yWzFdOnJbMF0pPDw4fGk7KHM9PT02NTI3OXx8cz09PTY1NTM0KSYmKG89Mil9cmV0dXJuIFd0KHIuc2xpY2Uobyksbix0aGlzLl9mYXRhbCl9fSx2PWNsYXNze19lbmNvZGluZztjb25zdHJ1Y3RvcihlKXt0aGlzLl9lbmNvZGluZz1zdChlKX1nZXQgZW5jb2RpbmcoKXtyZXR1cm4gdGhpcy5fZW5jb2Rpbmd9ZW5jb2RlKGUpe2lmKCFlKXJldHVybiBuZXcgVWludDhBcnJheSgwKTtpZih0aGlzLl9lbmNvZGluZz09PSJ1dGYtOCIpe2xldCBpPVtdO2ZvcihsZXQgYz0wO2M8ZS5sZW5ndGg7YysrKXtsZXQgcz1lLmNoYXJDb2RlQXQoYyk7aWYoczwxMjgpaS5wdXNoKHMpO2Vsc2UgaWYoczwyMDQ4KWkucHVzaCgxOTJ8cz4+NiwxMjh8cyY2Myk7ZWxzZSBpZihzPDU1Mjk2fHxzPj01NzM0NClpLnB1c2goMjI0fHM+PjEyLDEyOHxzPj42JjYzLDEyOHxzJjYzKTtlbHNle2MrKztsZXQgdT1lLmNoYXJDb2RlQXQoYyk7cz02NTUzNisoKHMmMTAyMyk8PDEwKXx1JjEwMjMsaS5wdXNoKDI0MHxzPj4xOCwxMjh8cz4+MTImNjMsMTI4fHM+PjYmNjMsMTI4fHMmNjMpfX1yZXR1cm4gbmV3IFVpbnQ4QXJyYXkoaSl9bGV0IHI9dGhpcy5fZW5jb2Rpbmc9PT0idXRmLTE2bGUiLG49bmV3IEFycmF5QnVmZmVyKGUubGVuZ3RoKjIpLG89bmV3IERhdGFWaWV3KG4pO2ZvcihsZXQgaT0wO2k8ZS5sZW5ndGg7aSsrKW8uc2V0VWludDE2KGkqMixlLmNoYXJDb2RlQXQoaSkscik7cmV0dXJuIG5ldyBVaW50OEFycmF5KG4pfX07dHlwZW9mIGdsb2JhbFRoaXMuVGV4dERlY29kZXI+InUiJiYoZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj1WKTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RW5jb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHRFbmNvZGVyPXYpO2ltcG9ydHtidWZmZXJQdHIgYXMgUnR9ZnJvbSJmZmkiO2ltcG9ydCphcyBjdCBmcm9tIm9zIjt2YXIga3Q9WyJ2b2lkIiwidTgiLCJpOCIsInUxNiIsImkxNiIsInUzMiIsImkzMiIsInU2NCIsImk2NCIsImYzMiIsImY2NCIsInB0ciJdLGo9L148KFtBLVphLXpfXVx3KnwpPnB0cighfEBbQS1aYS16X11cdyopPyQvO2Z1bmN0aW9uIE4odCl7cmV0dXJuIGoudGVzdCh0KX12YXIgdXQ9L148KFtBLVphLXpfXVx3Kik+JC87ZnVuY3Rpb24geSh0KXtyZXR1cm4gdXQudGVzdCh0KX1mdW5jdGlvbiBXKHQpe3JldHVybiB1dC5leGVjKHQpPy5bMV18fCIifWZ1bmN0aW9uIFgodCl7cmV0dXJuIGouZXhlYyh0KT8uWzFdfHwiIn12YXIgYXQ9dD0+e2lmKE4odCkpcmV0dXJuInB0ciI7aWYoeSh0KSl0aHJvdyBuZXcgRXJyb3IoYGZmaTogY1Rva2VuVG9UeXBlOiBieS12YWx1ZSB0b2tlbiAiJHt0fSIgaGFzIG5vIHNjYWxhciBzbG90IHR5cGVgKTtyZXR1cm4gdH0sRD1jdC5hcmNoPT09Ing2NCI/ODo0LFI9e3U4OjEsaTg6MSx1MTY6MixpMTY6Mix1MzI6NCxpMzI6NCx1NjQ6OCxpNjQ6OCxmMzI6NCxmNjQ6OH0sTz0wO2Z1bmN0aW9uIGsodCl7aWYoTih0KSl7bGV0IG89ai5leGVjKHQpLGk9bz8uWzFdfHwiIjtyZXR1cm4gbz8uWzJdPy5zdGFydHNXaXRoKCJAIik/YDwke2l9PnB0cmA6dH1pZih5KHQpKXJldHVybiB0O2xldCBlPXQuaW5kZXhPZigiQCIpLHI9ZT49MD90LnNsaWNlKDAsZSk6dDtpZigoZTwwfHwvXltBLVphLXpfXVx3KiQvLnRlc3QodC5zbGljZShlKzEpKSkmJnIhPT0icHRyIiYma3QuaW5jbHVkZXMocikpcmV0dXJuIHI7dGhyb3cgbmV3IEVycm9yKCJVbmtub3duIHRva2VuOiAiK3QpfWZ1bmN0aW9uIHoodCxlLHIpe3N3aXRjaChyKXtjYXNlInU4IjpyZXR1cm4gdC5nZXRVaW50OChlKTtjYXNlImk4IjpyZXR1cm4gdC5nZXRJbnQ4KGUpO2Nhc2UidTE2IjpyZXR1cm4gdC5nZXRVaW50MTYoZSwhMCk7Y2FzZSJpMTYiOnJldHVybiB0LmdldEludDE2KGUsITApO2Nhc2UidTMyIjpyZXR1cm4gdC5nZXRVaW50MzIoZSwhMCk7Y2FzZSJpMzIiOnJldHVybiB0LmdldEludDMyKGUsITApO2Nhc2UidTY0IjpyZXR1cm4gdC5nZXRCaWdVaW50NjQoZSwhMCk7Y2FzZSJpNjQiOnJldHVybiB0LmdldEJpZ0ludDY0KGUsITApO2Nhc2UiZjMyIjpyZXR1cm4gdC5nZXRGbG9hdDMyKGUsITApO2Nhc2UiZjY0IjpyZXR1cm4gdC5nZXRGbG9hdDY0KGUsITApO2Nhc2UicHRyIjpyZXR1cm4gRD09PTg/TnVtYmVyKHQuZ2V0QmlnSW50NjQoZSwhMCkpOnQuZ2V0SW50MzIoZSwhMCl9fWZ1bmN0aW9uIFoodCxlLHtrOnIsdjpufSl7c3dpdGNoKHIpe2Nhc2UidTgiOnQuc2V0VWludDgoZSxOdW1iZXIobikpO2JyZWFrO2Nhc2UiaTgiOnQuc2V0SW50OChlLE51bWJlcihuKSk7YnJlYWs7Y2FzZSJ1MTYiOnQuc2V0VWludDE2KGUsTnVtYmVyKG4pLCEwKTticmVhaztjYXNlImkxNiI6dC5zZXRJbnQxNihlLE51bWJlcihuKSwhMCk7YnJlYWs7Y2FzZSJ1MzIiOnQuc2V0VWludDMyKGUsbj4+PjAsITApO2JyZWFrO2Nhc2UiaTMyIjp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVhaztjYXNlInU2NCI6dC5zZXRCaWdVaW50NjQoZSxuLCEwKTticmVhaztjYXNlImk2NCI6dC5zZXRCaWdJbnQ2NChlLG4sITApO2JyZWFrO2Nhc2UiZjMyIjp0LnNldEZsb2F0MzIoZSxuLCEwKTticmVhaztjYXNlImY2NCI6dC5zZXRGbG9hdDY0KGUsbiwhMCk7YnJlYWs7Y2FzZSJwdHIiOntpZihuPT1udWxsKXRocm93IG5ldyBFcnJvcigiZmZpOiBnb3QgbnVsbC91bmRlZmluZWQgZm9yIGEgcHRyIHNsb3Q7IHBhc3MgdGhlIGltcG9ydGVkIE5VTEwgY29uc3RhbnQgZm9yIGVtcHR5Iik7RD09PTg/dC5zZXRCaWdVaW50NjQoZSxCaWdJbnQuYXNVaW50Tig2NCxCaWdJbnQobikpLCEwKTp0LnNldFVpbnQzMihlLG4+Pj4wLCEwKTticmVha319fWZ1bmN0aW9uIF8odCxlLHIpe2xldHtrOm4sdjpvfT1yO2lmKG49PT0idTgifHxuPT09Imk4Inx8bj09PSJ1MTYifHxuPT09ImkxNiIpe3Quc2V0VWludDMyKGUsTnVtYmVyKG8pPj4+MCwhMCk7cmV0dXJufVoodCxlLHIpfXZhciB4PWNsYXNzIGV4dGVuZHMgQXJyYXlCdWZmZXJ7cHRyO2NvbnN0cnVjdG9yKGUpe3N1cGVyKGUpLHRoaXMucHRyPVJ0KHRoaXMpfX07ZnVuY3Rpb24gcSh0LGUpe3JldHVybiBlW3RdfXZhciBwdD1uZXcgTWFwO2Z1bmN0aW9uIF90KHQpe2xldCBlPXB0LmdldCh0KTtpZihlIT09dm9pZCAwKXJldHVybiBlO2xldCByPSQuTG9hZExpYnJhcnkodCk7aWYoIXIpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogTG9hZExpYnJhcnkoIiR7dH0iKSBmYWlsZWRgKTtyZXR1cm4gcHQuc2V0KHQscikscn1mdW5jdGlvbiBVdCh0KXtsZXQgZT10LnNwbGl0KCIgLT4gIik7aWYoZS5sZW5ndGghPT0yKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IGludmFsaWQgc2lnbmF0dXJlICIke3R9IiAoZXhwZWN0ZWQgImFyZzEgYXJnMiAtPiByZXQiKWApO2xldCByPWVbMF0uc3BsaXQoIiAiKS5maWx0ZXIoaT0+aSE9PSIiKSxuPVtdO2ZvcihsZXQgaSBvZiByKXtsZXQgYz1rKGkpO2lmKGM9PT0idm9pZCIpdGhyb3cgbmV3IEVycm9yKCJWb2lkIGNhbiBub3QgaW4gYXJncyIpO24ucHVzaChjKX1sZXQgbz1rKGVbMV0pO2lmKHkobykpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogIiR7dH0iOiBieS12YWx1ZSBzdHJ1Y3QgYXQgdGhlIHJldHVybiBwb3NpdGlvbiAoPCR7VyhvKX0+KSBpcyBub3Qgc3VwcG9ydGVkIFx1MjAxNCBhcmd1bWVudCBwb3NpdGlvbnMgb25seTsgcGFzcyBhIHN0cnVjdCBvdXQgdGhyb3VnaCBhbiBvdXQtcGFyYW0gc2xvdCBpbnN0ZWFkICg8Tj5wdHIgKyBjYWxsZXIgYnVmZmVyKWApO3JldHVybnthcmdUb2tlbnM6bixyZXRUb2tlbjpvLHNpZzp0fX1mdW5jdGlvbiBCdCh0LGUscixuKXtsZXQgbz1VdChlKTtmb3IobGV0IGkgb2Ygby5hcmdUb2tlbnMpe2lmKCF5KGkpKWNvbnRpbnVlO2xldCBjPVcoaSkscz1xKGMscik7aWYoIXN8fHR5cGVvZiBzLmVuY29kZSE9ImZ1bmN0aW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0IChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMocikuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZih0eXBlb2Ygcy5zaXplIT0ibnVtYmVyInx8cy5zaXplPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtlfTogYnktdmFsdWUgcG9zaXRpb24gPCR7Y30+IHJlcXVpcmVzIGEgc3RydWN0IGxheW91dCB3aXRoIHNpemUgPj0gMSAoZ290ICR7cy5zaXplfTsgbm9uLXN0cnVjdCBjb2RlY3MgZXhwb3NlIG5vIHNpemUpYCl9cmV0dXJuKC4uLmkpPT56dCh0LG8saSxyLG4pfXZhciBIdD17dTg6NCxpODo0LHUxNjo0LGkxNjo0LHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4LHB0cjpEfSxmdD00O2Z1bmN0aW9uIHp0KHQse2FyZ1Rva2VuczplLHJldFRva2VuOnIsc2lnOm59LG8saSxjKXtsZXQgcz1kdC5hcmNoPT09Ing2NCIsdT0oYSxkKT0+e2lmKHkoYSkpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogZ2V0V2lkdGg6IGJ5LXZhbHVlIHRva2VuICIke2F9IiAoZGlzcGF0Y2hlZCBieSB3aWR0aE9mKWApO3JldHVybiBkPzg6TihhKT9EOkh0W2FdfSxwPWE9PntpZih5KGEpKXtpZihzKXJldHVybiA4O2xldCBkPXEoVyhhKSxpKTtpZighZCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtXKGEpfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7bGV0IG09ZC5zaXplO3JldHVybiBtJTQ9PT0wP206bSs0LW0lNH1yZXR1cm4gdShhLHMpfSxoPTA7Zm9yKGxldCBhIG9mIGUpaCs9cChhKTtzJiZlLmxlbmd0aDxmdCYmKGg9ZnQqOCk7bGV0IEY9bmV3IEFycmF5QnVmZmVyKGgpLGc9bmV3IERhdGFWaWV3KEYpLFQ9W10sRT0wO2ZvcihsZXQgYT0wO2E8ZS5sZW5ndGg7YSsrKXtsZXQgZD1lW2FdLG09ZC5lbmRzV2l0aCgiISIpLGY9b1thXTtpZihOKGQpKXtsZXQgbD1YKGQpO2lmKHR5cGVvZiBmPT0ibnVtYmVyIil7aWYobSYmZj09PTApdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtufTogYXJnIyR7YSsxfSA8JHtsfT5wdHIhIGdvdCAwIChudWxsIHBvaW50ZXIgZm9yYmlkZGVuIGhlcmU7IHRoZSB0b2tlbiBtYXJrcyB0aGlzIHBvc2l0aW9uIG5vbi1udWxsKWApO18oZyxFLHtrOiJwdHIiLHY6Zn0pfWVsc2V7aWYoZj09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtsfT5wdHIgZ290ICR7U3RyaW5nKGYpfTsgcGFzcyB0aGUgaW1wb3J0ZWQgTlVMTCBjb25zdGFudCBmb3IgYW4gZW1wdHkgcG9pbnRlcmApO2xldCBJPWlbbF07aWYoIUkpdGhyb3cgbmV3IEVycm9yKGw9PT0iIj9gZmZpLWJpbmQ6IDw+cHRyIGV4cGVjdHMgbnVtYmVyIChOVUxMIHwgUHRyKSwgZ290ICR7dHlwZW9mIGZ9OyB1c2UgPEJZVEU+cHRyIHdpdGggYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pKSwgb3IgZmZpLmJ1ZmZlclB0cihidWYpIGZvciBhbiBhZGRyZXNzYDpgZmZpLWJpbmQ6IHVua25vd24gbGF5b3V0ICI8JHtsfT5wdHIiIChhdmFpbGFibGU6ICR7T2JqZWN0LmtleXMoaSkuam9pbigiLCAiKXx8Im5vbmUifSlgKTtpZighSS5lbmNvZGUpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+cHRyIGhhcyBubyBlbmNvZGVyIChvdXQtb25seSBjb2RlYylgKTtsZXQgTD1JLmVuY29kZShmKTtULnB1c2goTCk7bGV0IEE9TC5wdHI7aWYodHlwZW9mIEEhPSJudW1iZXIiKXRocm93IG5ldyBFcnJvcigiZmZpLWJpbmQ6IGNvZGVjLmVuY29kZSBtdXN0IHJldHVybiBhIFB0ckFycmF5QnVmZmVyLCBnb3QgcGxhaW4gQXJyYXlCdWZmZXIiKTtpZihtJiZBPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiBhcmcjJHthKzF9IDwke2x9PnB0ciEgZW5jb2RlIHByb2R1Y2VkIDAgKG51bGwgcG9pbnRlciBmb3JiaWRkZW4gaGVyZSlgKTtfKGcsRSx7azoicHRyIix2OkF9KX19ZWxzZSBpZih5KGQpKXtsZXQgbD1XKGQpLEk9cShsLGkpO2lmKCFJKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7bn06IGFyZyMke2ErMX0gPCR7bH0+IGJ5LXZhbHVlIHBvc2l0aW9uIGhhcyBubyByZWdpc3RlcmVkIGxheW91dGApO2lmKGY9PW51bGwpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogPCR7bH0+IHZhbHVlIHBvc2l0aW9uIGdvdCAke1N0cmluZyhmKX07IHBhc3MgYSBzdHJ1Y3Qgb2JqZWN0ICh1c2UgPCR7bH0+cHRyIHRvIHBhc3MgYSBwb2ludGVyKWApO2xldCBMPUkuc2l6ZTtpZighc3x8TDw9OCYmKEwmTC0xKT09PTApSS5lbmNvZGUoZixGLEUpO2Vsc2V7bGV0IEE9bmV3IEFycmF5QnVmZmVyKEwrMTUpLG90PUMuYnVmZmVyUHRyKEEpLGl0PSgxNi1vdCUxNiklMTY7SS5lbmNvZGUoZixBLGl0KSxULnB1c2goQSksXyhnLEUse2s6InB0ciIsdjpvdCtpdH0pfX1lbHNlIF8oZyxFLHtrOmQsdjpmfSk7RSs9cChkKX1sZXQgUD1uZXcgQXJyYXlCdWZmZXIoOCk7Qy5mZmlDYWxsKHQsRixQLHI9PT0iZjMyInx8cj09PSJmNjQiPzE6MCk7bGV0IFM9JHQoYXQociksUCk7aWYoci5lbmRzV2l0aCgiISIpJiZTPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiByZXR1cm4gJHtyfSBnb3QgMCAodGhlIHRva2VuIHByb21pc2VzIEMgbmV2ZXIgcmV0dXJucyBudWxsIGhlcmUpYCk7aWYoTihyKSYmUyE9PTApe2xldCBhPVgocik7aWYoYSE9PSIiKXtsZXQgZD1jW2FdO2lmKGQ/LmRlY29kZSlyZXR1cm4gZC5kZWNvZGUoUyl9fXJldHVybiBTfWZ1bmN0aW9uICR0KHQsZSl7aWYodCE9PSJ2b2lkIilyZXR1cm4geihuZXcgRGF0YVZpZXcoZSksMCx0KX12YXIgRz17ZW5jb2RlOnQ9PntsZXQgZT1uZXcgVGV4dEVuY29kZXIoInV0Zi0xNmxlIikuZW5jb2RlKHQrIlwwIikscj1uZXcgeChlLmJ5dGVMZW5ndGgpO3JldHVybiBuZXcgVWludDhBcnJheShyKS5zZXQoZSkscn0sZGVjb2RlOnQ9PntpZih0eXBlb2YgdD09Im51bWJlciIpe2xldCBvPSIiLGk9dCxjPWk7Zm9yKDs7KXtsZXQgcz1DLnJlYWRCeXRlKGkpLHU9Qy5yZWFkQnl0ZShpKzEpO2lmKHM9PT0wJiZ1PT09MClyZXR1cm4gbztpZihvKz1TdHJpbmcuZnJvbUNoYXJDb2RlKHN8dTw8OCksaSs9MixpLWM+MTw8MjEpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogV0NIQVIgZGVjb2RlIGV4Y2VlZGVkIDRNaUIgd2l0aG91dCBOVUwiKX19bGV0IGU9bmV3IFVpbnQ4QXJyYXkodCkscj1lLmxlbmd0aCYtMixuPSIiO2ZvcihsZXQgbz0wO288cjtvKz0yKXtsZXQgaT1lW29dfGVbbysxXTw8ODtpZihpPT09MClyZXR1cm4gbjtuKz1TdHJpbmcuZnJvbUNoYXJDb2RlKGkpfXJldHVybiBufSxhbGxvYzoodD0yNTYpPT5uZXcgeCh0KjIpfSxHdD17ZW5jb2RlOnQ9PntpZighKHQgaW5zdGFuY2VvZiB4KSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiA8QllURT5wdHIgd2FudHMgYSBQdHJBcnJheUJ1ZmZlciAobmV3IFB0ckFycmF5QnVmZmVyKG4pIC8gQllURS5hbGxvYyAvIHN0cnVjdC5lbmNvZGUpLCBub3QgYSBwbGFpbiBBcnJheUJ1ZmZlciIpO3JldHVybiB0fSxhbGxvYzp0PT5uZXcgeCh0KX0sbHQ9e1dDSEFSOkcsQllURTpHdH07ZnVuY3Rpb24gRXQodCxlLHIsbixvKXtsZXQgaT0kLkdldFByb2NBZGRyZXNzKF90KHQpLGUpO2lmKCFpKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IHByb2MgIiR7ZX0iIG5vdCBmb3VuZCBpbiAke3R9YCk7bGV0IGM9bz8/bjtyZXR1cm4gQnQoaSxyLHsuLi5sdCwuLi5ufSx7Li4ubHQsLi4uYz8/e319KX12YXIgZmU9bmV3IEZpbmFsaXphdGlvblJlZ2lzdHJ5KHQ9PnttdC5wcmludGYoYFtmZmldIGNsb3N1cmUgbGVha2VkIChHQ2VkIHdpdGhvdXQgZGlzcG9zZSk6IHNpZz0iJXMiIHB0cj0weCV4CmAsdC5zaWcsdC5wdHIpfSk7aW1wb3J0KmFzIGh0IGZyb20iZmZpIjtmdW5jdGlvbiBVKHQsZSl7cmV0dXJuIHQrZS0xJn4oZS0xKX12YXIgeHQ9dD0+Ult0XSE9PXZvaWQgMDtmdW5jdGlvbiBLKHQpe2lmKHR5cGVvZiB0PT0ic3RyaW5nIil7bGV0IGU9L14odTh8dTE2KVxbKFxkKylcXUAodXRmLTh8dXRmLTE2bGUpJC8uZXhlYyh0KTtpZihlKXtsZXQgYz1OdW1iZXIoZVsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHN0cmluZyBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke2N9YCk7bGV0IHM9ZVsxXT09PSJ1OCI/MToyO3JldHVybntzaXplOnMqYyxhbGlnbjpzLHR5cGU6e3RhZzoic3RyaW5nIixlbmNvZGluZzplWzNdfX19bGV0IHI9L14oW15cW1xdXSspXFsoXGQrKVxdJC8uZXhlYyh0KTtpZihyKXtsZXQgYz1OdW1iZXIoclsyXSk7aWYoIU51bWJlci5pc0ludGVnZXIoYyl8fGM8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFycmF5IGxlbmd0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7Y31gKTtsZXQgcz1LKHJbMV0pO2lmKHMudHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOnMuc2l6ZSpjLGFsaWduOnMuYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6cy50eXBlLGVsZW1lbnRTaXplOnMuc2l6ZX19fWxldCBuPS9eKFtBLVphLXpfXVx3Kik6KFxkKykkLy5leGVjKHQpO2lmKG4pe2xldCBjPW5bMV0scz1rKGMpO2lmKCF4dChzKXx8cz09PSJmMzIifHxzPT09ImY2NCIpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB1bml0IG11c3QgYmUgYW4gaW50ZWdlciB0eXBlLCBnb3QgIiR7Y30iYCk7bGV0IHU9TnVtYmVyKG5bMl0pLHA9UltzXSxoPXAqODtpZighTnVtYmVyLmlzSW50ZWdlcih1KXx8dTwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke3V9YCk7aWYodT5oKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYml0ZmllbGQgd2lkdGggJHt1fSBleGNlZWRzIHVuaXQgd2lkdGggJHtofWApO3JldHVybntzaXplOnAsYWxpZ246cCx0eXBlOnt0YWc6ImJpdGZpZWxkIix1bml0OnMsYml0OjAsd2lkdGg6dX19fWxldCBvPWsodCk7aWYoTihvKSlyZXR1cm57c2l6ZTpELGFsaWduOkQsdHlwZTp7dGFnOiJiYXNpYyIsa2luZDoicHRyIn19O2lmKCF4dChvKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IHVua25vd24ga2luZCAiJHt0fSJgKTtsZXQgaT1SW29dO3JldHVybntzaXplOmksYWxpZ246aSx0eXBlOnt0YWc6ImJhc2ljIixraW5kOm99fX1pZih0JiZ0eXBlb2YgdD09Im9iamVjdCIpe2xldCBlPXQscj1lWyIjIl07aWYocj09PXZvaWQgMCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IG5lc3RlZCBvYmplY3QgdmFsdWUgcmVxdWlyZXMgYSAnIycga2V5ICgnc3RydWN0JyB8ICd1bmlvbicgfCAnYXJyYXknKSIpO2lmKHI9PT0iYXJyYXkiJiYiI3BhY2siaW4gZSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICcjcGFjaycgaXMgb25seSBhbGxvd2VkIG9uIHN0cnVjdC91bmlvbiwgZ290ICcke3J9J2ApO2lmKHI9PT0iYXJyYXkiKXtsZXQgbj1lLmxlbmd0aDtpZighTnVtYmVyLmlzSW50ZWdlcihuKXx8bjwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYXJyYXkgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtTdHJpbmcobil9YCk7bGV0IG89SyhlLmVsZW1lbnQpO2lmKG8udHlwZS50YWc9PT0iYml0ZmllbGQiKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGRzIGNhbm5vdCBiZSBhcnJheSBlbGVtZW50cyIpO3JldHVybntzaXplOm8uc2l6ZSpuLGFsaWduOm8uYWxpZ24sdHlwZTp7dGFnOiJhcnJheSIsZWxlbWVudFR5cGU6by50eXBlLGVsZW1lbnRTaXplOm8uc2l6ZX19fWlmKHI9PT0ic3RydWN0Inx8cj09PSJ1bmlvbiIpe2xldCBuPXd0KHQpO3JldHVybntzaXplOm4uc2l6ZSxhbGlnbjpuLm1heEVmZmVjdGl2ZUFsaWduLHR5cGU6e3RhZzpyLGZpZWxkczpuLmZpZWxkc319fXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biAnIycgZGVjbGFyYXRpb24gJHtKU09OLnN0cmluZ2lmeShTdHJpbmcocikpfWApfXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogaW52YWxpZCBtZW1iZXIgdmFsdWU6ICR7U3RyaW5nKHQpfWApfWZ1bmN0aW9uIHd0KHQpe2xldCBlPXRbIiMiXT09PSJzdHJ1Y3QiLHI9dFsiI3BhY2siXT8/OCxuPTEsbz0wLGk9W10sYz0wLHM9LTEsdT0wLHA9MCxoPSgpPT57czwwfHwoYz1VKHMrTWF0aC5jZWlsKHUvOCkscCkscz0tMSl9O2ZvcihsZXRbRixnXW9mIE9iamVjdC5lbnRyaWVzKHQpKXtpZihGLnN0YXJ0c1dpdGgoIiMiKSljb250aW51ZTtsZXQgVD0vXihbXkBdKylAKFxkKykkLy5leGVjKEYpLEU9VD9UWzFdOkYsUD1UP051bWJlcihUWzJdKTowLHtzaXplOncsYWxpZ246Uyx0eXBlOmF9PUsoZyksZD10eXBlb2YgZz09InN0cmluZyImJmcuZW5kc1dpdGgoIiEiKSxtPVM7aWYocj4wJiYobT1NYXRoLm1pbihyLG0pKSxQJiYobT1NYXRoLm1heChtLFApKSxhLnRhZz09PSJiaXRmaWVsZCIpe2lmKEUuc3RhcnRzV2l0aCgiJCIpKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogYml0ZmllbGQgbWVtYmVycyBtdXN0IGJlIG5hbWVkIik7aWYoIWUpe2kucHVzaCh7bmFtZTpFLG9mZnNldDowLHNpemU6dyx0eXBlOnsuLi5hLGJpdDowfX0pLG49TWF0aC5tYXgobixtKSxvPU1hdGgubWF4KG8sdyk7Y29udGludWV9bGV0IGw9YS53aWR0aDsoczwwfHx3IT09cHx8dStsPnAqOCkmJihzPj0wJiZoKCkscz1VKGMsbSksdT0wLHA9dyksaS5wdXNoKHtuYW1lOkUsb2Zmc2V0OnMsc2l6ZTp3LHR5cGU6ey4uLmEsYml0OnV9fSksdSs9bCxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpO2NvbnRpbnVlfWgoKTtsZXQgZj1VKGMsbSk7aWYoIUUuc3RhcnRzV2l0aCgiJCIpKWkucHVzaCh7bmFtZTpFLG9mZnNldDpmLHNpemU6dyx0eXBlOmEsLi4uZD97bm9ubnVsbDohMH06e319KTtlbHNle2lmKGEudGFnIT09InN0cnVjdCImJmEudGFnIT09InVuaW9uIil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGFub255bW91cyBtZW1iZXIgIiR7RX0iIG11c3QgYmUgYSBzdHJ1Y3QvdW5pb25gKTtmb3IobGV0IGwgb2YgYS5maWVsZHMpaS5wdXNoKHsuLi5sLG9mZnNldDpsLm9mZnNldCtmfSl9ZSYmKGM9Zit3KSxuPU1hdGgubWF4KG4sbSksbz1NYXRoLm1heChvLHcpfXJldHVybiBoKCkse3NpemU6VShlP2M6byxuKSxtYXhFZmZlY3RpdmVBbGlnbjpuLGZpZWxkczppfX1mdW5jdGlvbiBndCh0LGUscil7bGV0IG49UltyXTtyZXR1cm4gbj09PTE/QmlnSW50KHQuZ2V0VWludDgoZSkpOm49PT0yP0JpZ0ludCh0LmdldFVpbnQxNihlLCEwKSk6bj09PTQ/QmlnSW50KHQuZ2V0VWludDMyKGUsITApKTp0LmdldEJpZ1VpbnQ2NChlLCEwKX1mdW5jdGlvbiBZdCh0LGUscixuKXtsZXQgbz1SW3JdO2lmKG89PT0xKXt0LnNldFVpbnQ4KGUsTnVtYmVyKG4mMHhmZm4pKTtyZXR1cm59aWYobz09PTIpe3Quc2V0VWludDE2KGUsTnVtYmVyKG4mMHhmZmZmbiksITApO3JldHVybn1pZihvPT09NCl7dC5zZXRVaW50MzIoZSxOdW1iZXIobiYweGZmZmZmZmZmbiksITApO3JldHVybn10LnNldEJpZ1VpbnQ2NChlLG4mMHhmZmZmZmZmZmZmZmZmZmZmbiwhMCl9ZnVuY3Rpb24gVnQodCxlLHIpe2xldCBuPUJpZ0ludChyLndpZHRoKSxvPWd0KHQsZSxyLnVuaXQpPj5CaWdJbnQoci5iaXQpJigxbjw8biktMW47cmV0dXJuIHIudW5pdFswXT09PSJpIiYmbyYxbjw8bi0xbiYmKG8tPTFuPDxuKSxyLndpZHRoPjUzP286TnVtYmVyKG8pfWZ1bmN0aW9uIHZ0KHQsZSxyLG4pe2xldCBvPUJpZ0ludChyLndpZHRoKSxpPUJpZ0ludChyLmJpdCksYz0oMW48PG8pLTFuLHM9Yzw8aSx1PWd0KHQsZSxyLnVuaXQpLHA9KHR5cGVvZiBuPT0iYmlnaW50Ij9uOkJpZ0ludChNYXRoLnRydW5jKG4pKSkmYztZdCh0LGUsci51bml0LHUmfnN8cDw8aSl9dmFyIGp0PXsidXRmLTgiOm5ldyBUZXh0RW5jb2RlcigidXRmLTgiKSwidXRmLTE2bGUiOm5ldyBUZXh0RW5jb2RlcigidXRmLTE2bGUiKX0sWHQ9eyJ1dGYtOCI6bmV3IFRleHREZWNvZGVyKCJ1dGYtOCIse2lnbm9yZUJPTTohMH0pLCJ1dGYtMTZsZSI6bmV3IFRleHREZWNvZGVyKCJ1dGYtMTZsZSIse2lnbm9yZUJPTTohMH0pfTtmdW5jdGlvbiBadCh0LGUscixuKXtsZXQgbz1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKSxpPW49PT0idXRmLTE2bGUiPzI6MSxjPXI7Zm9yKGxldCBzPTA7cytpPD1yO3MrPWkpaWYob1tzXT09PTAmJihpPT09MXx8b1tzKzFdPT09MCkpe2M9czticmVha31yZXR1cm4gWHRbbl0uZGVjb2RlKG8uc3ViYXJyYXkoMCxjKSl9ZnVuY3Rpb24gcXQodCxlLHIsbixvKXtsZXQgaT1uZXcgVWludDhBcnJheSh0LmJ1ZmZlcix0LmJ5dGVPZmZzZXQrZSxyKTtpLmZpbGwoMCk7bGV0IHM9ci0obj09PSJ1dGYtMTZsZSI/MjoxKTtpZihzPD0wKXJldHVybjtsZXQgdT1qdFtuXS5lbmNvZGUoU3RyaW5nKG8/PyIiKSk7aS5zZXQodS5zdWJhcnJheSgwLE1hdGgubWluKHUubGVuZ3RoLHMpKSl9ZnVuY3Rpb24gS3QodCxlLHIsbil7bGV0IG89bi5lbGVtZW50U2l6ZT4wP3Ivbi5lbGVtZW50U2l6ZTowLGk9W107Zm9yKGxldCBjPTA7YzxvO2MrKylpLnB1c2goVHQodCxlK2Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUpKTtyZXR1cm4gaX1mdW5jdGlvbiBRdCh0LGUscixuLG8pe2xldCBpPW4uZWxlbWVudFNpemU+MD9yL24uZWxlbWVudFNpemU6MCxjPW8/P1tdO2ZvcihsZXQgcz0wO3M8aTtzKyspRnQodCxlK3Mqbi5lbGVtZW50U2l6ZSxuLmVsZW1lbnRUeXBlLG4uZWxlbWVudFNpemUsY1tzXSl9ZnVuY3Rpb24gVHQodCxlLHIsbil7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpyZXR1cm4geih0LGUsci5raW5kKTtjYXNlImJpdGZpZWxkIjpyZXR1cm4gVnQodCxlLHIpO2Nhc2Uic3RyaW5nIjpyZXR1cm4gWnQodCxlLG4sci5lbmNvZGluZyk7Y2FzZSJzdHJ1Y3QiOmNhc2UidW5pb24iOnJldHVybiBRKHQsZSxyLmZpZWxkcyk7Y2FzZSJhcnJheSI6cmV0dXJuIEt0KHQsZSxuLHIpfX1mdW5jdGlvbiBGdCh0LGUscixuLG8pe3N3aXRjaChyLnRhZyl7Y2FzZSJiYXNpYyI6Wih0LGUse2s6ci5raW5kLHY6b30pO2JyZWFrO2Nhc2UiYml0ZmllbGQiOnZ0KHQsZSxyLG8/PzApO2JyZWFrO2Nhc2Uic3RyaW5nIjpxdCh0LGUsbixyLmVuY29kaW5nLG8pO2JyZWFrO2Nhc2Uic3RydWN0IjpjYXNlInVuaW9uIjpTdCh0LGUsci5maWVsZHMsbz8/e30pO2JyZWFrO2Nhc2UiYXJyYXkiOlF0KHQsZSxuLHIsbyk7YnJlYWt9fWZ1bmN0aW9uIFEodCxlLHIpe2xldCBuPXt9O2ZvcihsZXQgbyBvZiByKXtsZXQgaT1UdCh0LGUrby5vZmZzZXQsby50eXBlLG8uc2l6ZSk7aWYoby5ub25udWxsJiZpPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGRlY29kZTogJyEnIGZpZWxkICIke28ubmFtZX0iIGdvdCAwIChDIGRpZCBub3QgZmlsbCBpdCwgb3IgZGVjb2RlIHdhcyBjYWxsZWQgb24gYW4gdW5maWxsZWQgc2xvdClgKTtuW28ubmFtZV09aX1yZXR1cm4gbn1mdW5jdGlvbiBTdCh0LGUscixuKXtmb3IobGV0IG8gb2YgciluW28ubmFtZV0hPT12b2lkIDAmJkZ0KHQsZStvLm9mZnNldCxvLnR5cGUsby5zaXplLG5bby5uYW1lXSl9ZnVuY3Rpb24gSnQodCl7bGV0e2ZpZWxkczplLHNpemU6cixtYXhFZmZlY3RpdmVBbGlnbjpufT13dCh0KTtyZXR1cm57ZmllbGRzOmUsc2l6ZTpyLHN0cnVjdEFsaWduOm4sZGVjb2RlOm89PlEodHlwZW9mIG89PSJudW1iZXIiP25ldyBEYXRhVmlldyhodC5yZWFkQnl0ZXMobyxyKSk6bmV3IERhdGFWaWV3KG8pLDAsZSksYWxsb2M6KG89PntpZihvIT09dm9pZCAwJiYoIU51bWJlci5pc0ludGVnZXIobyl8fG88MSkpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBhbGxvYyhuKSByZXF1aXJlcyBhbiBpbnRlZ2VyIG4gPj0gMSAoUEFCKDApIG5ldmVyIGVzY2FwZXMgXHUyMDE0IHBhc3MgTlVMTCBmb3IgYW4gZW1wdHkgcG9pbnRlciBwb3NpdGlvbikiKTtyZXR1cm4gbmV3IHgocioobz8/MSkpfSksZW5jb2RlOigobyxpLGMpPT57aWYobz09bnVsbCl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGVuY29kZSh2KSByZXF1aXJlcyBhbiBhcmd1bWVudDsgdXNlIGFsbG9jKCkgZm9yIGEgemVyb2VkIG91dC1wYXJhbSBzbG90Iik7bGV0IHM9aT8/bmV3IHgocik7cmV0dXJuIFN0KG5ldyBEYXRhVmlldyhzKSxjPz8wLGUsbyksc30pLG9mZnNldE9mOm89Pntmb3IobGV0IGkgb2YgZSlpZihpLm5hbWU9PT1vKXJldHVybiBpLm9mZnNldDt0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IG5vIGZpZWxkICIke299ImApfX19ZnVuY3Rpb24gdGUodCxlLHIpe2xldCBuPWVbIiMiXTtpZihuIT09dm9pZCAwJiZuIT09dCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICR7dH0oKSByZWNlaXZlZCBhICcke1N0cmluZyhuKX0nIGRlY2xhcmF0aW9uIChraW5kIG1pc21hdGNoIFx1MjAxNCB1c2UgJHtufSgpIGZvciBpdClgKTtsZXQgbz1lWyIjcGFjayJdO2lmKHI9PT12b2lkIDAmJm8hPT12b2lkIDApcj1vO2Vsc2UgaWYociE9PXZvaWQgMCYmbyE9PXZvaWQgMCYmciE9PW8pdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiAjcGFjayBjb25mbGljdDogb3B0cy5wYWNrPSR7cn0gdnMgZGVjbGFyYXRpb24gJHtTdHJpbmcobyl9YCk7bGV0IGk9eyIjIjp0fTtyIT09dm9pZCAwJiYoaVsiI3BhY2siXT1yKTtmb3IobGV0W2Msc11vZiBPYmplY3QuZW50cmllcyhlKSljLnN0YXJ0c1dpdGgoIiMiKXx8KGlbY109cyk7cmV0dXJuIGl9ZnVuY3Rpb24gQih0LGUscil7bGV0IG49dHlwZW9mIHQ9PSJzdHJpbmciO3JldHVybiBKdCh0ZSgic3RydWN0IixuP2U6dCwobj9yOmUpPy5wYWNrKSl9dmFyIGVlPXsiIyI6InN0cnVjdCIsY2I6InUzMiIsbHBSZXNlcnZlZDoiPD5wdHIiLGxwRGVza3RvcDoiPD5wdHIiLGxwVGl0bGU6Ijw+cHRyIixkd1g6InUzMiIsZHdZOiJ1MzIiLGR3WFNpemU6InUzMiIsZHdZU2l6ZToidTMyIixkd1hDb3VudENoYXJzOiJ1MzIiLGR3WUNvdW50Q2hhcnM6InUzMiIsZHdGaWxsQXR0cmlidXRlOiJ1MzIiLGR3RmxhZ3M6InUzMiIsd1Nob3dXaW5kb3c6InUxNkBTaG93V2luZG93Q21kIixjYlJlc2VydmVkMjoidTE2IixscFJlc2VydmVkMjoiPD5wdHIiLGhTdGRJbnB1dDoiPEhGSUxFPnB0ciIsaFN0ZE91dHB1dDoiPEhGSUxFPnB0ciIsaFN0ZEVycm9yOiI8SEZJTEU+cHRyIn0sWT1CKCJTVEFSVFVQSU5GT1ciLGVlKSxyZT17IiMiOiJzdHJ1Y3QiLGhQcm9jZXNzOiI8SFBST0NFU1M+cHRyISIsaFRocmVhZDoiPEhUSFJFQUQ+cHRyISIsZHdQcm9jZXNzSWQ6InUzMiIsZHdUaHJlYWRJZDoidTMyIn0sSj1CKCJQUk9DRVNTX0lORk9STUFUSU9OIixyZSk7dmFyIGI9KHQsZSxyKT0+RXQoImtlcm5lbDMyLmRsbCIsdCxlLHIpLEl0PWIoIkNyZWF0ZVBpcGUiLCI8PnB0ciA8PnB0ciA8PnB0ciB1MzIgLT4gaTMyIiksdHQ9YigiU2V0SGFuZGxlSW5mb3JtYXRpb24iLCI8SEZJTEU+cHRyISB1MzIgdTMyIC0+IGkzMiIpLEN0PWIoIkNyZWF0ZVByb2Nlc3NXIiwiPFdDSEFSPnB0ciA8V0NIQVI+cHRyIDw+cHRyIDw+cHRyIGkzMiB1MzIgPD5wdHIgPFdDSEFSPnB0ciA8U1RBUlRVUElORk9XPnB0ciA8UFJPQ0VTU19JTkZPUk1BVElPTj5wdHIgLT4gaTMyIix7U1RBUlRVUElORk9XOll9KSxidD1iKCJXYWl0Rm9yU2luZ2xlT2JqZWN0IiwiPD5wdHIgdTMyIC0+IHUzMiIpLE50PWIoIkdldEV4aXRDb2RlUHJvY2VzcyIsIjxIUFJPQ0VTUz5wdHIhIDxCWVRFPnB0ciAtPiBpMzIiKSxNPWIoIkNsb3NlSGFuZGxlIiwiPD5wdHIgLT4gaTMyIik7dmFyIHl0PWIoIlJlYWRGaWxlIiwiPEhGSUxFPnB0ciEgPEJZVEU+cHRyIHUzMiA8QllURT5wdHIgPD5wdHIgLT4gaTMyIik7dmFyIGV0PWIoIkdldExhc3RFcnJvciIsIiAtPiB1MzIiKSxEdD1iKCJHZXRTeXN0ZW1EaXJlY3RvcnlXIiwiPEJZVEU+cHRyIHUzMiAtPiB1MzIiKTt2YXIgbmU9dD0+e3RyeXtsZXQgZT1QdC5vcGVuKCJkaWFnLmxvZyIsImEiKTtlJiYoZS5wdXRzKGAke0RhdGUubm93KCl9ICR7dH0KYCksZS5jbG9zZSgpKX1jYXRjaHt9fSxydD0xLG9lPTI1NixpZT00Mjk0OTY3Mjk1LEg9T3QuV29ya2VyLnBhcmVudCxMdD0iQzpcXFdpbmRvd3NcXFN5c3RlbTMyIjt0cnl7bGV0IHQ9Ry5hbGxvYygyNTYpLHI9RHQodCwyNTYpPjA/Ry5kZWNvZGUodCk6IiI7ciYmKEx0PXIpfWNhdGNoKHQpe25lKCJTWVMtRElSLUZBSUw6ICIrU3RyaW5nKHQpKX12YXIgbnQ9QigiUElQRV9IQU5ETEVTIix7aFJlYWQ6IjxIRklMRT5wdHIhIixoV3JpdGU6IjxIRklMRT5wdHIhIn0pO2Z1bmN0aW9uIHNlKHQsZSl7bGV0IHI9bnQuYWxsb2MoKTtpZighSXQoci5wdHIsci5wdHIrbnQub2Zmc2V0T2YoImhXcml0ZSIpLE8sMCkpdGhyb3cgbmV3IEVycm9yKCJDcmVhdGVQaXBlIGVycj0iK2V0KCkpO2xldHtoUmVhZDpuLGhXcml0ZTpvfT1udC5kZWNvZGUocik7dHQobyxydCxydCksdHQobixydCwwKTtsZXQgaT1KLmFsbG9jKCksYz1gJHtMdH1cXGNtZC5leGUgL3UgL2MgJHtlfWA7aWYoIUN0KE8sYyxPLE8sMSwwLE8sTyx7Y2I6WS5zaXplLGR3RmxhZ3M6b2UsaFN0ZE91dHB1dDpvLGhTdGRFcnJvcjpvfSxpLnB0cikpdGhyb3cgTShuKSxNKG8pLG5ldyBFcnJvcigiQ3JlYXRlUHJvY2Vzc1cgZXJyPSIrZXQoKSsiIGNtZD0iK2MpO2xldHtoUHJvY2VzczpzLGhUaHJlYWQ6dSxkd1Byb2Nlc3NJZDpwfT1KLmRlY29kZShpKTtNKHUpLE0obyksSC5wb3N0TWVzc2FnZSh7dHlwZToiaW5mbyIsaWQ6dCxwaWQ6cH0pO2xldCBoPW5ldyB4KDQwOTYpLEY9bmV3IFVpbnQ4QXJyYXkoaCksZz1uZXcgeCg0KSxUPW5ldyBVaW50MzJBcnJheShnKTtmb3IoO1RbMF09MCwhIXl0KG4saCw0MDk2LGcsTyk7KXtsZXQgUz1UWzBdO2lmKFM9PT0wKWJyZWFrO0gucG9zdE1lc3NhZ2Uoe3R5cGU6ImRhdGEiLGlkOnQsY2h1bms6Ri5zbGljZSgwLFMpfSl9YnQocyxpZSk7bGV0IEU9bmV3IHgoNCksUD1uZXcgSW50MzJBcnJheShFKTtOdChzLEUpO2xldCB3PVBbMF07cmV0dXJuIE0obiksTShzKSx3fUgub25tZXNzYWdlPXQ9PntsZXQgZT10LmRhdGE7aWYoZS50eXBlPT09InJ1biImJnR5cGVvZiBlLmNtZD09InN0cmluZyIpe2xldCByPS0xLG49bnVsbDt0cnl7cj1zZShlLmlkLGUuY21kKX1jYXRjaChvKXtuPVN0cmluZyhvKX1ILnBvc3RNZXNzYWdlKHt0eXBlOiJyZXN1bHQiLGlkOmUuaWQsY29kZTpyLGVycm9yOm59KX1ILm9ubWVzc2FnZT1udWxsfTsK");
22049
22295
  bumpWorkers(1);
22050
22296
  const id = 1;
22051
22297
  let innerPid = null;
@@ -22076,7 +22322,7 @@ function runInWorker(cmd, signal, timeoutMs) {
22076
22322
  return;
22077
22323
  settled = true;
22078
22324
  if (timer !== null)
22079
- os6.clearTimeout(timer);
22325
+ os7.clearTimeout(timer);
22080
22326
  worker.onmessage = null;
22081
22327
  bumpWorkers(-1);
22082
22328
  fn();
@@ -22103,7 +22349,7 @@ function runInWorker(cmd, signal, timeoutMs) {
22103
22349
  killOnAbort();
22104
22350
  }
22105
22351
  if (timeoutMs != null && timeoutMs > 0) {
22106
- timer = os6.setTimeout(() => {
22352
+ timer = os7.setTimeout(() => {
22107
22353
  finish(() => {
22108
22354
  kill();
22109
22355
  resolveTrailers({ "X-Exit-Code": "-1" });
@@ -22382,35 +22628,35 @@ function listWindows() {
22382
22628
  var DISP_CHANGE_NAME = {
22383
22629
  [
22384
22630
  0
22385
- /* gui.DisplayChangeResult.SUCCESSFUL */
22631
+ /* DisplayChangeResult.SUCCESSFUL */
22386
22632
  ]: "SUCCESSFUL",
22387
22633
  [
22388
22634
  1
22389
- /* gui.DisplayChangeResult.RESTART */
22635
+ /* DisplayChangeResult.RESTART */
22390
22636
  ]: "RESTART",
22391
22637
  [
22392
22638
  -1
22393
- /* gui.DisplayChangeResult.FAILED */
22639
+ /* DisplayChangeResult.FAILED */
22394
22640
  ]: "FAILED",
22395
22641
  [
22396
22642
  -2
22397
- /* gui.DisplayChangeResult.BADMODE */
22643
+ /* DisplayChangeResult.BADMODE */
22398
22644
  ]: "BADMODE",
22399
22645
  [
22400
22646
  -3
22401
- /* gui.DisplayChangeResult.NOTUPDATED */
22647
+ /* DisplayChangeResult.NOTUPDATED */
22402
22648
  ]: "NOTUPDATED",
22403
22649
  [
22404
22650
  -4
22405
- /* gui.DisplayChangeResult.BADFLAGS */
22651
+ /* DisplayChangeResult.BADFLAGS */
22406
22652
  ]: "BADFLAGS",
22407
22653
  [
22408
22654
  -5
22409
- /* gui.DisplayChangeResult.BADPARAM */
22655
+ /* DisplayChangeResult.BADPARAM */
22410
22656
  ]: "BADPARAM",
22411
22657
  [
22412
22658
  -6
22413
- /* gui.DisplayChangeResult.BADDUALVIEW */
22659
+ /* DisplayChangeResult.BADDUALVIEW */
22414
22660
  ]: "BADDUALVIEW"
22415
22661
  };
22416
22662
  function dispChangeName(ret) {
@@ -22419,10 +22665,10 @@ function dispChangeName(ret) {
22419
22665
  function currentScreen() {
22420
22666
  return GetSystemMetrics(
22421
22667
  0
22422
- /* gui.SysMetrics.CXSCREEN */
22668
+ /* SysMetrics.CXSCREEN */
22423
22669
  ) + "x" + GetSystemMetrics(
22424
22670
  1
22425
- /* gui.SysMetrics.CYSCREEN */
22671
+ /* SysMetrics.CYSCREEN */
22426
22672
  );
22427
22673
  }
22428
22674
  function listModes32() {
@@ -22456,7 +22702,7 @@ function applyDisplayMode(w2, h2, persist) {
22456
22702
  const testRet = ChangeDisplaySettings(
22457
22703
  dm.ptr,
22458
22704
  2
22459
- /* gui.ChangeDisplayFlag.TEST */
22705
+ /* ChangeDisplayFlag.TEST */
22460
22706
  );
22461
22707
  if (testRet !== 0) {
22462
22708
  return {
@@ -22473,7 +22719,7 @@ function applyDisplayMode(w2, h2, persist) {
22473
22719
  ret = ChangeDisplaySettings(
22474
22720
  dm.ptr,
22475
22721
  1
22476
- /* gui.ChangeDisplayFlag.UPDATEREGISTRY */
22722
+ /* ChangeDisplayFlag.UPDATEREGISTRY */
22477
22723
  );
22478
22724
  }
22479
22725
  return { before, after: currentScreen(), testRet, ret, retName: dispChangeName(ret), modes32: listModes32() };
@@ -22486,16 +22732,87 @@ API\uFF08\u914D\u7F6E token \u540E\u9700 Authorization: Bearer <token>\uFF0C\u67
22486
22732
  \uFF08X-Dimensions\uFF1B\u4E0D\u5E26 hwnd = \u6574\u5C4F BitBlt\uFF1B\u5E26 hwnd \u9ED8\u8BA4 mode=print
22487
22733
  \u8BA9\u7A97\u53E3\u81EA\u7ED8\u2014\u2014\u906E\u6321/\u6700\u5C0F\u5316/\u8D85\u5C4F\u4E5F\u62FF\u5B8C\u6574\u50CF\u7D20\uFF0Cscreen \u53EA\u622A\u53EF\u89C1\u90E8\u5206\uFF09
22488
22734
  GET /window_list \u2192 JSON \u7A97\u53E3\u5217\u8868 [{hwnd,title,className,...}]
22735
+ GET /tray_list \u2192 JSON {icons:[{area,index,hWnd,uID,tooltip,rect}]}\uFF08\u8DE8\u8FDB\u7A0B\u679A\u4E3E
22736
+ explorer toolbar\uFF1A\u53EF\u89C1\u533A Shell_TrayWnd + \u6298\u53E0\u533A NotifyIconOverflowWindow\uFF1B
22737
+ rect \u5C4F\u5E55\u7269\u7406\u50CF\u7D20\uFF0C\u5168 0 \u2192 null\uFF1B\u6298\u53E0\u9762\u677F\u672A\u5C55\u5F00\u65F6 overflow \u533A rect
22738
+ \u4EC5\u5F53\u5C55\u5F00\u540E\u53EF\u9760\uFF09\uFF1B?probe=<hwnd>&uid=<n> \u2192 \u9644 probe {hr,hrName,rect}
22739
+ \uFF08\u5355\u56FE\u6807 Shell_NotifyIconGetRect\uFF0CWin7+\uFF1A0=found \u9644\u5BB9\u5668 rect / 1=hidden
22740
+ / E_FAIL=\u4E0D\u5B58\u5728\u6216 GUID \u56FE\u6807\uFF1BXP \u65E0\u6B64 API \u2192 unsupported\uFF09
22489
22741
  POST /set_resolution ?w=<px>&h=<px>&persist=0|1\uFF08\u9ED8\u8BA4 1 = \u5199\u6CE8\u518C\u8868\u8DE8\u91CD\u542F\uFF09\u2192 JSON
22490
22742
  {before,after,testRet,ret,retName,modes32}\uFF1Bmodes32 \u6052\u5E26 32bpp
22491
- \u53EF\u7528\u6A21\u5F0F\uFF08\u975E\u6CD5\u5BBD\u9AD8\u4F1A\u4EE5 BADMODE \u62D2\u7EDD\u5E76\u7ED9\u672C\u5217\u8868\uFF09`;
22743
+ \u53EF\u7528\u6A21\u5F0F\uFF08\u975E\u6CD5\u5BBD\u9AD8\u4F1A\u4EE5 BADMODE \u62D2\u7EDD\u5E76\u7ED9\u672C\u5217\u8868\uFF09
22744
+ POST /input body = JSON \u6570\u7EC4\uFF08\u6279\u91CF\u6CE8\u5165\uFF1Bx/y \u7269\u7406\u50CF\u7D20\uFF09\uFF1A
22745
+ {"t":"move","x":,"y":} | {"t":"down|up","btn":"left|right|middle|x1|x2","x":,"y":?} |
22746
+ {"t":"key","key":"a|enter|0x41","up":true?} | {"t":"sleep","ms":0..5000}
22747
+ \u2192 JSON {sent,expected}\uFF1B\u6309 sleep \u5207\u6BB5\uFF0C\u6BB5\u5185\u4E00\u6B21 SendInput \u539F\u5B50\u6CE8\u5165`;
22492
22748
  function usageResponse() {
22493
22749
  return new Response(USAGE, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
22494
22750
  }
22751
+ var INPUT_MOUSE = 0;
22752
+ var INPUT_KEYBOARD = 1;
22753
+ var MOUSEEVENTF_MOVE = 1;
22754
+ var MOUSEEVENTF_ABSOLUTE = 32768;
22755
+ var KEYEVENTF_KEYUP = 2;
22756
+ var MOUSE_BTNS = {
22757
+ left: [2, 4, 0],
22758
+ right: [8, 16, 0],
22759
+ middle: [32, 64, 0],
22760
+ x1: [128, 256, 1],
22761
+ x2: [128, 256, 2]
22762
+ };
22763
+ var VK_NAMES = {
22764
+ backspace: 8,
22765
+ tab: 9,
22766
+ enter: 13,
22767
+ shift: 16,
22768
+ ctrl: 17,
22769
+ alt: 18,
22770
+ caps: 20,
22771
+ esc: 27,
22772
+ space: 32,
22773
+ pageup: 33,
22774
+ pagedown: 34,
22775
+ end: 35,
22776
+ home: 36,
22777
+ left: 37,
22778
+ up: 38,
22779
+ right: 39,
22780
+ down: 40,
22781
+ insert: 45,
22782
+ delete: 46,
22783
+ win: 91,
22784
+ f1: 112,
22785
+ f2: 113,
22786
+ f3: 114,
22787
+ f4: 115,
22788
+ f5: 116,
22789
+ f6: 117,
22790
+ f7: 118,
22791
+ f8: 119,
22792
+ f9: 120,
22793
+ f10: 121,
22794
+ f11: 122,
22795
+ f12: 123
22796
+ };
22797
+ function vkOf(key) {
22798
+ if (typeof key === "number" && Number.isInteger(key) && key >= 0 && key <= 65535)
22799
+ return key;
22800
+ if (typeof key === "string") {
22801
+ if (key.length === 1) {
22802
+ const c2 = key.toUpperCase().charCodeAt(0);
22803
+ if (c2 >= 48 && c2 <= 57 || c2 >= 65 && c2 <= 90)
22804
+ return c2;
22805
+ }
22806
+ const vk = VK_NAMES[key.toLowerCase()];
22807
+ if (vk !== void 0)
22808
+ return vk;
22809
+ }
22810
+ throw new Error("bad key: " + JSON.stringify(key) + " (a-z/0-9|name|0..0xFFFF)");
22811
+ }
22495
22812
  var server = createServer(async (req) => {
22496
22813
  const t0 = Date.now();
22497
22814
  const path = new URL(req.url).pathname;
22498
- const isApi = req.method === "POST" && (path === "/exec" || path === "/set_resolution") || req.method === "GET" && (path === "/window_list" || path === "/screenshot");
22815
+ const isApi = req.method === "POST" && (path === "/exec" || path === "/set_resolution" || path === "/input") || req.method === "GET" && (path === "/window_list" || path === "/screenshot" || path === "/tray_list");
22499
22816
  if (!isApi)
22500
22817
  return usageResponse();
22501
22818
  const denied = authCheck(req);
@@ -22514,6 +22831,31 @@ var server = createServer(async (req) => {
22514
22831
  return jsonError(500, String(ex));
22515
22832
  }
22516
22833
  }
22834
+ if (req.method === "GET" && path === "/tray_list") {
22835
+ const params = new URL(req.url).searchParams;
22836
+ let probe = null;
22837
+ const ph = params.get("probe");
22838
+ if (ph !== null) {
22839
+ const hh = Number(ph), uid = Number(params.get("uid") ?? "");
22840
+ if (!Number.isInteger(hh) || hh <= 0 || !Number.isInteger(uid) || uid < 0) {
22841
+ logReq(t0, "GET /tray_list", 400, "probe=<hwnd>&uid=<n>");
22842
+ return jsonError(400, "probe needs integer hwnd>0 and uid>=0");
22843
+ }
22844
+ probe = { hWnd: hh, uID: uid };
22845
+ }
22846
+ try {
22847
+ const icons = listTrayIcons();
22848
+ const body = { icons };
22849
+ if (probe)
22850
+ body.probe = probeTrayIcon(probe.hWnd, probe.uID);
22851
+ const nOv = icons.reduce((n2, e2) => n2 + (e2.area === "overflow" ? 1 : 0), 0);
22852
+ logReq(t0, "GET /tray_list", 200, icons.length + " icons \xB7 overflow " + nOv);
22853
+ return new Response(JSON.stringify(body), { headers: { "Content-Type": "application/json" } });
22854
+ } catch (ex) {
22855
+ logReq(t0, "GET /tray_list", 500, String(ex));
22856
+ return jsonError(500, String(ex));
22857
+ }
22858
+ }
22517
22859
  if (req.method === "GET" && path === "/screenshot") {
22518
22860
  let opts;
22519
22861
  try {
@@ -22555,6 +22897,105 @@ var server = createServer(async (req) => {
22555
22897
  logReq(t0, "POST /set_resolution " + w2 + "x" + h2 + (persist ? "" : " persist=0"), 200, result.ret !== 0 ? result.retName : void 0);
22556
22898
  return resp;
22557
22899
  }
22900
+ if (req.method === "POST" && path === "/input") {
22901
+ const bad = (msg) => {
22902
+ logReq(t0, "POST /input", 400, msg);
22903
+ return jsonError(400, msg);
22904
+ };
22905
+ let raw;
22906
+ try {
22907
+ raw = await req.json();
22908
+ } catch (ex) {
22909
+ return bad("bad json: " + String(ex));
22910
+ }
22911
+ if (!Array.isArray(raw) || raw.length === 0)
22912
+ return bad("body must be a non-empty JSON array");
22913
+ if (raw.length > 1e3)
22914
+ return bad("too many events: " + raw.length + " (max 1000)");
22915
+ const sw = GetSystemMetrics(0), sh = GetSystemMetrics(1);
22916
+ const segs = [{ els: [], sleep: 0 }];
22917
+ const cur = () => segs[segs.length - 1];
22918
+ try {
22919
+ for (const e2 of raw) {
22920
+ if (typeof e2 !== "object" || e2 === null || Array.isArray(e2))
22921
+ throw new Error("event must be an object: " + JSON.stringify(e2));
22922
+ const ev = e2;
22923
+ const abs = (required) => {
22924
+ if (ev.x === void 0 && ev.y === void 0) {
22925
+ if (required)
22926
+ throw new Error("x/y required for move");
22927
+ return [0, 0, 0];
22928
+ }
22929
+ const x2 = ev.x, y2 = ev.y;
22930
+ if (typeof x2 !== "number" || typeof y2 !== "number" || !Number.isInteger(x2) || !Number.isInteger(y2))
22931
+ throw new Error("x/y must be integers (physical px)");
22932
+ if (x2 < 0 || x2 >= sw || y2 < 0 || y2 >= sh)
22933
+ throw new Error("x/y out of screen: 0.." + (sw - 1) + " / 0.." + (sh - 1));
22934
+ return [
22935
+ Math.round(x2 * 65535 / (sw - 1)),
22936
+ Math.round(y2 * 65535 / (sh - 1)),
22937
+ MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE
22938
+ ];
22939
+ };
22940
+ switch (ev.t) {
22941
+ case "move": {
22942
+ const [dx, dy, f2] = abs(true);
22943
+ cur().els.push({ type: INPUT_MOUSE, data: { mi: { dx, dy, dwFlags: f2 } } });
22944
+ break;
22945
+ }
22946
+ case "down":
22947
+ case "up": {
22948
+ const btn = typeof ev.btn === "string" ? MOUSE_BTNS[ev.btn] : void 0;
22949
+ if (!btn)
22950
+ throw new Error("bad btn: " + JSON.stringify(ev.btn) + " (left|right|middle|x1|x2)");
22951
+ const [downF, upF, mData] = btn;
22952
+ const [dx, dy, f2] = abs(false);
22953
+ const flag = ev.t === "down" ? downF : upF;
22954
+ cur().els.push({ type: INPUT_MOUSE, data: { mi: { dx, dy, mouseData: mData, dwFlags: f2 | flag } } });
22955
+ break;
22956
+ }
22957
+ case "key": {
22958
+ const up = ev.up === true;
22959
+ cur().els.push({ type: INPUT_KEYBOARD, data: { ki: { wVk: vkOf(ev.key), dwFlags: up ? KEYEVENTF_KEYUP : 0 } } });
22960
+ break;
22961
+ }
22962
+ case "sleep": {
22963
+ const ms = ev.ms;
22964
+ if (typeof ms !== "number" || !Number.isFinite(ms) || ms < 0 || ms > 5e3)
22965
+ throw new Error("sleep ms must be a number in 0..5000");
22966
+ segs.push({ els: [], sleep: ms });
22967
+ break;
22968
+ }
22969
+ default:
22970
+ throw new Error("bad t: " + JSON.stringify(ev.t) + " (move|down|up|key|sleep)");
22971
+ }
22972
+ }
22973
+ } catch (ex) {
22974
+ return bad(ex instanceof Error ? ex.message : String(ex));
22975
+ }
22976
+ let expected = 0, sent = 0;
22977
+ for (const s2 of segs)
22978
+ expected += s2.els.length;
22979
+ try {
22980
+ for (const seg of segs) {
22981
+ if (seg.sleep > 0)
22982
+ await new Promise((r2) => {
22983
+ os7.setTimeout(r2, seg.sleep);
22984
+ });
22985
+ if (seg.els.length === 0)
22986
+ continue;
22987
+ const n2 = SendInput(seg.els.length, seg.els, INPUT.size);
22988
+ sent += n2;
22989
+ if (n2 < seg.els.length)
22990
+ break;
22991
+ }
22992
+ } catch (ex) {
22993
+ logReq(t0, "POST /input", 500, String(ex));
22994
+ return jsonError(500, String(ex));
22995
+ }
22996
+ logReq(t0, "POST /input " + raw.length + "ev", 200, sent < expected ? "sent " + sent + "/" + expected : void 0);
22997
+ return new Response(JSON.stringify({ sent, expected }), { headers: { "Content-Type": "application/json" } });
22998
+ }
22558
22999
  if (req.method === "POST" && path === "/exec") {
22559
23000
  let out;
22560
23001
  let cmd;