quickwin 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.en.md +1 -2
  2. package/README.md +1 -2
  3. package/constants.ts +22 -0
  4. package/enum_map.d.ts +4 -0
  5. package/examples/PdfCanvas.js +1 -1
  6. package/examples/PdfCanvas.tsx +2 -2
  7. package/examples/execd/main.js +491 -217
  8. package/examples/pdf_preview2.js +76 -67
  9. package/examples/pdf_preview2.ts +84 -64
  10. package/examples/pdf_viewer.js +4932 -1029
  11. package/examples/pdf_viewer.tsx +11 -22
  12. package/examples/test_gallery.js +308 -143
  13. package/examples/test_gallery.tsx +12 -7
  14. package/examples/test_react_lazy.js +295 -133
  15. package/examples/test_react_lazy.tsx +4 -3
  16. package/examples/test_react_listbox.js +293 -132
  17. package/examples/test_react_listbox.tsx +3 -2
  18. package/examples/test_root_window.js +283 -126
  19. package/examples/test_tab.js +295 -133
  20. package/examples/test_tab.tsx +4 -3
  21. package/examples/tray_demo.js +37 -30
  22. package/examples/tray_demo.tsx +39 -32
  23. package/lib/bitmap.js +40 -0
  24. package/lib/bitmap.ts +39 -0
  25. package/lib/certs.js +31 -3
  26. package/lib/certs.ts +32 -3
  27. package/lib/dpi.js +30 -0
  28. package/lib/dpi.ts +31 -0
  29. package/lib/dumpRects.js +14 -7
  30. package/lib/dumpRects.ts +14 -6
  31. package/lib/ffi/bind.js +5 -4
  32. package/lib/ffi/bind.ts +9 -8
  33. package/lib/http-server.js +50 -25
  34. package/lib/http-server.ts +51 -23
  35. package/lib/react-qw/components/DateTimePicker.js +6 -7
  36. package/lib/react-qw/components/Input.js +5 -1
  37. package/lib/react-qw/components/ListView.js +8 -6
  38. package/lib/react-qw/components/ScrollView.js +28 -22
  39. package/lib/react-qw/index.js +7 -5
  40. package/lib/react-qw/index.ts +5 -5
  41. package/lib/react-qw/props.js +3 -3
  42. package/lib/react-qw/props.ts +3 -3
  43. package/lib/react-qw/reconciler.js +12 -17
  44. package/lib/react-qw/reconciler.ts +12 -16
  45. package/lib/text-measure.js +9 -6
  46. package/lib/text-measure.ts +9 -6
  47. package/lib/windows/comctl32.js +3 -2
  48. package/lib/windows/comctl32.ts +3 -2
  49. package/lib/windows/gdi32.js +28 -6
  50. package/lib/windows/gdi32.ts +30 -6
  51. package/lib/windows/kernel32.js +9 -0
  52. package/lib/windows/kernel32.ts +9 -0
  53. package/lib/windows/shell32.js +11 -2
  54. package/lib/windows/shell32.ts +13 -2
  55. package/lib/windows/structs.js +51 -0
  56. package/lib/windows/structs.ts +55 -0
  57. package/lib/windows/user32.js +6 -5
  58. package/lib/windows/user32.ts +6 -5
  59. package/main.js +13 -5
  60. package/package.json +2 -2
  61. package/quickwin.d.ts +13 -115
  62. package/qwin-nowasm-x86.exe +0 -0
  63. package/qwin-nowasm.exe +0 -0
  64. package/qwin-x86.exe +0 -0
  65. package/qwin.exe +0 -0
  66. package/test/bench_ffi_callraw.js +3 -4
  67. package/test/bench_ffi_callraw.ts +3 -4
  68. package/test/debug/mupdf_debug.js +4 -22
  69. package/test/debug/wasm_export_debug.js +2 -12
  70. package/test/debug/wasm_names.js +3 -13
  71. package/test/example.pdf +0 -0
  72. package/test/mupdf-cdn.js +40 -0
  73. package/test/mupdf-cdn.ts +43 -0
  74. package/test/test_ffi.js +8 -9
  75. package/test/test_ffi.ts +8 -9
  76. package/test/test_ffi_abi.js +6 -6
  77. package/test/test_ffi_abi.ts +8 -8
  78. package/test/test_ffi_windows.js +82 -11
  79. package/test/test_ffi_windows.ts +85 -11
  80. package/test/test_gdi_draw.js +3 -3
  81. package/test/test_gdi_draw.ts +4 -4
  82. package/test/test_mupdf_render.js +4 -22
  83. package/test/test_mupdf_render.ts +4 -23
  84. package/test/test_mupdf_twice.js +4 -19
  85. package/test/test_mupdf_twice.ts +4 -20
  86. package/test/test_mupdf_wasm.js +10 -4
  87. package/test/test_mupdf_wasm.ts +6 -4
  88. package/test/test_react_complex.js +316 -140
  89. package/test/test_react_counter.js +295 -133
  90. package/test/test_react_flex.js +297 -138
  91. package/test/test_react_hidden.js +296 -134
  92. package/test/test_react_listview_link.js +288 -131
  93. package/test/test_react_notify.js +290 -133
  94. package/test/test_react_render.js +295 -133
  95. package/vendor/mupdf-wasm/mupdf-wasm.d.ts +0 -571
  96. package/vendor/mupdf-wasm/mupdf-wasm.js +0 -2749
  97. package/vendor/mupdf-wasm/mupdf-wasm.wasm +0 -0
  98. package/vendor/mupdf-wasm/mupdf.d.ts +0 -939
  99. package/vendor/mupdf-wasm/mupdf.js +0 -3317
@@ -1367,9 +1367,9 @@ var require_scheduler_development = __commonJS({
1367
1367
  }
1368
1368
  return first;
1369
1369
  }
1370
- function compare(a2, b8) {
1371
- var diff = a2.sortIndex - b8.sortIndex;
1372
- return 0 !== diff ? diff : a2.id - b8.id;
1370
+ function compare(a2, b9) {
1371
+ var diff = a2.sortIndex - b9.sortIndex;
1372
+ return 0 !== diff ? diff : a2.id - b9.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, b8 = alternate; ; ) {
1670
+ for (var a2 = fiber, b9 = 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
- b8 = parentA.return;
1676
- if (null !== b8) {
1677
- a2 = b8;
1675
+ b9 = parentA.return;
1676
+ if (null !== b9) {
1677
+ a2 = b9;
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 === b8) return assertIsMounted(parentA), alternate;
1685
+ if (parentB === b9) 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 !== b8.return) a2 = parentA, b8 = parentB;
1690
+ if (a2.return !== b9.return) a2 = parentA, b9 = 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
- b8 = parentB;
1696
+ b9 = parentB;
1697
1697
  break;
1698
1698
  }
1699
- if (_child === b8) {
1699
+ if (_child === b9) {
1700
1700
  didFindChild = true;
1701
- b8 = parentA;
1701
+ b9 = 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
- b8 = parentA;
1712
+ b9 = parentA;
1713
1713
  break;
1714
1714
  }
1715
- if (_child === b8) {
1715
+ if (_child === b9) {
1716
1716
  didFindChild = true;
1717
- b8 = parentB;
1717
+ b9 = 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 !== b8)
1729
+ if (a2.alternate !== b9)
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, b8, c2, d2) {
15074
+ exports2.discreteUpdates = function(fn, a2, b9, c2, d2) {
15075
15075
  var prevTransition = ReactSharedInternals.T, previousPriority = getCurrentUpdatePriority();
15076
15076
  try {
15077
- return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2, b8, c2, d2);
15077
+ return setCurrentUpdatePriority(2), ReactSharedInternals.T = null, fn(a2, b9, c2, d2);
15078
15078
  } finally {
15079
15079
  setCurrentUpdatePriority(previousPriority), ReactSharedInternals.T = prevTransition, executionContext === NoContext && (workInProgressRootRenderTargetTime = now$1() + RENDER_TIMEOUT_MS);
15080
15080
  }
@@ -15514,7 +15514,7 @@ var URLSearchParamsImpl = class {
15514
15514
  this._list.push([key, value]);
15515
15515
  }
15516
15516
  sort() {
15517
- this._list.sort(([a2], [b8]) => a2 < b8 ? -1 : a2 > b8 ? 1 : 0);
15517
+ this._list.sort(([a2], [b9]) => a2 < b9 ? -1 : a2 > b9 ? 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 b8 = new _URLImpl(base);
15567
+ const b9 = new _URLImpl(base);
15568
15568
  if (p2.host) {
15569
- p2.scheme = b8._scheme;
15569
+ p2.scheme = b9._scheme;
15570
15570
  this._apply(p2);
15571
15571
  return;
15572
15572
  }
15573
15573
  if (!p2.path && !p2.query) {
15574
15574
  this._apply({
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,
15575
+ scheme: b9._scheme,
15576
+ user: b9._username,
15577
+ pass: b9._password,
15578
+ host: b9._hostname,
15579
+ port: b9._port,
15580
+ path: b9._pathname,
15581
+ query: b9._query,
15582
15582
  fragment: p2.fragment || ""
15583
15583
  });
15584
15584
  return;
15585
15585
  }
15586
- p2.scheme = b8._scheme;
15586
+ p2.scheme = b9._scheme;
15587
15587
  if (!p2.user)
15588
- p2.user = b8._username;
15588
+ p2.user = b9._username;
15589
15589
  if (!p2.pass)
15590
- p2.pass = b8._password;
15590
+ p2.pass = b9._password;
15591
15591
  if (!p2.host)
15592
- p2.host = b8._hostname;
15592
+ p2.host = b9._hostname;
15593
15593
  if (!p2.port)
15594
- p2.port = b8._port;
15594
+ p2.port = b9._port;
15595
15595
  if (!p2.fragment)
15596
15596
  p2.fragment = "";
15597
15597
  if (p2.path && !p2.path.startsWith("/")) {
15598
- const bd = b8._pathname.substring(0, b8._pathname.lastIndexOf("/") + 1);
15598
+ const bd = b9._pathname.substring(0, b9._pathname.lastIndexOf("/") + 1);
15599
15599
  p2.path = _normalizePath(bd + p2.path);
15600
15600
  } else if (!p2.path) {
15601
- p2.path = b8._pathname;
15601
+ p2.path = b9._pathname;
15602
15602
  if (!p2.query)
15603
- p2.query = b8._query;
15603
+ p2.query = b9._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 b8 = buf[i2++];
15709
- if (b8 < 128) {
15710
- out += String.fromCharCode(b8);
15708
+ const b9 = buf[i2++];
15709
+ if (b9 < 128) {
15710
+ out += String.fromCharCode(b9);
15711
15711
  continue;
15712
15712
  }
15713
- if (b8 < 192) {
15713
+ if (b9 < 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 (b8 < 224) {
15720
+ if (b9 < 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 = (b8 & 31) << 6 | b22 & 63;
15732
+ c2 = (b9 & 31) << 6 | b22 & 63;
15733
15733
  min = 128;
15734
- } else if (b8 < 240) {
15734
+ } else if (b9 < 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 = (b8 & 15) << 12 | (b22 & 63) << 6 | b32 & 63;
15747
+ c2 = (b9 & 15) << 12 | (b22 & 63) << 6 | b32 & 63;
15748
15748
  min = 2048;
15749
- } else if (b8 < 248) {
15749
+ } else if (b9 < 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 = (b8 & 7) << 18 | (b22 & 63) << 12 | (b32 & 63) << 6 | b42 & 63;
15763
+ c2 = (b9 & 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, b8 = h1, c2 = h2, d2 = h3, e2 = h4;
15943
+ let a2 = h0, b9 = 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 = b8 & c2 | ~b8 & d2;
15947
+ f2 = b9 & c2 | ~b9 & d2;
15948
15948
  k2 = 1518500249;
15949
15949
  } else if (t2 < 40) {
15950
- f2 = b8 ^ c2 ^ d2;
15950
+ f2 = b9 ^ c2 ^ d2;
15951
15951
  k2 = 1859775393;
15952
15952
  } else if (t2 < 60) {
15953
- f2 = b8 & c2 | b8 & d2 | c2 & d2;
15953
+ f2 = b9 & c2 | b9 & d2 | c2 & d2;
15954
15954
  k2 = 2400959708;
15955
15955
  } else {
15956
- f2 = b8 ^ c2 ^ d2;
15956
+ f2 = b9 ^ 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(b8, 30);
15963
- b8 = a2;
15962
+ c2 = rotl(b9, 30);
15963
+ b9 = a2;
15964
15964
  a2 = temp;
15965
15965
  }
15966
15966
  h0 = h0 + a2 >>> 0;
15967
- h1 = h1 + b8 >>> 0;
15967
+ h1 = h1 + b9 >>> 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 b8 = u((e4) => {
17516
+ const b9 = 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 b8;
17586
+ return b9;
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 b8;
17593
+ return b9;
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 b8() {
17604
+ function b9() {
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 && b8();
17611
+ d2 || Rr(n2._readableStreamController, t4), f2 || Rr(i2._readableStreamController, r3), s2 = false, l2 && b9();
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, 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];
17635
+ return n2 = Dr(S2, b9, m2), i2 = Dr(S2, b9, 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 b8;
17944
+ let b9;
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
- b8 = e3;
18008
+ b9 = 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 ? b8(i2.start(this._transformStreamController)) : b8(void 0);
18024
+ })(this, i2), void 0 !== i2.start ? b9(i2.start(this._transformStreamController)) : b9(void 0);
18025
18025
  }
18026
18026
  get readable() {
18027
18027
  if (!ro(this)) throw _o("readable");
@@ -18535,6 +18535,8 @@ function concatU8(parts) {
18535
18535
  return out;
18536
18536
  }
18537
18537
  function toArrayBuffer(u8) {
18538
+ if (u8.byteOffset === 0 && u8.byteLength === u8.buffer.byteLength)
18539
+ return u8.buffer;
18538
18540
  return u8.buffer.slice(u8.byteOffset, u8.byteOffset + u8.byteLength);
18539
18541
  }
18540
18542
  function findCrLfCrLf(buf) {
@@ -18694,6 +18696,7 @@ var HttpServer = class {
18694
18696
  const c2 = {
18695
18697
  sock: ac.handle,
18696
18698
  parts: [],
18699
+ partsLen: 0,
18697
18700
  pending: null,
18698
18701
  current: null,
18699
18702
  outQueue: null,
@@ -18732,7 +18735,9 @@ function onRead(c2) {
18732
18735
  const d2 = sock.recv(c2.sock, 8192);
18733
18736
  if (!d2)
18734
18737
  break;
18735
- c2.parts.push(new Uint8Array(d2));
18738
+ const u8 = new Uint8Array(d2);
18739
+ c2.parts.push(u8);
18740
+ c2.partsLen += u8.length;
18736
18741
  }
18737
18742
  if (!c2.closed)
18738
18743
  tryProcess(c2);
@@ -18822,11 +18827,17 @@ async function writeStreamingBody(c2, body, chunked, trailer) {
18822
18827
  if (done)
18823
18828
  break;
18824
18829
  if (value && value.byteLength > 0) {
18825
- const frame = chunked ? encodeChunkFrame(value, enc) : value;
18826
- if (!queueSend(c2, frame)) {
18827
- await new Promise((resolve) => {
18828
- c2.resumeRead = resolve;
18829
- });
18830
+ const MAX_SEND = 65536;
18831
+ for (let off = 0; off < value.byteLength; off += MAX_SEND) {
18832
+ const piece = value.byteLength <= MAX_SEND ? value : value.subarray(off, Math.min(off + MAX_SEND, value.byteLength));
18833
+ const frame = chunked ? encodeChunkFrame(piece, enc) : piece;
18834
+ if (!queueSend(c2, frame)) {
18835
+ await new Promise((resolve) => {
18836
+ c2.resumeRead = resolve;
18837
+ });
18838
+ }
18839
+ if (c2.closed)
18840
+ break;
18830
18841
  }
18831
18842
  }
18832
18843
  }
@@ -18867,36 +18878,36 @@ function whole(c2) {
18867
18878
  function trimParts(c2, buf, consumed) {
18868
18879
  if (consumed >= buf.length) {
18869
18880
  c2.parts = [];
18881
+ c2.partsLen = 0;
18870
18882
  } else {
18871
18883
  c2.parts = [buf.subarray(consumed)];
18884
+ c2.partsLen = buf.length - consumed;
18872
18885
  }
18873
18886
  }
18874
18887
  function tryProcess(c2) {
18875
18888
  if (c2.closed || c2.current)
18876
18889
  return;
18877
- const buf = whole(c2);
18878
18890
  if (c2.pending) {
18879
18891
  const bodyStart2 = c2.pending.bodyStart;
18880
18892
  const parsed2 = c2.pending.parsed;
18881
- let body;
18882
- let end;
18883
- if (parsed2.chunked) {
18884
- const dec = decodeChunked(buf, bodyStart2);
18885
- if (!dec)
18886
- return;
18887
- body = dec.data;
18888
- end = dec.end;
18889
- } else {
18890
- const needed = parsed2.contentLength;
18891
- if (bodyStart2 + needed > buf.length)
18893
+ if (!parsed2.chunked) {
18894
+ const end = bodyStart2 + parsed2.contentLength;
18895
+ if (end > c2.partsLen)
18892
18896
  return;
18893
- body = buf.subarray(bodyStart2, bodyStart2 + needed);
18894
- end = bodyStart2 + needed;
18897
+ const buf3 = whole(c2);
18898
+ c2.pending = null;
18899
+ dispatchRequest(c2, parsed2, buf3.subarray(bodyStart2, end), end, buf3);
18900
+ return;
18895
18901
  }
18902
+ const buf2 = whole(c2);
18903
+ const dec = decodeChunked(buf2, bodyStart2);
18904
+ if (!dec)
18905
+ return;
18896
18906
  c2.pending = null;
18897
- dispatchRequest(c2, parsed2, body, end);
18907
+ dispatchRequest(c2, parsed2, dec.data, dec.end, buf2);
18898
18908
  return;
18899
18909
  }
18910
+ const buf = whole(c2);
18900
18911
  const headerEnd = findCrLfCrLf(buf);
18901
18912
  if (headerEnd < 0)
18902
18913
  return;
@@ -18914,18 +18925,18 @@ function tryProcess(c2) {
18914
18925
  c2.pending = { parsed, bodyStart };
18915
18926
  return;
18916
18927
  }
18917
- dispatchRequest(c2, parsed, dec.data, dec.end);
18928
+ dispatchRequest(c2, parsed, dec.data, dec.end, buf);
18918
18929
  } else if (parsed.contentLength > 0) {
18919
18930
  if (bodyStart + parsed.contentLength > buf.length) {
18920
18931
  c2.pending = { parsed, bodyStart };
18921
18932
  return;
18922
18933
  }
18923
- dispatchRequest(c2, parsed, buf.subarray(bodyStart, bodyStart + parsed.contentLength), bodyStart + parsed.contentLength);
18934
+ dispatchRequest(c2, parsed, buf.subarray(bodyStart, bodyStart + parsed.contentLength), bodyStart + parsed.contentLength, buf);
18924
18935
  } else {
18925
- dispatchRequest(c2, parsed, new Uint8Array(0), bodyStart);
18936
+ dispatchRequest(c2, parsed, new Uint8Array(0), bodyStart, buf);
18926
18937
  }
18927
18938
  }
18928
- function dispatchRequest(c2, parsed, body, end) {
18939
+ function dispatchRequest(c2, parsed, body, end, wholeBuf) {
18929
18940
  const connHeader = (parsed.headers["connection"] || "").toLowerCase();
18930
18941
  if (parsed.version === "HTTP/1.1")
18931
18942
  c2.keepAlive = connHeader.indexOf("close") < 0;
@@ -18948,7 +18959,7 @@ function dispatchRequest(c2, parsed, body, end) {
18948
18959
  });
18949
18960
  c2.ac = ac;
18950
18961
  c2.current = { req };
18951
- trimParts(c2, whole(c2), end);
18962
+ trimParts(c2, wholeBuf ?? whole(c2), end);
18952
18963
  void handleRequest(c2);
18953
18964
  }
18954
18965
  async function handleRequest(c2) {
@@ -19047,7 +19058,6 @@ async function sendResponse(c2, method, res) {
19047
19058
  // _build/examples/execd/main.js
19048
19059
  import * as os7 from "os";
19049
19060
  import * as std2 from "std";
19050
- import * as gui19 from "gui";
19051
19061
 
19052
19062
  // _build/lib/exec-log.js
19053
19063
  var RequestLog = class {
@@ -19070,7 +19080,7 @@ var RequestLog = class {
19070
19080
  };
19071
19081
 
19072
19082
  // _build/lib/react-qw/index.js
19073
- import * as gui17 from "gui";
19083
+ import * as gui16 from "gui";
19074
19084
 
19075
19085
  // _build/lib/windows/user32.js
19076
19086
  import * as os4 from "os";
@@ -19079,7 +19089,6 @@ import * as os4 from "os";
19079
19089
  import * as ffi from "ffi";
19080
19090
  import * as os3 from "os";
19081
19091
  import * as std from "std";
19082
- import * as win from "win";
19083
19092
 
19084
19093
  // _build/lib/ffi/ctype.js
19085
19094
  import { bufferPtr } from "ffi";
@@ -19247,7 +19256,7 @@ function loadDll(dll) {
19247
19256
  const cached = _dllCache.get(dll);
19248
19257
  if (cached !== void 0)
19249
19258
  return cached;
19250
- const loaded = win.LoadLibrary(dll);
19259
+ const loaded = ffi.LoadLibrary(dll);
19251
19260
  if (!loaded)
19252
19261
  throw new Error(`ffi-bind: LoadLibrary("${dll}") failed`);
19253
19262
  _dllCache.set(dll, loaded);
@@ -19457,7 +19466,7 @@ var BYTE = {
19457
19466
  };
19458
19467
  var builtinCodecs = { WCHAR, BYTE };
19459
19468
  function bind2(dll, name, sig, encoders, decoders) {
19460
- const proc = win.GetProcAddress(loadDll(dll), name);
19469
+ const proc = ffi.GetProcAddress(loadDll(dll), name);
19461
19470
  if (!proc)
19462
19471
  throw new Error(`ffi-bind: proc "${name}" not found in ${dll}`);
19463
19472
  const effDec = decoders ?? encoders;
@@ -19566,13 +19575,13 @@ function lower(v2) {
19566
19575
  type: { tag: "array", elementType: el.type, elementSize: el.size }
19567
19576
  };
19568
19577
  }
19569
- const b8 = /^([A-Za-z_]\w*):(\d+)$/.exec(v2);
19570
- if (b8) {
19571
- const rawUnit = b8[1];
19578
+ const b9 = /^([A-Za-z_]\w*):(\d+)$/.exec(v2);
19579
+ if (b9) {
19580
+ const rawUnit = b9[1];
19572
19581
  const unit = normToken(rawUnit);
19573
19582
  if (!isCNumberToken(unit) || unit === "f32" || unit === "f64")
19574
19583
  throw new Error(`ffi-struct: bitfield unit must be an integer type, got "${rawUnit}"`);
19575
- const width = Number(b8[2]);
19584
+ const width = Number(b9[2]);
19576
19585
  const s3 = SizeAlign[unit];
19577
19586
  const cap = s3 * 8;
19578
19587
  if (!Number.isInteger(width) || width < 1)
@@ -19931,10 +19940,10 @@ function structArray(def) {
19931
19940
  })
19932
19941
  };
19933
19942
  }
19934
- function struct(a2, b8, c2) {
19943
+ function struct(a2, b9, c2) {
19935
19944
  const isNamed = typeof a2 === "string";
19936
- const raw = isNamed ? b8 : a2;
19937
- const opts = isNamed ? c2 : b8;
19945
+ const raw = isNamed ? b9 : a2;
19946
+ const opts = isNamed ? c2 : b9;
19938
19947
  return createStruct(buildDecl("struct", raw, opts?.pack));
19939
19948
  }
19940
19949
 
@@ -19959,6 +19968,17 @@ var SIZE_DECL = {
19959
19968
  cy: "i32"
19960
19969
  };
19961
19970
  var SIZE = /* @__PURE__ */ struct("SIZE", SIZE_DECL);
19971
+ var SCROLLINFO_DECL = {
19972
+ "#": "struct",
19973
+ cbSize: "u32",
19974
+ fMask: "u32",
19975
+ nMin: "i32",
19976
+ nMax: "i32",
19977
+ nPage: "u32",
19978
+ nPos: "i32",
19979
+ nTrackPos: "i32"
19980
+ };
19981
+ var SCROLLINFO = /* @__PURE__ */ struct("SCROLLINFO", SCROLLINFO_DECL);
19962
19982
  var LOGFONTW_DECL = {
19963
19983
  "#": "struct",
19964
19984
  lfHeight: "i32",
@@ -19977,6 +19997,26 @@ var LOGFONTW_DECL = {
19977
19997
  lfFaceName: "u16[32]@utf-16le"
19978
19998
  };
19979
19999
  var LOGFONTW = /* @__PURE__ */ struct("LOGFONTW", LOGFONTW_DECL);
20000
+ var NONCLIENTMETRICSW_DECL = {
20001
+ "#": "struct",
20002
+ cbSize: "u32",
20003
+ iBorderWidth: "i32",
20004
+ iScrollWidth: "i32",
20005
+ iScrollHeight: "i32",
20006
+ iCaptionWidth: "i32",
20007
+ iCaptionHeight: "i32",
20008
+ lfCaptionFont: LOGFONTW_DECL,
20009
+ iSmCaptionWidth: "i32",
20010
+ iSmCaptionHeight: "i32",
20011
+ lfSmCaptionFont: LOGFONTW_DECL,
20012
+ iMenuWidth: "i32",
20013
+ iMenuHeight: "i32",
20014
+ lfMenuFont: LOGFONTW_DECL,
20015
+ lfStatusFont: LOGFONTW_DECL,
20016
+ lfMessageFont: LOGFONTW_DECL,
20017
+ iPaddedBorderWidth: "i32"
20018
+ };
20019
+ var NONCLIENTMETRICSW = /* @__PURE__ */ struct("NONCLIENTMETRICSW", NONCLIENTMETRICSW_DECL);
19980
20020
  var BITMAPINFOHEADER_DECL = {
19981
20021
  "#": "struct",
19982
20022
  biSize: "u32",
@@ -20268,6 +20308,7 @@ var NOTIFYICONIDENTIFIER = /* @__PURE__ */ struct("NOTIFYICONIDENTIFIER", NOTIFY
20268
20308
  var b2 = (name, sig, encoders) => bind2("user32.dll", name, sig, encoders);
20269
20309
  var _bProbe = b2("GetDesktopWindow", " -> <HWND>ptr");
20270
20310
  var LONG_PTR_SYM = os4.arch === "x64" ? "PtrW" : "W";
20311
+ var ShowWindow = /* @__PURE__ */ b2("ShowWindow", "<HWND>ptr i32@ShowWindowCmd -> i32");
20271
20312
  var SetWindowPos = /* @__PURE__ */ b2("SetWindowPos", "<HWND>ptr <>ptr@SetWindowPosHwnd i32 i32 i32 i32 u32 -> i32");
20272
20313
  var GetWindowRect = /* @__PURE__ */ b2("GetWindowRect", "<HWND>ptr <RECT>ptr -> i32");
20273
20314
  var GetClientRect = /* @__PURE__ */ b2("GetClientRect", "<HWND>ptr <RECT>ptr -> i32");
@@ -20278,6 +20319,7 @@ var FindWindow = /* @__PURE__ */ b2("FindWindowW", "<WCHAR>ptr <WCHAR>ptr -> <HW
20278
20319
  var FindWindowEx = /* @__PURE__ */ b2("FindWindowExW", "<HWND>ptr <HWND>ptr <WCHAR>ptr <WCHAR>ptr -> <HWND>ptr");
20279
20320
  var GetWindowText = /* @__PURE__ */ b2("GetWindowTextW", "<HWND>ptr <BYTE>ptr i32 -> i32");
20280
20321
  var SetWindowText = /* @__PURE__ */ b2("SetWindowTextW", "<HWND>ptr <WCHAR>ptr -> i32");
20322
+ var GetWindowTextLength = /* @__PURE__ */ b2("GetWindowTextLengthW", "<HWND>ptr -> i32");
20281
20323
  var GetClassName = /* @__PURE__ */ b2("GetClassNameW", "<HWND>ptr <BYTE>ptr i32 -> i32");
20282
20324
  var GetWindowLongPtr = /* @__PURE__ */ b2("GetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp -> <>ptr");
20283
20325
  var SetWindowLongPtr = /* @__PURE__ */ b2("SetWindowLong" + LONG_PTR_SYM, "<HWND>ptr i32@Gwlp <>ptr -> <>ptr");
@@ -20291,6 +20333,7 @@ var ReleaseDC = /* @__PURE__ */ b2("ReleaseDC", "<HWND>ptr <HDC>ptr! -> i32");
20291
20333
  var PrintWindow = /* @__PURE__ */ b2("PrintWindow", "<HWND>ptr <HDC>ptr! u32 -> i32");
20292
20334
  var DrawText = /* @__PURE__ */ b2("DrawTextW", "<HDC>ptr! <WCHAR>ptr i32 <RECT>ptr i32 -> i32");
20293
20335
  var InvalidateRect = /* @__PURE__ */ b2("InvalidateRect", "<HWND>ptr <RECT>ptr i32 -> i32", { RECT });
20336
+ var UpdateWindow = /* @__PURE__ */ b2("UpdateWindow", "<HWND>ptr -> i32");
20294
20337
  var SetCursor = /* @__PURE__ */ b2("SetCursor", "<HCURSOR>ptr -> <HCURSOR>ptr");
20295
20338
  var LoadCursor = /* @__PURE__ */ b2("LoadCursorW", "<HMODULE>ptr <>ptr -> <HCURSOR>ptr");
20296
20339
  var GetCursorPos = /* @__PURE__ */ b2("GetCursorPos", "<POINT>ptr -> i32");
@@ -20298,8 +20341,11 @@ var ScreenToClient = /* @__PURE__ */ b2("ScreenToClient", "<HWND>ptr <POINT>ptr
20298
20341
  var ClientToScreen = /* @__PURE__ */ b2("ClientToScreen", "<HWND>ptr <POINT>ptr -> i32");
20299
20342
  var INPUTArr = /* @__PURE__ */ structArray(INPUT);
20300
20343
  var SendInput = /* @__PURE__ */ b2("SendInput", "u32 <INPUT>ptr i32 -> u32", { INPUT: INPUTArr });
20344
+ var SetScrollInfo = /* @__PURE__ */ b2("SetScrollInfo", "<HWND>ptr u32 <SCROLLINFO>ptr i32 -> i32", { SCROLLINFO });
20345
+ var GetScrollInfo = /* @__PURE__ */ b2("GetScrollInfo", "<HWND>ptr u32 <SCROLLINFO>ptr -> i32");
20301
20346
  var ShowScrollBar = /* @__PURE__ */ b2("ShowScrollBar", "<HWND>ptr u32 i32 -> i32");
20302
20347
  var GetSystemMetrics = /* @__PURE__ */ b2("GetSystemMetrics", "i32 -> i32");
20348
+ var SystemParametersInfo = /* @__PURE__ */ b2("SystemParametersInfoW", "u32 u32 <BYTE>ptr u32 -> i32");
20303
20349
  var EnumWindows = /* @__PURE__ */ b2("EnumWindows", "<>ptr <>ptr -> i32");
20304
20350
  var EnumDisplaySettings = /* @__PURE__ */ b2("EnumDisplaySettingsW", "<WCHAR>ptr u32 <DEVMODEW>ptr -> i32");
20305
20351
  var ChangeDisplaySettings = /* @__PURE__ */ b2("ChangeDisplaySettingsW", "<DEVMODEW>ptr u32 -> i32");
@@ -20320,10 +20366,35 @@ var CreateCompatibleDC = /* @__PURE__ */ b3("CreateCompatibleDC", "<HDC>ptr -> <
20320
20366
  var CreateCompatibleBitmap = /* @__PURE__ */ b3("CreateCompatibleBitmap", "<HDC>ptr! i32 i32 -> <HGDIOBJ>ptr");
20321
20367
  var SelectObject = /* @__PURE__ */ b3("SelectObject", "<HDC>ptr! <HGDIOBJ>ptr -> <HGDIOBJ>ptr");
20322
20368
  var BitBlt = /* @__PURE__ */ b3("BitBlt", "<HDC>ptr! i32 i32 i32 i32 <HDC>ptr i32 i32 u32@RasterOp -> i32");
20323
- var GetDIBits = /* @__PURE__ */ b3("GetDIBits", "<HDC>ptr! <HGDIOBJ>ptr u32 u32 <BYTE>ptr <>ptr u32 -> i32");
20369
+ var GetDIBits = /* @__PURE__ */ b3("GetDIBits", "<HDC>ptr! <HGDIOBJ>ptr u32 u32 <BYTE>ptr <>ptr u32@ColorUse -> i32");
20370
+ var CreateDIBSection = /* @__PURE__ */ b3("CreateDIBSection", "<HDC>ptr <>ptr u32@ColorUse <>ptr <>ptr u32 -> <HGDIOBJ>ptr");
20371
+ var SetDIBits = /* @__PURE__ */ b3("SetDIBits", "<HDC>ptr <HGDIOBJ>ptr! u32 u32 <BYTE>ptr <>ptr u32@ColorUse -> i32");
20324
20372
  var GetObject = /* @__PURE__ */ b3("GetObjectW", "<HGDIOBJ>ptr i32 <BYTE>ptr -> i32");
20325
20373
  var DeleteDC = /* @__PURE__ */ b3("DeleteDC", "<HDC>ptr! -> i32");
20326
20374
 
20375
+ // _build/lib/dpi.js
20376
+ function getScaleFactor() {
20377
+ const hdc = GetDC(NULL);
20378
+ const dpi = hdc ? GetDeviceCaps(
20379
+ hdc,
20380
+ 88
20381
+ /* DeviceCap.LOGPIXELSX */
20382
+ ) : 96;
20383
+ if (hdc)
20384
+ ReleaseDC(NULL, hdc);
20385
+ return dpi / 96;
20386
+ }
20387
+ function createSystemDpiFont() {
20388
+ const ncm = NONCLIENTMETRICSW.encode({ cbSize: NONCLIENTMETRICSW.size });
20389
+ if (!SystemParametersInfo(41, NONCLIENTMETRICSW.size, ncm, 0)) {
20390
+ const legacySize = NONCLIENTMETRICSW.size - 4;
20391
+ NONCLIENTMETRICSW.encode({ cbSize: legacySize }, ncm);
20392
+ if (!SystemParametersInfo(41, legacySize, ncm, 0))
20393
+ return NULL;
20394
+ }
20395
+ return CreateFontIndirect(NONCLIENTMETRICSW.decode(ncm).lfMessageFont);
20396
+ }
20397
+
20327
20398
  // _build/lib/react-qw/props.js
20328
20399
  import * as gui from "gui";
20329
20400
  function applyProps(instance, newProps, _oldProps) {
@@ -20347,14 +20418,14 @@ function applyProps(instance, newProps, _oldProps) {
20347
20418
  EnableWindow(hwnd, !newProps.disabled ? 1 : 0);
20348
20419
  }
20349
20420
  if ("hidden" in newProps) {
20350
- gui.ShowWindow(
20421
+ ShowWindow(
20351
20422
  hwnd,
20352
20423
  newProps.hidden ? 0 : 5
20353
20424
  /* ShowWindowCmd.SHOW */
20354
20425
  );
20355
20426
  }
20356
20427
  if ("visible" in newProps) {
20357
- gui.ShowWindow(
20428
+ ShowWindow(
20358
20429
  hwnd,
20359
20430
  newProps.visible ? 5 : 0
20360
20431
  /* ShowWindowCmd.HIDE */
@@ -20474,24 +20545,21 @@ function measureTextForHwnd(hwnd, text) {
20474
20545
  if (hFont)
20475
20546
  SelectObject(hdc, oldFont);
20476
20547
  ReleaseDC(hwnd, hdc);
20477
- const wr2 = gui2.GetWindowRect(hwnd);
20478
- const cr2 = gui2.GetClientRect(hwnd);
20479
- if (wr2 && cr2) {
20480
- result.width += wr2.right - wr2.left - (cr2.right - cr2.left);
20481
- result.height += wr2.bottom - wr2.top - (cr2.bottom - cr2.top);
20548
+ const wr2 = RECT.alloc();
20549
+ const cr2 = RECT.alloc();
20550
+ const okWr = GetWindowRect(hwnd, wr2.ptr);
20551
+ const okCr = GetClientRect(hwnd, cr2.ptr);
20552
+ if (okWr && okCr) {
20553
+ const w2 = RECT.decode(wr2), c2 = RECT.decode(cr2);
20554
+ result.width += w2.right - w2.left - (c2.right - c2.left);
20555
+ result.height += w2.bottom - w2.top - (c2.bottom - c2.top);
20482
20556
  }
20483
20557
  return result;
20484
20558
  }
20485
20559
 
20486
20560
  // _build/lib/react-qw/reconciler.js
20487
- var dpiFont = gui3.CreateSystemDpiFont();
20488
- var scaleFactor = (() => {
20489
- const hdc = GetDC(NULL);
20490
- const dpi = hdc ? GetDeviceCaps(hdc, 88) : 96;
20491
- if (hdc)
20492
- ReleaseDC(NULL, hdc);
20493
- return dpi / 96;
20494
- })();
20561
+ var dpiFont = createSystemDpiFont();
20562
+ var scaleFactor = getScaleFactor();
20495
20563
  var DELAYED_CONTROLS = /* @__PURE__ */ new Set(["SysListView32", "SysTreeView32", "LISTBOX", "COMBOBOX", "msctls_trackbar32", "SysDateTimePick32", "SysLink"]);
20496
20564
  function isDelayedControl(winClass) {
20497
20565
  return DELAYED_CONTROLS.has(winClass);
@@ -20537,11 +20605,12 @@ function runFlexLayout(inst) {
20537
20605
  const visible = children.filter((c2) => !c2.props.hidden);
20538
20606
  if (visible.length === 0)
20539
20607
  return;
20540
- const rect = gui3.GetClientRect(inst.hwnd);
20541
- if (!rect) {
20608
+ const rcBuf = RECT.alloc();
20609
+ if (!GetClientRect(inst.hwnd, rcBuf.ptr)) {
20542
20610
  console.log("flex: no rect for", inst.hwnd, inst.type);
20543
20611
  return;
20544
20612
  }
20613
+ const rect = RECT.decode(rcBuf);
20545
20614
  const pw = (rect.right - rect.left) / scaleFactor;
20546
20615
  const ph = (rect.bottom - rect.top) / scaleFactor;
20547
20616
  if (pw <= 0 || ph <= 0) {
@@ -20742,7 +20811,7 @@ var hostConfig = {
20742
20811
  },
20743
20812
  hideInstance(instance) {
20744
20813
  if (instance.hwnd !== null)
20745
- gui3.ShowWindow(
20814
+ ShowWindow(
20746
20815
  instance.hwnd,
20747
20816
  0
20748
20817
  /* ShowWindowCmd.HIDE */
@@ -20750,7 +20819,7 @@ var hostConfig = {
20750
20819
  },
20751
20820
  hideTextInstance(instance) {
20752
20821
  if (instance.hwnd !== null)
20753
- gui3.ShowWindow(
20822
+ ShowWindow(
20754
20823
  instance.hwnd,
20755
20824
  0
20756
20825
  /* ShowWindowCmd.HIDE */
@@ -20758,7 +20827,7 @@ var hostConfig = {
20758
20827
  },
20759
20828
  unhideInstance(instance, _props) {
20760
20829
  if (instance.hwnd !== null)
20761
- gui3.ShowWindow(
20830
+ ShowWindow(
20762
20831
  instance.hwnd,
20763
20832
  5
20764
20833
  /* ShowWindowCmd.SHOW */
@@ -20766,7 +20835,7 @@ var hostConfig = {
20766
20835
  },
20767
20836
  unhideTextInstance(instance, _text) {
20768
20837
  if (instance.hwnd !== null)
20769
- gui3.ShowWindow(
20838
+ ShowWindow(
20770
20839
  instance.hwnd,
20771
20840
  5
20772
20841
  /* ShowWindowCmd.SHOW */
@@ -21013,11 +21082,10 @@ var DateTimePicker = (0, import_react5.forwardRef)(function DateTimePicker2({ va
21013
21082
  if (!h2)
21014
21083
  return;
21015
21084
  InvalidateRect(h2, NULL, 1);
21016
- const cr2 = gui6.GetClientRect(h2);
21017
- if (cr2) {
21018
- const w2 = cr2.right - cr2.left;
21019
- const hh = cr2.bottom - cr2.top;
21020
- gui6.SendMessage(h2, 5, 0, hh << 16 | w2);
21085
+ const cr2 = RECT.alloc();
21086
+ if (GetClientRect(h2, cr2.ptr)) {
21087
+ const { left, top, right, bottom } = RECT.decode(cr2);
21088
+ gui6.SendMessage(h2, 5, 0, bottom - top << 16 | right - left);
21021
21089
  }
21022
21090
  }, []);
21023
21091
  return (0, import_jsx_runtime4.jsx)("w", { type: "STATIC", ws: 268435456 | 33554432, style: { ...style, flexDirection: "column", alignItems: "stretch" }, ref, onEvent: (e2) => {
@@ -21078,7 +21146,10 @@ var Input = (0, import_react6.forwardRef)(({ value: controlledValue, defaultValu
21078
21146
  const h2 = inputRef.current;
21079
21147
  if (!h2)
21080
21148
  return;
21081
- const newText = gui7.GetWindowText(h2);
21149
+ const cap = GetWindowTextLength(h2) + 1;
21150
+ const buf = WCHAR.alloc(cap);
21151
+ GetWindowText(h2, buf, cap);
21152
+ const newText = WCHAR.decode(buf);
21082
21153
  if (!isControlled)
21083
21154
  setInternalValue(newText);
21084
21155
  onChange?.(newText);
@@ -21166,6 +21237,49 @@ var import_jsx_runtime8 = __toESM(require_jsx_runtime(), 1);
21166
21237
  var import_react9 = __toESM(require_react(), 1);
21167
21238
  import * as gui9 from "gui";
21168
21239
  import * as ffi3 from "ffi";
21240
+
21241
+ // _build/lib/bitmap.js
21242
+ function createBitmapFromPixels(width, height, pixels) {
21243
+ if (width <= 0 || height <= 0)
21244
+ return NULL;
21245
+ const len = width * height * 4;
21246
+ if (pixels.byteLength < len)
21247
+ return NULL;
21248
+ const bi = BITMAPINFOHEADER.encode({
21249
+ biSize: BITMAPINFOHEADER.size,
21250
+ biWidth: width,
21251
+ biHeight: -height,
21252
+ biPlanes: 1,
21253
+ biBitCount: 32
21254
+ });
21255
+ const hbm = CreateDIBSection(NULL, bi.ptr, 0, NULL, NULL, 0);
21256
+ if (!hbm)
21257
+ return NULL;
21258
+ const src = new PtrArrayBuffer(len);
21259
+ new Uint8Array(src).set(new Uint8Array(pixels, 0, len));
21260
+ if (SetDIBits(
21261
+ NULL,
21262
+ hbm,
21263
+ 0,
21264
+ height,
21265
+ src,
21266
+ bi.ptr,
21267
+ 0
21268
+ /* ColorUse.RGB_COLORS */
21269
+ ) !== height) {
21270
+ DeleteObject(hbm);
21271
+ return NULL;
21272
+ }
21273
+ return hbm;
21274
+ }
21275
+
21276
+ // _build/lib/windows/comctl32.js
21277
+ var b4 = (name, sig) => bind2("comctl32.dll", name, sig);
21278
+ var ImageListCreate = /* @__PURE__ */ b4("ImageList_Create", "i32 i32 u32 i32 i32 -> <HIMAGELIST>ptr");
21279
+ var ImageListAdd = /* @__PURE__ */ b4("ImageList_Add", "<HIMAGELIST>ptr <HGDIOBJ>ptr <HGDIOBJ>ptr -> i32");
21280
+ var ImageListDestroy = /* @__PURE__ */ b4("ImageList_Destroy", "<HIMAGELIST>ptr -> i32");
21281
+
21282
+ // _build/lib/react-qw/components/ListView.js
21169
21283
  function writeU32(ptr, offset, v2) {
21170
21284
  ffi3.writeByte(ptr + offset, v2 & 255);
21171
21285
  ffi3.writeByte(ptr + offset + 1, v2 >> 8 & 255);
@@ -21255,7 +21369,7 @@ function resolveCellStyle(columns, data, row, colIndex) {
21255
21369
  }
21256
21370
  function makeLVItem(i2, sub, text, image) {
21257
21371
  const textBuf = WCHAR.encode(text);
21258
- const b8 = LVITEMW.encode({
21372
+ const b9 = LVITEMW.encode({
21259
21373
  mask: 1 | (image !== void 0 ? 2 : 0),
21260
21374
  iItem: i2,
21261
21375
  iSubItem: sub,
@@ -21272,32 +21386,32 @@ function makeLVItem(i2, sub, text, image) {
21272
21386
  piColFmt: 0,
21273
21387
  iGroup: 0
21274
21388
  });
21275
- b8.__textBuf = textBuf;
21276
- return b8;
21389
+ b9.__textBuf = textBuf;
21390
+ return b9;
21277
21391
  }
21278
21392
  var ListView = (0, import_react9.forwardRef)(function ListViewInner({ columns, data, style, icons, iconSize, getIcon }, ref) {
21279
21393
  const lvRef = (0, import_react9.useRef)(null);
21280
- const iconListRef = (0, import_react9.useRef)(0);
21394
+ const iconListRef = (0, import_react9.useRef)(NULL);
21281
21395
  (0, import_react9.useEffect)(() => {
21282
21396
  const h2 = lvRef.current;
21283
21397
  if (!h2)
21284
21398
  return;
21285
21399
  const il = iconListRef.current;
21286
- iconListRef.current = 0;
21400
+ iconListRef.current = NULL;
21287
21401
  if (il) {
21288
21402
  gui9.SendMessage(h2, 4099, 1, 0);
21289
- gui9.ImageListDestroy(il);
21403
+ ImageListDestroy(il);
21290
21404
  }
21291
21405
  if (!icons || icons.length === 0)
21292
21406
  return;
21293
21407
  const size = iconSize ?? 32;
21294
- const img = gui9.ImageListCreate(size, size, 32, icons.length, 1);
21408
+ const img = ImageListCreate(size, size, 32, icons.length, 1);
21295
21409
  if (!img)
21296
21410
  return;
21297
21411
  for (const p2 of icons) {
21298
- const hbm = gui9.CreateBitmapFromPixels(size, size, p2);
21412
+ const hbm = createBitmapFromPixels(size, size, p2);
21299
21413
  if (hbm) {
21300
- gui9.ImageListAdd(img, hbm);
21414
+ ImageListAdd(img, hbm, NULL);
21301
21415
  DeleteObject(hbm);
21302
21416
  }
21303
21417
  }
@@ -21478,22 +21592,19 @@ var RadioButton = (0, import_react11.forwardRef)(({ checked: controlledChecked,
21478
21592
  // _build/lib/react-qw/components/ScrollView.js
21479
21593
  var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
21480
21594
  var import_react12 = __toESM(require_react(), 1);
21481
- import * as gui12 from "gui";
21482
21595
  var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth, contentHeight }, ref) => {
21483
21596
  const svRef = (0, import_react12.useRef)(null);
21484
21597
  const contentRef = (0, import_react12.useRef)(null);
21485
21598
  const scrollXRef = (0, import_react12.useRef)(0);
21486
21599
  const scrollYRef = (0, import_react12.useRef)(0);
21487
21600
  function updateScroll(sv, content) {
21488
- const svRect = gui12.GetClientRect(sv);
21489
- if (!svRect)
21601
+ const svBuf = RECT.alloc();
21602
+ if (!GetClientRect(sv, svBuf.ptr))
21490
21603
  return;
21491
- const svW = svRect.right - svRect.left;
21492
- const svH = svRect.bottom - svRect.top;
21493
- const hdc = GetDC(NULL);
21494
- const scale = hdc ? GetDeviceCaps(hdc, 88) / 96 : 1;
21495
- if (hdc)
21496
- ReleaseDC(NULL, hdc);
21604
+ const { left, top, right, bottom } = RECT.decode(svBuf);
21605
+ const svW = right - left;
21606
+ const svH = bottom - top;
21607
+ const scale = getScaleFactor();
21497
21608
  const natW = Math.round((contentWidth ?? svW / scale) * scale);
21498
21609
  const natH = Math.round((contentHeight ?? svH / scale) * scale);
21499
21610
  scrollXRef.current = Math.max(0, Math.min(scrollXRef.current, natW - svW));
@@ -21510,14 +21621,28 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21510
21621
  );
21511
21622
  forceFlexLayout(content);
21512
21623
  if (natW > svW) {
21513
- gui12.SetScrollInfo(sv, 0, { min: 0, max: natW - 1, page: svW, pos: scrollXRef.current }, true);
21624
+ SetScrollInfo(sv, 0, {
21625
+ cbSize: SCROLLINFO.size,
21626
+ fMask: 1 | 2 | 4,
21627
+ nMin: 0,
21628
+ nMax: natW - 1,
21629
+ nPage: svW,
21630
+ nPos: scrollXRef.current
21631
+ }, 1);
21514
21632
  ShowScrollBar(sv, 0, 1);
21515
21633
  } else {
21516
21634
  scrollXRef.current = 0;
21517
21635
  ShowScrollBar(sv, 0, 0);
21518
21636
  }
21519
21637
  if (natH > svH) {
21520
- gui12.SetScrollInfo(sv, 1, { min: 0, max: natH - 1, page: svH, pos: scrollYRef.current }, true);
21638
+ SetScrollInfo(sv, 1, {
21639
+ cbSize: SCROLLINFO.size,
21640
+ fMask: 1 | 2 | 4,
21641
+ nMin: 0,
21642
+ nMax: natH - 1,
21643
+ nPage: svH,
21644
+ nPos: scrollYRef.current
21645
+ }, 1);
21521
21646
  ShowScrollBar(sv, 1, 1);
21522
21647
  } else {
21523
21648
  scrollYRef.current = 0;
@@ -21547,15 +21672,21 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21547
21672
  1 | 4
21548
21673
  /* SetWindowPosFlag.SWP_NOZORDER */
21549
21674
  );
21550
- gui12.SetScrollInfo(sv, bar, { pos: newPos }, true);
21675
+ SetScrollInfo(sv, bar, { cbSize: SCROLLINFO.size, fMask: 4, nPos: newPos }, 1);
21551
21676
  }
21552
21677
  function handleScroll(e2, bar) {
21553
21678
  const sv = svRef.current;
21554
21679
  const content = contentRef.current;
21555
21680
  if (!sv || !content)
21556
21681
  return;
21557
- const info = gui12.GetScrollInfo(sv, bar);
21558
- const maxPos = info.max - info.page + 1;
21682
+ const si = SCROLLINFO.encode({
21683
+ cbSize: SCROLLINFO.size,
21684
+ fMask: 23
21685
+ /* ScrollInfoFlag.ALL */
21686
+ });
21687
+ GetScrollInfo(sv, bar, si.ptr);
21688
+ const info = SCROLLINFO.decode(si);
21689
+ const maxPos = info.nMax - info.nPage + 1;
21559
21690
  const code = e2.wParam & 65535;
21560
21691
  const ref_ = bar === 1 ? scrollYRef : scrollXRef;
21561
21692
  let newPos = ref_.current;
@@ -21566,9 +21697,9 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21566
21697
  else if (code === 1)
21567
21698
  newPos += 20;
21568
21699
  else if (code === 2)
21569
- newPos -= info.page;
21700
+ newPos -= info.nPage;
21570
21701
  else if (code === 3)
21571
- newPos += info.page;
21702
+ newPos += info.nPage;
21572
21703
  else
21573
21704
  return;
21574
21705
  newPos = Math.max(0, Math.min(maxPos, newPos));
@@ -21588,8 +21719,14 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21588
21719
  if (!isHorz && contentHeight === void 0)
21589
21720
  return;
21590
21721
  const bar = isHorz ? 0 : 1;
21591
- const info = gui12.GetScrollInfo(sv, bar);
21592
- const maxPos = info.max - info.page + 1;
21722
+ const si = SCROLLINFO.encode({
21723
+ cbSize: SCROLLINFO.size,
21724
+ fMask: 23
21725
+ /* ScrollInfoFlag.ALL */
21726
+ });
21727
+ GetScrollInfo(sv, bar, si.ptr);
21728
+ const info = SCROLLINFO.decode(si);
21729
+ const maxPos = info.nMax - info.nPage + 1;
21593
21730
  const ref_ = isHorz ? scrollXRef : scrollYRef;
21594
21731
  let newPos = ref_.current + dy;
21595
21732
  newPos = Math.max(0, Math.min(maxPos, newPos));
@@ -21637,7 +21774,7 @@ var ScrollView = (0, import_react12.forwardRef)(({ children, style, contentWidth
21637
21774
  // _build/lib/react-qw/components/Slider.js
21638
21775
  var import_jsx_runtime12 = __toESM(require_jsx_runtime(), 1);
21639
21776
  var import_react13 = __toESM(require_react(), 1);
21640
- import * as gui13 from "gui";
21777
+ import * as gui12 from "gui";
21641
21778
  var Slider = (0, import_react13.forwardRef)(({ value, onChange, min = 0, max = 100, vertical = false, disabled, style }, ref) => {
21642
21779
  const wrapperRef = (0, import_react13.useRef)(null);
21643
21780
  const sliderRef = (0, import_react13.useRef)(null);
@@ -21646,14 +21783,14 @@ var Slider = (0, import_react13.forwardRef)(({ value, onChange, min = 0, max = 1
21646
21783
  if (!h2)
21647
21784
  return;
21648
21785
  const lParam = min & 65535 | (max & 65535) << 16;
21649
- gui13.SendMessage(h2, 1030, 0, lParam);
21650
- gui13.SendMessage(h2, 1029, 1, value);
21786
+ gui12.SendMessage(h2, 1030, 0, lParam);
21787
+ gui12.SendMessage(h2, 1029, 1, value);
21651
21788
  }, [min, max]);
21652
21789
  (0, import_react13.useEffect)(() => {
21653
21790
  const h2 = sliderRef.current;
21654
21791
  if (!h2)
21655
21792
  return;
21656
- gui13.SendMessage(h2, 1029, 1, value);
21793
+ gui12.SendMessage(h2, 1029, 1, value);
21657
21794
  }, [value]);
21658
21795
  const tbStyle = 268435456 | 65536 | 1 | (vertical ? 2 : 0);
21659
21796
  return (0, import_jsx_runtime12.jsx)("w", { type: "STATIC", ws: 268435456 | 33554432, style, ref: (h2) => {
@@ -21670,7 +21807,7 @@ var Slider = (0, import_react13.forwardRef)(({ value, onChange, min = 0, max = 1
21670
21807
  const h2 = sliderRef.current;
21671
21808
  if (!h2)
21672
21809
  return 0;
21673
- const pos = gui13.SendMessage(h2, 1024, 0, 0);
21810
+ const pos = gui12.SendMessage(h2, 1024, 0, 0);
21674
21811
  onChange?.(pos);
21675
21812
  return 0;
21676
21813
  }
@@ -21683,7 +21820,7 @@ var Slider = (0, import_react13.forwardRef)(({ value, onChange, min = 0, max = 1
21683
21820
  // _build/lib/react-qw/components/Tab.js
21684
21821
  var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
21685
21822
  var import_react14 = __toESM(require_react(), 1);
21686
- import * as gui14 from "gui";
21823
+ import * as gui13 from "gui";
21687
21824
  var Tab = (0, import_react14.forwardRef)(({ tabs, selectedIndex: controlledIndex, defaultSelectedIndex = 0, onChange, style }, ref) => {
21688
21825
  const [internalIndex, setInternalIndex] = (0, import_react14.useState)(defaultSelectedIndex);
21689
21826
  const isControlled = controlledIndex !== void 0;
@@ -21693,7 +21830,7 @@ var Tab = (0, import_react14.forwardRef)(({ tabs, selectedIndex: controlledIndex
21693
21830
  const h2 = tabHwnd.current;
21694
21831
  if (!h2)
21695
21832
  return;
21696
- gui14.SendMessage(h2, 4873, 0, 0);
21833
+ gui13.SendMessage(h2, 4873, 0, 0);
21697
21834
  for (let i2 = 0; i2 < tabs.length; i2++) {
21698
21835
  const titleBuf = WCHAR.encode(tabs[i2].title);
21699
21836
  const tci = TCITEMW.encode({
@@ -21706,14 +21843,14 @@ var Tab = (0, import_react14.forwardRef)(({ tabs, selectedIndex: controlledIndex
21706
21843
  lParam: 0
21707
21844
  });
21708
21845
  const tciPtr = tci.ptr;
21709
- gui14.SendMessage(h2, 4926, i2, tciPtr);
21846
+ gui13.SendMessage(h2, 4926, i2, tciPtr);
21710
21847
  }
21711
- gui14.SendMessage(h2, 4876, sel, 0);
21848
+ gui13.SendMessage(h2, 4876, sel, 0);
21712
21849
  }, [tabs]);
21713
21850
  (0, import_react14.useEffect)(() => {
21714
21851
  const h2 = tabHwnd.current;
21715
21852
  if (h2)
21716
- gui14.SendMessage(h2, 4876, sel, 0);
21853
+ gui13.SendMessage(h2, 4876, sel, 0);
21717
21854
  }, [sel]);
21718
21855
  return (0, import_jsx_runtime13.jsxs)("w", { type: "STATIC", ws: 268435456 | 33554432, style: { ...style, flexDirection: "column", alignItems: "stretch" }, ref, onEvent: (e2) => {
21719
21856
  if (e2.msg === 78) {
@@ -21722,7 +21859,7 @@ var Tab = (0, import_react14.forwardRef)(({ tabs, selectedIndex: controlledIndex
21722
21859
  return;
21723
21860
  const code = nmCode(e2.lParam);
21724
21861
  if (code === -552 || code === -2) {
21725
- const newSel = gui14.SendMessage(h2, 4875, 0, 0);
21862
+ const newSel = gui13.SendMessage(h2, 4875, 0, 0);
21726
21863
  if (newSel !== sel) {
21727
21864
  if (!isControlled)
21728
21865
  setInternalIndex(newSel);
@@ -21735,12 +21872,12 @@ var Tab = (0, import_react14.forwardRef)(({ tabs, selectedIndex: controlledIndex
21735
21872
 
21736
21873
  // _build/lib/react-qw/components/Tooltip.js
21737
21874
  var import_react15 = __toESM(require_react(), 1);
21738
- import * as gui15 from "gui";
21875
+ import * as gui14 from "gui";
21739
21876
 
21740
21877
  // _build/lib/react-qw/components/TreeView.js
21741
21878
  var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
21742
21879
  var import_react16 = __toESM(require_react(), 1);
21743
- import * as gui16 from "gui";
21880
+ import * as gui15 from "gui";
21744
21881
  function buildTvItem(textPtr, cChildren) {
21745
21882
  let mask = 1;
21746
21883
  if (cChildren > 0)
@@ -21765,20 +21902,20 @@ function insertItems(hTree, nodes, parentHandle, hItemMap, keyMap) {
21765
21902
  const itemBuf = buildTvItem(textBuf.ptr, cChildren);
21766
21903
  const item = TVITEM.decode(itemBuf);
21767
21904
  const tvins = TVINSERTSTRUCT.encode({ hParent: parentHandle, hInsertAfter: -65536, item });
21768
- const hItem = gui16.SendMessage(hTree, 4402, 0, tvins.ptr);
21905
+ const hItem = gui15.SendMessage(hTree, 4402, 0, tvins.ptr);
21769
21906
  hItemMap.set(hItem, node);
21770
21907
  if (node.key)
21771
21908
  keyMap.set(node.key, hItem);
21772
21909
  if (node.children && node.children.length > 0) {
21773
21910
  insertItems(hTree, node.children, hItem, hItemMap, keyMap);
21774
- gui16.SendMessage(hTree, 4354, 2, hItem);
21911
+ gui15.SendMessage(hTree, 4354, 2, hItem);
21775
21912
  }
21776
21913
  }
21777
21914
  }
21778
21915
  function deleteAllItems(hTree) {
21779
- const n2 = gui16.SendMessage(hTree, 4357, 0, 0);
21916
+ const n2 = gui15.SendMessage(hTree, 4357, 0, 0);
21780
21917
  if (n2 > 0)
21781
- gui16.SendMessage(
21918
+ gui15.SendMessage(
21782
21919
  hTree,
21783
21920
  4353,
21784
21921
  1,
@@ -21810,7 +21947,7 @@ var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onS
21810
21947
  const h2 = tvRef.current;
21811
21948
  if (!h2)
21812
21949
  return;
21813
- gui16.SendMessage(
21950
+ gui15.SendMessage(
21814
21951
  h2,
21815
21952
  4396,
21816
21953
  0,
@@ -21826,7 +21963,7 @@ var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onS
21826
21963
  return;
21827
21964
  const hItem = keyMapRef.current.get(selKey);
21828
21965
  if (hItem !== void 0)
21829
- gui16.SendMessage(h2, 4363, 9, hItem);
21966
+ gui15.SendMessage(h2, 4363, 9, hItem);
21830
21967
  }, [selKey]);
21831
21968
  return (0, import_jsx_runtime14.jsx)("w", { type: "STATIC", ws: 268435456 | 33554432, style: { ...style, flexDirection: "column", alignItems: "stretch" }, ref, onEvent: (e2) => {
21832
21969
  if (e2.msg === 78) {
@@ -21835,7 +21972,7 @@ var TreeView = (0, import_react16.forwardRef)(function TreeViewInner({ data, onS
21835
21972
  const h2 = tvRef.current;
21836
21973
  if (!h2)
21837
21974
  return;
21838
- const hCaret = gui16.SendMessage(h2, 4362, 9, 0);
21975
+ const hCaret = gui15.SendMessage(h2, 4362, 9, 0);
21839
21976
  const node = hItemMapRef.current.get(hCaret) ?? null;
21840
21977
  const key = node?.key ?? null;
21841
21978
  if (!isControlled)
@@ -21853,24 +21990,24 @@ var import_jsx_runtime15 = __toESM(require_jsx_runtime(), 1);
21853
21990
  var import_react17 = __toESM(require_react(), 1);
21854
21991
 
21855
21992
  // _build/lib/windows/comdlg32.js
21856
- var b4 = (name, sig) => bind2("comdlg32.dll", name, sig);
21857
- var GetOpenFileName = /* @__PURE__ */ b4("GetOpenFileNameW", "<OPENFILENAMEW>ptr -> u32");
21993
+ var b5 = (name, sig) => bind2("comdlg32.dll", name, sig);
21994
+ var GetOpenFileName = /* @__PURE__ */ b5("GetOpenFileNameW", "<OPENFILENAMEW>ptr -> u32");
21858
21995
 
21859
21996
  // _build/lib/windows/shell32.js
21860
- var b5 = (name, sig, encoders) => bind2("shell32.dll", name, sig, encoders);
21861
- var SHBrowseForFolder = /* @__PURE__ */ b5("SHBrowseForFolderW", "<BROWSEINFOW>ptr -> <>ptr");
21862
- var SHGetPathFromIDList = /* @__PURE__ */ b5("SHGetPathFromIDListW", "<>ptr <BYTE>ptr -> u32");
21997
+ var b6 = (name, sig, encoders) => bind2("shell32.dll", name, sig, encoders);
21998
+ var SHBrowseForFolder = /* @__PURE__ */ b6("SHBrowseForFolderW", "<BROWSEINFOW>ptr -> <>ptr");
21999
+ var SHGetPathFromIDList = /* @__PURE__ */ b6("SHGetPathFromIDListW", "<>ptr <BYTE>ptr -> u32");
21863
22000
  var Shell_NotifyIconGetRect = (() => {
21864
22001
  try {
21865
- return b5("Shell_NotifyIconGetRect", "<NOTIFYICONIDENTIFIER>ptr <RECT>ptr -> i32", { NOTIFYICONIDENTIFIER });
22002
+ return b6("Shell_NotifyIconGetRect", "<NOTIFYICONIDENTIFIER>ptr <RECT>ptr -> i32", { NOTIFYICONIDENTIFIER });
21866
22003
  } catch {
21867
22004
  return null;
21868
22005
  }
21869
22006
  })();
21870
22007
 
21871
22008
  // _build/lib/windows/ole32.js
21872
- var b6 = (name, sig) => bind2("ole32.dll", name, sig);
21873
- var CoTaskMemFree = /* @__PURE__ */ b6("CoTaskMemFree", "<>ptr -> void");
22009
+ var b7 = (name, sig) => bind2("ole32.dll", name, sig);
22010
+ var CoTaskMemFree = /* @__PURE__ */ b7("CoTaskMemFree", "<>ptr -> void");
21874
22011
 
21875
22012
  // _build/lib/react-qw/components/PathPicker.js
21876
22013
  function openFileDialog(owner, filter, title, multiple) {
@@ -21965,7 +22102,7 @@ var rootMap = /* @__PURE__ */ new Map();
21965
22102
  function ensureDefaultClass() {
21966
22103
  if (defaultClassRegistered)
21967
22104
  return DEFAULT_CLASS;
21968
- gui17.RegisterClass(DEFAULT_CLASS, (hwnd, msg, wParam, lParam) => {
22105
+ gui16.RegisterClass(DEFAULT_CLASS, (hwnd, msg, wParam, lParam) => {
21969
22106
  const entry = rootMap.get(hwnd);
21970
22107
  if (msg === 2 && entry) {
21971
22108
  rootMap.delete(hwnd);
@@ -21991,15 +22128,27 @@ function createRoot(container) {
21991
22128
  const ws = (cfg2.ws ?? 0) | 13565952;
21992
22129
  const w2 = (cfg2.width ?? 800) * scaleFactor;
21993
22130
  const h2 = (cfg2.height ?? 600) * scaleFactor;
21994
- const [sw, sh] = [GetSystemMetrics(0), GetSystemMetrics(1)];
22131
+ const [sw, sh] = [GetSystemMetrics(
22132
+ 0
22133
+ /* SysMetrics.CXSCREEN */
22134
+ ), GetSystemMetrics(
22135
+ 1
22136
+ /* SysMetrics.CYSCREEN */
22137
+ )];
21995
22138
  const x2 = cfg2.x === void 0 ? (sw - w2) / 2 | 0 : cfg2.x === -2147483648 ? -2147483648 : cfg2.x * scaleFactor;
21996
22139
  const y2 = cfg2.y === void 0 ? (sh - h2) / 2 | 0 : cfg2.y === -2147483648 ? -2147483648 : cfg2.y * scaleFactor;
21997
- const hwin = gui17.CreateWindow(className, cfg2.text || "", ws, x2, y2, w2, h2, null, null);
22140
+ const hwin = gui16.CreateWindow(className, cfg2.text || "", ws, x2, y2, w2, h2, null, null);
21998
22141
  if (!hwin)
21999
22142
  throw new Error("CreateWindow failed");
22000
22143
  hwnd = hwin;
22001
- if (!cfg2.noShowWindow)
22002
- gui17.ShowWindow(hwnd);
22144
+ if (!cfg2.noShowWindow) {
22145
+ ShowWindow(
22146
+ hwnd,
22147
+ 1
22148
+ /* ShowWindowCmd.SHOWNORMAL */
22149
+ );
22150
+ UpdateWindow(hwnd);
22151
+ }
22003
22152
  } else {
22004
22153
  hwnd = container;
22005
22154
  }
@@ -22022,21 +22171,21 @@ function createRoot(container) {
22022
22171
  // _build/examples/execd/main.js
22023
22172
  var import_react18 = __toESM(require_react(), 1);
22024
22173
 
22025
- // _build/examples/execd/tray.js
22026
- import * as os6 from "os";
22027
- import * as gui18 from "gui";
22028
-
22029
22174
  // _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");
22175
+ var b8 = (name, sig, encoders) => bind2("kernel32.dll", name, sig, encoders);
22176
+ var CloseHandle = /* @__PURE__ */ b8("CloseHandle", "<>ptr -> i32");
22177
+ var OpenProcess = /* @__PURE__ */ b8("OpenProcess", "u32 i32 u32 -> <HPROCESS>ptr");
22178
+ var GetCurrentProcess = /* @__PURE__ */ b8("GetCurrentProcess", " -> <HPROCESS>ptr");
22179
+ var VirtualAllocEx = /* @__PURE__ */ b8("VirtualAllocEx", "<HPROCESS>ptr <>ptr <>ptr u32 u32 -> <>ptr");
22180
+ var VirtualFreeEx = /* @__PURE__ */ b8("VirtualFreeEx", "<HPROCESS>ptr <>ptr <>ptr u32 -> i32");
22181
+ var ReadProcessMemory = /* @__PURE__ */ b8("ReadProcessMemory", "<HPROCESS>ptr <>ptr <BYTE>ptr <>ptr <>ptr -> i32");
22182
+ var MoveFileEx = /* @__PURE__ */ b8("MoveFileExW", "<WCHAR>ptr! <WCHAR>ptr! u32 -> i32");
22183
+ var GetLastError = /* @__PURE__ */ b8("GetLastError", " -> u32");
22184
+ var IsWow64Process = /* @__PURE__ */ b8("IsWow64Process", "<HPROCESS>ptr <BYTE>ptr -> i32");
22038
22185
 
22039
22186
  // _build/examples/execd/tray.js
22187
+ import * as os6 from "os";
22188
+ import * as gui17 from "gui";
22040
22189
  var TB_GETBUTTON = 1047;
22041
22190
  var TB_BUTTONCOUNT = 1048;
22042
22191
  var TB_GETITEMRECT = 1053;
@@ -22067,7 +22216,7 @@ function findToolbars(root) {
22067
22216
  return out;
22068
22217
  }
22069
22218
  function readToolbar(tb, area, out) {
22070
- const count = gui18.SendMessage(tb, TB_BUTTONCOUNT, 0, 0);
22219
+ const count = gui17.SendMessage(tb, TB_BUTTONCOUNT, 0, 0);
22071
22220
  if (!Number.isInteger(count) || count <= 0 || count > 512)
22072
22221
  return;
22073
22222
  const pidBuf = BYTE.alloc(4);
@@ -22086,7 +22235,7 @@ function readToolbar(tb, area, out) {
22086
22235
  const tbBuf = BYTE.alloc(REMOTE_BUF), trBuf = BYTE.alloc(REMOTE_BUF), tipBuf = BYTE.alloc(REMOTE_BUF);
22087
22236
  const dvTb = new DataView(tbBuf), dvTr = new DataView(trBuf);
22088
22237
  for (let i2 = 0; i2 < count; i2++) {
22089
- if (!gui18.SendMessage(tb, TB_GETBUTTON, i2, remote))
22238
+ if (!gui17.SendMessage(tb, TB_GETBUTTON, i2, remote))
22090
22239
  continue;
22091
22240
  if (!ReadProcessMemory(proc, remote, tbBuf, TBBUTTON_SZ, NULL))
22092
22241
  continue;
@@ -22100,14 +22249,14 @@ function readToolbar(tb, area, out) {
22100
22249
  if (!hWnd || !IsWindow(hWnd))
22101
22250
  continue;
22102
22251
  let rect = null;
22103
- if (gui18.SendMessage(tb, TB_GETITEMRECT, i2, remote) && ReadProcessMemory(proc, remote, trBuf, 16, NULL)) {
22252
+ if (gui17.SendMessage(tb, TB_GETITEMRECT, i2, remote) && ReadProcessMemory(proc, remote, trBuf, 16, NULL)) {
22104
22253
  const L2 = dvTr.getInt32(0, true), T2 = dvTr.getInt32(4, true);
22105
22254
  const R2 = dvTr.getInt32(8, true), B2 = dvTr.getInt32(12, true);
22106
22255
  if (!(L2 === 0 && T2 === 0 && R2 === 0 && B2 === 0)) {
22107
22256
  const tl = POINT.encode({ x: L2, y: T2 }), br2 = POINT.encode({ x: R2, y: B2 });
22108
22257
  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 };
22258
+ const a2 = POINT.decode(tl), b9 = POINT.decode(br2);
22259
+ rect = { left: a2.x, top: a2.y, right: b9.x, bottom: b9.y };
22111
22260
  }
22112
22261
  }
22113
22262
  }
@@ -22177,25 +22326,25 @@ function probeTrayIcon(hWnd, uID) {
22177
22326
 
22178
22327
  // _build/examples/execd/main.js
22179
22328
  function parseArgs() {
22180
- let gui20 = true;
22329
+ let gui18 = true;
22181
22330
  let token = null;
22182
22331
  const args = typeof scriptArgs === "undefined" ? [] : scriptArgs;
22183
22332
  const normToken2 = (v2) => v2 === "" ? null : v2;
22184
22333
  for (let i2 = 0; i2 < args.length; i2++) {
22185
22334
  const a2 = args[i2] ?? "";
22186
22335
  if (a2 === "--nogui") {
22187
- gui20 = false;
22336
+ gui18 = false;
22188
22337
  } else if (a2 === "--gui") {
22189
- gui20 = (args[++i2] ?? "") !== "0";
22338
+ gui18 = (args[++i2] ?? "") !== "0";
22190
22339
  } else if (a2.startsWith("--gui=")) {
22191
- gui20 = a2.slice(6) !== "0";
22340
+ gui18 = a2.slice(6) !== "0";
22192
22341
  } else if (a2 === "--token") {
22193
22342
  token = normToken2(args[++i2] ?? "");
22194
22343
  } else if (a2.startsWith("--token=")) {
22195
22344
  token = normToken2(a2.slice(8));
22196
22345
  }
22197
22346
  }
22198
- return { gui: gui20, token };
22347
+ return { gui: gui18, token };
22199
22348
  }
22200
22349
  var cfg = parseArgs();
22201
22350
  var log = new RequestLog(100);
@@ -22259,7 +22408,7 @@ function initGui() {
22259
22408
  height: 420
22260
22409
  });
22261
22410
  root.render((0, import_jsx_runtime16.jsx)(LogPanel, {}));
22262
- gui19.ShowWindow(
22411
+ ShowWindow(
22263
22412
  root.hwnd,
22264
22413
  9
22265
22414
  /* ShowWindowCmd.RESTORE */
@@ -22291,7 +22440,7 @@ function authCheck(req) {
22291
22440
  }
22292
22441
  function runInWorker(cmd, signal, timeoutMs) {
22293
22442
  const spawnCmd = cmd;
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");
22443
+ const worker = new os7.Worker("data:text/javascript;base64,aW1wb3J0KmFzIER0IGZyb20ib3MiO2ltcG9ydCphcyBPdCBmcm9tInN0ZCI7aW1wb3J0KmFzIGcgZnJvbSJmZmkiO2ltcG9ydCphcyBsdCBmcm9tIm9zIjtpbXBvcnQqYXMgZHQgZnJvbSJzdGQiO3ZhciBMdD17InV0Zi04IjoidXRmLTgiLHV0Zjg6InV0Zi04IiwidW5pY29kZS0xLTEtdXRmLTgiOiJ1dGYtOCIsInV0Zi0xNiI6InV0Zi0xNmxlIiwidXRmLTE2bGUiOiJ1dGYtMTZsZSIsInV0Zi0xNmJlIjoidXRmLTE2YmUifTtmdW5jdGlvbiBpdCh0KXtpZighdClyZXR1cm4idXRmLTgiO2xldCBlPUx0W3QudHJpbSgpLnRvTG93ZXJDYXNlKCldO2lmKGUpcmV0dXJuIGU7dGhyb3cgbmV3IFJhbmdlRXJyb3IoYFRoZSBlbmNvZGluZyBsYWJlbCAiJHt0fSIgaXMgbm90IHN1cHBvcnRlZGApfWZ1bmN0aW9uIE10KHQsZSl7bGV0IHI9IiI7Zm9yKGxldCBuPTA7bjx0Lmxlbmd0aDspe2xldCBvPXRbbisrXTtpZihvPDEyOCl7cis9U3RyaW5nLmZyb21DaGFyQ29kZShvKTtjb250aW51ZX1pZihvPDE5Mil7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJ1bmV4cGVjdGVkIGNvbnRpbnVhdGlvbiBieXRlIil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWxldCBpLGM7aWYobzwyMjQpe2lmKG4+PXQubGVuZ3RoKXtyKz1lPygoKT0+e3Rocm93IG5ldyBUeXBlRXJyb3IoImluY29tcGxldGUgdXRmLTgiKX0pKCk6Ilx1RkZGRCI7YnJlYWt9bGV0IHM9dFtuKytdO2lmKChzJjE5MikhPT0xMjgpe3IrPSJcdUZGRkQiO2NvbnRpbnVlfWk9KG8mMzEpPDw2fHMmNjMsYz0xMjh9ZWxzZSBpZihvPDI0MCl7aWYobisxPj10Lmxlbmd0aCl7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbmNvbXBsZXRlIHV0Zi04Iil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPXRbbisrXSx1PXRbbisrXTtpZigocyYxOTIpIT09MTI4fHwodSYxOTIpIT09MTI4KXtyKz0iXHVGRkZEIjtjb250aW51ZX1pPShvJjE1KTw8MTJ8KHMmNjMpPDw2fHUmNjMsYz0yMDQ4fWVsc2UgaWYobzwyNDgpe2lmKG4rMj49dC5sZW5ndGgpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW5jb21wbGV0ZSB1dGYtOCIpfSkoKToiXHVGRkZEIjticmVha31sZXQgcz10W24rK10sdT10W24rK10scD10W24rK107aWYoKHMmMTkyKSE9PTEyOHx8KHUmMTkyKSE9PTEyOHx8KHAmMTkyKSE9PTEyOCl7cis9Ilx1RkZGRCI7Y29udGludWV9aT0obyY3KTw8MTh8KHMmNjMpPDwxMnwodSY2Myk8PDZ8cCY2MyxjPTY1NTM2fWVsc2V7cis9ZT8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbnZhbGlkIHV0Zi04IHN0YXJ0Iil9KSgpOiJcdUZGRkQiO2NvbnRpbnVlfWlmKGk8Y3x8aT49NTUyOTYmJmk8PTU3MzQzfHxpPjExMTQxMTEpe3IrPWU/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigiaW52YWxpZCB1dGYtOCBjb2RlcG9pbnQiKX0pKCk6Ilx1RkZGRCI7Y29udGludWV9aTw9NjU1MzU/cis9U3RyaW5nLmZyb21DaGFyQ29kZShpKTooaS09NjU1MzYscis9U3RyaW5nLmZyb21DaGFyQ29kZSg1NTI5NnxpPj4xMCw1NjMyMHxpJjEwMjMpKX1yZXR1cm4gcn1mdW5jdGlvbiBBdCh0LGUscil7bGV0IG49bmV3IERhdGFWaWV3KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCx0LmJ5dGVMZW5ndGgpLG89IiI7Zm9yKGxldCBpPTA7aSsxPHQubGVuZ3RoO2krPTIpe2xldCBjPW4uZ2V0VWludDE2KGksZSk7aWYoYz49NTUyOTYmJmM8PTU2MzE5KXtpZihpKz0yLGkrMT49dC5sZW5ndGgpe28rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidHJ1bmNhdGVkIHN1cnJvZ2F0ZSBwYWlyIil9KSgpOiJcdUZGRkQiO2JyZWFrfWxldCBzPW4uZ2V0VWludDE2KGksZSk7cz49NTYzMjAmJnM8PTU3MzQzP28rPVN0cmluZy5mcm9tQ2hhckNvZGUoYyxzKToobys9cj8oKCk9Pnt0aHJvdyBuZXcgVHlwZUVycm9yKCJpbnZhbGlkIHN1cnJvZ2F0ZSBwYWlyIil9KSgpOiJcdUZGRkQiLGktPTIpfWVsc2UgYz49NTYzMjAmJmM8PTU3MzQzP28rPXI/KCgpPT57dGhyb3cgbmV3IFR5cGVFcnJvcigidW5leHBlY3RlZCB0cmFpbGluZyBzdXJyb2dhdGUiKX0pKCk6Ilx1RkZGRCI6bys9U3RyaW5nLmZyb21DaGFyQ29kZShjKX1yZXR1cm4gb312YXIgWT1jbGFzc3tfZW5jb2Rpbmc7X2ZhdGFsO19pZ25vcmVCT007Y29uc3RydWN0b3IoZSxyKXt0aGlzLl9lbmNvZGluZz1pdChlKSx0aGlzLl9mYXRhbD1yPy5mYXRhbD8/ITEsdGhpcy5faWdub3JlQk9NPXI/Lmlnbm9yZUJPTT8/ITF9Z2V0IGVuY29kaW5nKCl7cmV0dXJuIHRoaXMuX2VuY29kaW5nfWdldCBmYXRhbCgpe3JldHVybiB0aGlzLl9mYXRhbH1nZXQgaWdub3JlQk9NKCl7cmV0dXJuIHRoaXMuX2lnbm9yZUJPTX1kZWNvZGUoZSl7aWYoIWUpcmV0dXJuIiI7bGV0IHI9ZSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXk/ZTplIGluc3RhbmNlb2YgQXJyYXlCdWZmZXI/bmV3IFVpbnQ4QXJyYXkoZSk6bmV3IFVpbnQ4QXJyYXkoZS5idWZmZXIsZS5ieXRlT2Zmc2V0LGUuYnl0ZUxlbmd0aCk7aWYodGhpcy5fZW5jb2Rpbmc9PT0idXRmLTgiKXJldHVybiBNdChyLHRoaXMuX2ZhdGFsKTtsZXQgbj10aGlzLl9lbmNvZGluZz09PSJ1dGYtMTZsZSIsbz0wO2lmKHIubGVuZ3RoPj0yJiYhdGhpcy5faWdub3JlQk9NKXtsZXQgaT1uP3JbMF06clsxXSxzPShuP3JbMV06clswXSk8PDh8aTsocz09PTY1Mjc5fHxzPT09NjU1MzQpJiYobz0yKX1yZXR1cm4gQXQoci5zbGljZShvKSxuLHRoaXMuX2ZhdGFsKX19LFY9Y2xhc3N7X2VuY29kaW5nO2NvbnN0cnVjdG9yKGUpe3RoaXMuX2VuY29kaW5nPWl0KGUpfWdldCBlbmNvZGluZygpe3JldHVybiB0aGlzLl9lbmNvZGluZ31lbmNvZGUoZSl7aWYoIWUpcmV0dXJuIG5ldyBVaW50OEFycmF5KDApO2lmKHRoaXMuX2VuY29kaW5nPT09InV0Zi04Iil7bGV0IGk9W107Zm9yKGxldCBjPTA7YzxlLmxlbmd0aDtjKyspe2xldCBzPWUuY2hhckNvZGVBdChjKTtpZihzPDEyOClpLnB1c2gocyk7ZWxzZSBpZihzPDIwNDgpaS5wdXNoKDE5MnxzPj42LDEyOHxzJjYzKTtlbHNlIGlmKHM8NTUyOTZ8fHM+PTU3MzQ0KWkucHVzaCgyMjR8cz4+MTIsMTI4fHM+PjYmNjMsMTI4fHMmNjMpO2Vsc2V7YysrO2xldCB1PWUuY2hhckNvZGVBdChjKTtzPTY1NTM2KygocyYxMDIzKTw8MTApfHUmMTAyMyxpLnB1c2goMjQwfHM+PjE4LDEyOHxzPj4xMiY2MywxMjh8cz4+NiY2MywxMjh8cyY2Myl9fXJldHVybiBuZXcgVWludDhBcnJheShpKX1sZXQgcj10aGlzLl9lbmNvZGluZz09PSJ1dGYtMTZsZSIsbj1uZXcgQXJyYXlCdWZmZXIoZS5sZW5ndGgqMiksbz1uZXcgRGF0YVZpZXcobik7Zm9yKGxldCBpPTA7aTxlLmxlbmd0aDtpKyspby5zZXRVaW50MTYoaSoyLGUuY2hhckNvZGVBdChpKSxyKTtyZXR1cm4gbmV3IFVpbnQ4QXJyYXkobil9fTt0eXBlb2YgZ2xvYmFsVGhpcy5UZXh0RGVjb2Rlcj4idSImJihnbG9iYWxUaGlzLlRleHREZWNvZGVyPVkpO3R5cGVvZiBnbG9iYWxUaGlzLlRleHRFbmNvZGVyPiJ1IiYmKGdsb2JhbFRoaXMuVGV4dEVuY29kZXI9Vik7aW1wb3J0e2J1ZmZlclB0ciBhcyBXdH1mcm9tImZmaSI7aW1wb3J0KmFzIHN0IGZyb20ib3MiO3ZhciBSdD1bInZvaWQiLCJ1OCIsImk4IiwidTE2IiwiaTE2IiwidTMyIiwiaTMyIiwidTY0IiwiaTY0IiwiZjMyIiwiZjY0IiwicHRyIl0sdj0vXjwoW0EtWmEtel9dXHcqfCk+cHRyKCF8QFtBLVphLXpfXVx3Kik/JC87ZnVuY3Rpb24gYih0KXtyZXR1cm4gdi50ZXN0KHQpfXZhciBjdD0vXjwoW0EtWmEtel9dXHcqKT4kLztmdW5jdGlvbiB5KHQpe3JldHVybiBjdC50ZXN0KHQpfWZ1bmN0aW9uIFcodCl7cmV0dXJuIGN0LmV4ZWModCk/LlsxXXx8IiJ9ZnVuY3Rpb24gaih0KXtyZXR1cm4gdi5leGVjKHQpPy5bMV18fCIifXZhciB1dD10PT57aWYoYih0KSlyZXR1cm4icHRyIjtpZih5KHQpKXRocm93IG5ldyBFcnJvcihgZmZpOiBjVG9rZW5Ub1R5cGU6IGJ5LXZhbHVlIHRva2VuICIke3R9IiBoYXMgbm8gc2NhbGFyIHNsb3QgdHlwZWApO3JldHVybiB0fSxEPXN0LmFyY2g9PT0ieDY0Ij84OjQsUj17dTg6MSxpODoxLHUxNjoyLGkxNjoyLHUzMjo0LGkzMjo0LHU2NDo4LGk2NDo4LGYzMjo0LGY2NDo4fSxPPTA7ZnVuY3Rpb24gayh0KXtpZihiKHQpKXtsZXQgbz12LmV4ZWModCksaT1vPy5bMV18fCIiO3JldHVybiBvPy5bMl0/LnN0YXJ0c1dpdGgoIkAiKT9gPCR7aX0+cHRyYDp0fWlmKHkodCkpcmV0dXJuIHQ7bGV0IGU9dC5pbmRleE9mKCJAIikscj1lPj0wP3Quc2xpY2UoMCxlKTp0O2lmKChlPDB8fC9eW0EtWmEtel9dXHcqJC8udGVzdCh0LnNsaWNlKGUrMSkpKSYmciE9PSJwdHIiJiZSdC5pbmNsdWRlcyhyKSlyZXR1cm4gcjt0aHJvdyBuZXcgRXJyb3IoIlVua25vd24gdG9rZW46ICIrdCl9ZnVuY3Rpb24geih0LGUscil7c3dpdGNoKHIpe2Nhc2UidTgiOnJldHVybiB0LmdldFVpbnQ4KGUpO2Nhc2UiaTgiOnJldHVybiB0LmdldEludDgoZSk7Y2FzZSJ1MTYiOnJldHVybiB0LmdldFVpbnQxNihlLCEwKTtjYXNlImkxNiI6cmV0dXJuIHQuZ2V0SW50MTYoZSwhMCk7Y2FzZSJ1MzIiOnJldHVybiB0LmdldFVpbnQzMihlLCEwKTtjYXNlImkzMiI6cmV0dXJuIHQuZ2V0SW50MzIoZSwhMCk7Y2FzZSJ1NjQiOnJldHVybiB0LmdldEJpZ1VpbnQ2NChlLCEwKTtjYXNlImk2NCI6cmV0dXJuIHQuZ2V0QmlnSW50NjQoZSwhMCk7Y2FzZSJmMzIiOnJldHVybiB0LmdldEZsb2F0MzIoZSwhMCk7Y2FzZSJmNjQiOnJldHVybiB0LmdldEZsb2F0NjQoZSwhMCk7Y2FzZSJwdHIiOnJldHVybiBEPT09OD9OdW1iZXIodC5nZXRCaWdJbnQ2NChlLCEwKSk6dC5nZXRJbnQzMihlLCEwKX19ZnVuY3Rpb24gWCh0LGUse2s6cix2Om59KXtzd2l0Y2gocil7Y2FzZSJ1OCI6dC5zZXRVaW50OChlLE51bWJlcihuKSk7YnJlYWs7Y2FzZSJpOCI6dC5zZXRJbnQ4KGUsTnVtYmVyKG4pKTticmVhaztjYXNlInUxNiI6dC5zZXRVaW50MTYoZSxOdW1iZXIobiksITApO2JyZWFrO2Nhc2UiaTE2Ijp0LnNldEludDE2KGUsTnVtYmVyKG4pLCEwKTticmVhaztjYXNlInUzMiI6dC5zZXRVaW50MzIoZSxuPj4+MCwhMCk7YnJlYWs7Y2FzZSJpMzIiOnQuc2V0VWludDMyKGUsbj4+PjAsITApO2JyZWFrO2Nhc2UidTY0Ijp0LnNldEJpZ1VpbnQ2NChlLG4sITApO2JyZWFrO2Nhc2UiaTY0Ijp0LnNldEJpZ0ludDY0KGUsbiwhMCk7YnJlYWs7Y2FzZSJmMzIiOnQuc2V0RmxvYXQzMihlLG4sITApO2JyZWFrO2Nhc2UiZjY0Ijp0LnNldEZsb2F0NjQoZSxuLCEwKTticmVhaztjYXNlInB0ciI6e2lmKG49PW51bGwpdGhyb3cgbmV3IEVycm9yKCJmZmk6IGdvdCBudWxsL3VuZGVmaW5lZCBmb3IgYSBwdHIgc2xvdDsgcGFzcyB0aGUgaW1wb3J0ZWQgTlVMTCBjb25zdGFudCBmb3IgZW1wdHkiKTtEPT09OD90LnNldEJpZ1VpbnQ2NChlLEJpZ0ludC5hc1VpbnROKDY0LEJpZ0ludChuKSksITApOnQuc2V0VWludDMyKGUsbj4+PjAsITApO2JyZWFrfX19ZnVuY3Rpb24gXyh0LGUscil7bGV0e2s6bix2Om99PXI7aWYobj09PSJ1OCJ8fG49PT0iaTgifHxuPT09InUxNiJ8fG49PT0iaTE2Iil7dC5zZXRVaW50MzIoZSxOdW1iZXIobyk+Pj4wLCEwKTtyZXR1cm59WCh0LGUscil9dmFyIHg9Y2xhc3MgZXh0ZW5kcyBBcnJheUJ1ZmZlcntwdHI7Y29uc3RydWN0b3IoZSl7c3VwZXIoZSksdGhpcy5wdHI9V3QodGhpcyl9fTtmdW5jdGlvbiBaKHQsZSl7cmV0dXJuIGVbdF19dmFyIGF0PW5ldyBNYXA7ZnVuY3Rpb24ga3QodCl7bGV0IGU9YXQuZ2V0KHQpO2lmKGUhPT12b2lkIDApcmV0dXJuIGU7bGV0IHI9Zy5Mb2FkTGlicmFyeSh0KTtpZighcil0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBMb2FkTGlicmFyeSgiJHt0fSIpIGZhaWxlZGApO3JldHVybiBhdC5zZXQodCxyKSxyfWZ1bmN0aW9uIF90KHQpe2xldCBlPXQuc3BsaXQoIiAtPiAiKTtpZihlLmxlbmd0aCE9PTIpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogaW52YWxpZCBzaWduYXR1cmUgIiR7dH0iIChleHBlY3RlZCAiYXJnMSBhcmcyIC0+IHJldCIpYCk7bGV0IHI9ZVswXS5zcGxpdCgiICIpLmZpbHRlcihpPT5pIT09IiIpLG49W107Zm9yKGxldCBpIG9mIHIpe2xldCBjPWsoaSk7aWYoYz09PSJ2b2lkIil0aHJvdyBuZXcgRXJyb3IoIlZvaWQgY2FuIG5vdCBpbiBhcmdzIik7bi5wdXNoKGMpfWxldCBvPWsoZVsxXSk7aWYoeShvKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAiJHt0fSI6IGJ5LXZhbHVlIHN0cnVjdCBhdCB0aGUgcmV0dXJuIHBvc2l0aW9uICg8JHtXKG8pfT4pIGlzIG5vdCBzdXBwb3J0ZWQgXHUyMDE0IGFyZ3VtZW50IHBvc2l0aW9ucyBvbmx5OyBwYXNzIGEgc3RydWN0IG91dCB0aHJvdWdoIGFuIG91dC1wYXJhbSBzbG90IGluc3RlYWQgKDxOPnB0ciArIGNhbGxlciBidWZmZXIpYCk7cmV0dXJue2FyZ1Rva2VuczpuLHJldFRva2VuOm8sc2lnOnR9fWZ1bmN0aW9uIFV0KHQsZSxyLG4pe2xldCBvPV90KGUpO2ZvcihsZXQgaSBvZiBvLmFyZ1Rva2Vucyl7aWYoIXkoaSkpY29udGludWU7bGV0IGM9VyhpKSxzPVooYyxyKTtpZighc3x8dHlwZW9mIHMuZW5jb2RlIT0iZnVuY3Rpb24iKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7ZX06IGJ5LXZhbHVlIHBvc2l0aW9uIDwke2N9PiBoYXMgbm8gcmVnaXN0ZXJlZCBsYXlvdXQgKGF2YWlsYWJsZTogJHtPYmplY3Qua2V5cyhyKS5qb2luKCIsICIpfHwibm9uZSJ9KWApO2lmKHR5cGVvZiBzLnNpemUhPSJudW1iZXIifHxzLnNpemU8MSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke2V9OiBieS12YWx1ZSBwb3NpdGlvbiA8JHtjfT4gcmVxdWlyZXMgYSBzdHJ1Y3QgbGF5b3V0IHdpdGggc2l6ZSA+PSAxIChnb3QgJHtzLnNpemV9OyBub24tc3RydWN0IGNvZGVjcyBleHBvc2Ugbm8gc2l6ZSlgKX1yZXR1cm4oLi4uaSk9PkJ0KHQsbyxpLHIsbil9dmFyIEh0PXt1ODo0LGk4OjQsdTE2OjQsaTE2OjQsdTMyOjQsaTMyOjQsdTY0OjgsaTY0OjgsZjMyOjQsZjY0OjgscHRyOkR9LHB0PTQ7ZnVuY3Rpb24gQnQodCx7YXJnVG9rZW5zOmUscmV0VG9rZW46cixzaWc6bn0sbyxpLGMpe2xldCBzPWx0LmFyY2g9PT0ieDY0Iix1PShhLGQpPT57aWYoeShhKSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiBnZXRXaWR0aDogYnktdmFsdWUgdG9rZW4gIiR7YX0iIChkaXNwYXRjaGVkIGJ5IHdpZHRoT2YpYCk7cmV0dXJuIGQ/ODpiKGEpP0Q6SHRbYV19LHA9YT0+e2lmKHkoYSkpe2lmKHMpcmV0dXJuIDg7bGV0IGQ9WihXKGEpLGkpO2lmKCFkKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IDwke1coYSl9PiBieS12YWx1ZSBwb3NpdGlvbiBoYXMgbm8gcmVnaXN0ZXJlZCBsYXlvdXRgKTtsZXQgbT1kLnNpemU7cmV0dXJuIG0lND09PTA/bTptKzQtbSU0fXJldHVybiB1KGEscyl9LGg9MDtmb3IobGV0IGEgb2YgZSloKz1wKGEpO3MmJmUubGVuZ3RoPHB0JiYoaD1wdCo4KTtsZXQgRj1uZXcgQXJyYXlCdWZmZXIoaCksVD1uZXcgRGF0YVZpZXcoRiksST1bXSxFPTA7Zm9yKGxldCBhPTA7YTxlLmxlbmd0aDthKyspe2xldCBkPWVbYV0sbT1kLmVuZHNXaXRoKCIhIiksZj1vW2FdO2lmKGIoZCkpe2xldCBsPWooZCk7aWYodHlwZW9mIGY9PSJudW1iZXIiKXtpZihtJiZmPT09MCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiAke259OiBhcmcjJHthKzF9IDwke2x9PnB0ciEgZ290IDAgKG51bGwgcG9pbnRlciBmb3JiaWRkZW4gaGVyZTsgdGhlIHRva2VuIG1hcmtzIHRoaXMgcG9zaXRpb24gbm9uLW51bGwpYCk7XyhULEUse2s6InB0ciIsdjpmfSl9ZWxzZXtpZihmPT1udWxsKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6IDwke2x9PnB0ciBnb3QgJHtTdHJpbmcoZil9OyBwYXNzIHRoZSBpbXBvcnRlZCBOVUxMIGNvbnN0YW50IGZvciBhbiBlbXB0eSBwb2ludGVyYCk7bGV0IEM9aVtsXTtpZighQyl0aHJvdyBuZXcgRXJyb3IobD09PSIiP2BmZmktYmluZDogPD5wdHIgZXhwZWN0cyBudW1iZXIgKE5VTEwgfCBQdHIpLCBnb3QgJHt0eXBlb2YgZn07IHVzZSA8QllURT5wdHIgd2l0aCBhIFB0ckFycmF5QnVmZmVyIChuZXcgUHRyQXJyYXlCdWZmZXIobikpLCBvciBmZmkuYnVmZmVyUHRyKGJ1ZikgZm9yIGFuIGFkZHJlc3NgOmBmZmktYmluZDogdW5rbm93biBsYXlvdXQgIjwke2x9PnB0ciIgKGF2YWlsYWJsZTogJHtPYmplY3Qua2V5cyhpKS5qb2luKCIsICIpfHwibm9uZSJ9KWApO2lmKCFDLmVuY29kZSl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtsfT5wdHIgaGFzIG5vIGVuY29kZXIgKG91dC1vbmx5IGNvZGVjKWApO2xldCBMPUMuZW5jb2RlKGYpO0kucHVzaChMKTtsZXQgTT1MLnB0cjtpZih0eXBlb2YgTSE9Im51bWJlciIpdGhyb3cgbmV3IEVycm9yKCJmZmktYmluZDogY29kZWMuZW5jb2RlIG11c3QgcmV0dXJuIGEgUHRyQXJyYXlCdWZmZXIsIGdvdCBwbGFpbiBBcnJheUJ1ZmZlciIpO2lmKG0mJk09PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7bn06IGFyZyMke2ErMX0gPCR7bH0+cHRyISBlbmNvZGUgcHJvZHVjZWQgMCAobnVsbCBwb2ludGVyIGZvcmJpZGRlbiBoZXJlKWApO18oVCxFLHtrOiJwdHIiLHY6TX0pfX1lbHNlIGlmKHkoZCkpe2xldCBsPVcoZCksQz1aKGwsaSk7aWYoIUMpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogJHtufTogYXJnIyR7YSsxfSA8JHtsfT4gYnktdmFsdWUgcG9zaXRpb24gaGFzIG5vIHJlZ2lzdGVyZWQgbGF5b3V0YCk7aWYoZj09bnVsbCl0aHJvdyBuZXcgRXJyb3IoYGZmaS1iaW5kOiA8JHtsfT4gdmFsdWUgcG9zaXRpb24gZ290ICR7U3RyaW5nKGYpfTsgcGFzcyBhIHN0cnVjdCBvYmplY3QgKHVzZSA8JHtsfT5wdHIgdG8gcGFzcyBhIHBvaW50ZXIpYCk7bGV0IEw9Qy5zaXplO2lmKCFzfHxMPD04JiYoTCZMLTEpPT09MClDLmVuY29kZShmLEYsRSk7ZWxzZXtsZXQgTT1uZXcgQXJyYXlCdWZmZXIoTCsxNSksbnQ9Zy5idWZmZXJQdHIoTSksb3Q9KDE2LW50JTE2KSUxNjtDLmVuY29kZShmLE0sb3QpLEkucHVzaChNKSxfKFQsRSx7azoicHRyIix2Om50K290fSl9fWVsc2UgXyhULEUse2s6ZCx2OmZ9KTtFKz1wKGQpfWxldCBQPW5ldyBBcnJheUJ1ZmZlcig4KTtnLmZmaUNhbGwodCxGLFAscj09PSJmMzIifHxyPT09ImY2NCI/MTowKTtsZXQgUz16dCh1dChyKSxQKTtpZihyLmVuZHNXaXRoKCIhIikmJlM9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLWJpbmQ6ICR7bn06IHJldHVybiAke3J9IGdvdCAwICh0aGUgdG9rZW4gcHJvbWlzZXMgQyBuZXZlciByZXR1cm5zIG51bGwgaGVyZSlgKTtpZihiKHIpJiZTIT09MCl7bGV0IGE9aihyKTtpZihhIT09IiIpe2xldCBkPWNbYV07aWYoZD8uZGVjb2RlKXJldHVybiBkLmRlY29kZShTKX19cmV0dXJuIFN9ZnVuY3Rpb24genQodCxlKXtpZih0IT09InZvaWQiKXJldHVybiB6KG5ldyBEYXRhVmlldyhlKSwwLHQpfXZhciAkPXtlbmNvZGU6dD0+e2xldCBlPW5ldyBUZXh0RW5jb2RlcigidXRmLTE2bGUiKS5lbmNvZGUodCsiXDAiKSxyPW5ldyB4KGUuYnl0ZUxlbmd0aCk7cmV0dXJuIG5ldyBVaW50OEFycmF5KHIpLnNldChlKSxyfSxkZWNvZGU6dD0+e2lmKHR5cGVvZiB0PT0ibnVtYmVyIil7bGV0IG89IiIsaT10LGM9aTtmb3IoOzspe2xldCBzPWcucmVhZEJ5dGUoaSksdT1nLnJlYWRCeXRlKGkrMSk7aWYocz09PTAmJnU9PT0wKXJldHVybiBvO2lmKG8rPVN0cmluZy5mcm9tQ2hhckNvZGUoc3x1PDw4KSxpKz0yLGktYz4xPDwyMSl0aHJvdyBuZXcgRXJyb3IoImZmaS1iaW5kOiBXQ0hBUiBkZWNvZGUgZXhjZWVkZWQgNE1pQiB3aXRob3V0IE5VTCIpfX1sZXQgZT1uZXcgVWludDhBcnJheSh0KSxyPWUubGVuZ3RoJi0yLG49IiI7Zm9yKGxldCBvPTA7bzxyO28rPTIpe2xldCBpPWVbb118ZVtvKzFdPDw4O2lmKGk9PT0wKXJldHVybiBuO24rPVN0cmluZy5mcm9tQ2hhckNvZGUoaSl9cmV0dXJuIG59LGFsbG9jOih0PTI1Nik9Pm5ldyB4KHQqMil9LCR0PXtlbmNvZGU6dD0+e2lmKCEodCBpbnN0YW5jZW9mIHgpKXRocm93IG5ldyBFcnJvcigiZmZpLWJpbmQ6IDxCWVRFPnB0ciB3YW50cyBhIFB0ckFycmF5QnVmZmVyIChuZXcgUHRyQXJyYXlCdWZmZXIobikgLyBCWVRFLmFsbG9jIC8gc3RydWN0LmVuY29kZSksIG5vdCBhIHBsYWluIEFycmF5QnVmZmVyIik7cmV0dXJuIHR9LGFsbG9jOnQ9Pm5ldyB4KHQpfSxmdD17V0NIQVI6JCxCWVRFOiR0fTtmdW5jdGlvbiBtdCh0LGUscixuLG8pe2xldCBpPWcuR2V0UHJvY0FkZHJlc3Moa3QodCksZSk7aWYoIWkpdGhyb3cgbmV3IEVycm9yKGBmZmktYmluZDogcHJvYyAiJHtlfSIgbm90IGZvdW5kIGluICR7dH1gKTtsZXQgYz1vPz9uO3JldHVybiBVdChpLHIsey4uLmZ0LC4uLm59LHsuLi5mdCwuLi5jPz97fX0pfXZhciBwZT1uZXcgRmluYWxpemF0aW9uUmVnaXN0cnkodD0+e2R0LnByaW50ZihgW2ZmaV0gY2xvc3VyZSBsZWFrZWQgKEdDZWQgd2l0aG91dCBkaXNwb3NlKTogc2lnPSIlcyIgcHRyPTB4JXgKYCx0LnNpZyx0LnB0cil9KTtpbXBvcnQqYXMgeHQgZnJvbSJmZmkiO2Z1bmN0aW9uIFUodCxlKXtyZXR1cm4gdCtlLTEmfihlLTEpfXZhciBFdD10PT5SW3RdIT09dm9pZCAwO2Z1bmN0aW9uIHEodCl7aWYodHlwZW9mIHQ9PSJzdHJpbmciKXtsZXQgZT0vXih1OHx1MTYpXFsoXGQrKVxdQCh1dGYtOHx1dGYtMTZsZSkkLy5leGVjKHQpO2lmKGUpe2xldCBjPU51bWJlcihlWzJdKTtpZighTnVtYmVyLmlzSW50ZWdlcihjKXx8YzwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogc3RyaW5nIGxlbmd0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7Y31gKTtsZXQgcz1lWzFdPT09InU4Ij8xOjI7cmV0dXJue3NpemU6cypjLGFsaWduOnMsdHlwZTp7dGFnOiJzdHJpbmciLGVuY29kaW5nOmVbM119fX1sZXQgcj0vXihbXlxbXF1dKylcWyhcZCspXF0kLy5leGVjKHQpO2lmKHIpe2xldCBjPU51bWJlcihyWzJdKTtpZighTnVtYmVyLmlzSW50ZWdlcihjKXx8YzwxKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYXJyYXkgbGVuZ3RoIG11c3QgYmUgYW4gaW50ZWdlciA+PSAxLCBnb3QgJHtjfWApO2xldCBzPXEoclsxXSk7aWYocy50eXBlLnRhZz09PSJiaXRmaWVsZCIpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBiaXRmaWVsZHMgY2Fubm90IGJlIGFycmF5IGVsZW1lbnRzIik7cmV0dXJue3NpemU6cy5zaXplKmMsYWxpZ246cy5hbGlnbix0eXBlOnt0YWc6ImFycmF5IixlbGVtZW50VHlwZTpzLnR5cGUsZWxlbWVudFNpemU6cy5zaXplfX19bGV0IG49L14oW0EtWmEtel9dXHcqKTooXGQrKSQvLmV4ZWModCk7aWYobil7bGV0IGM9blsxXSxzPWsoYyk7aWYoIUV0KHMpfHxzPT09ImYzMiJ8fHM9PT0iZjY0Iil0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6IGJpdGZpZWxkIHVuaXQgbXVzdCBiZSBhbiBpbnRlZ2VyIHR5cGUsIGdvdCAiJHtjfSJgKTtsZXQgdT1OdW1iZXIoblsyXSkscD1SW3NdLGg9cCo4O2lmKCFOdW1iZXIuaXNJbnRlZ2VyKHUpfHx1PDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCBtdXN0IGJlIGFuIGludGVnZXIgPj0gMSwgZ290ICR7dX1gKTtpZih1PmgpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBiaXRmaWVsZCB3aWR0aCAke3V9IGV4Y2VlZHMgdW5pdCB3aWR0aCAke2h9YCk7cmV0dXJue3NpemU6cCxhbGlnbjpwLHR5cGU6e3RhZzoiYml0ZmllbGQiLHVuaXQ6cyxiaXQ6MCx3aWR0aDp1fX19bGV0IG89ayh0KTtpZihiKG8pKXJldHVybntzaXplOkQsYWxpZ246RCx0eXBlOnt0YWc6ImJhc2ljIixraW5kOiJwdHIifX07aWYoIUV0KG8pKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogdW5rbm93biBraW5kICIke3R9ImApO2xldCBpPVJbb107cmV0dXJue3NpemU6aSxhbGlnbjppLHR5cGU6e3RhZzoiYmFzaWMiLGtpbmQ6b319fWlmKHQmJnR5cGVvZiB0PT0ib2JqZWN0Iil7bGV0IGU9dCxyPWVbIiMiXTtpZihyPT09dm9pZCAwKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogbmVzdGVkIG9iamVjdCB2YWx1ZSByZXF1aXJlcyBhICcjJyBrZXkgKCdzdHJ1Y3QnIHwgJ3VuaW9uJyB8ICdhcnJheScpIik7aWYocj09PSJhcnJheSImJiIjcGFjayJpbiBlKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogJyNwYWNrJyBpcyBvbmx5IGFsbG93ZWQgb24gc3RydWN0L3VuaW9uLCBnb3QgJyR7cn0nYCk7aWYocj09PSJhcnJheSIpe2xldCBuPWUubGVuZ3RoO2lmKCFOdW1iZXIuaXNJbnRlZ2VyKG4pfHxuPDEpdGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBhcnJheSBsZW5ndGggbXVzdCBiZSBhbiBpbnRlZ2VyID49IDEsIGdvdCAke1N0cmluZyhuKX1gKTtsZXQgbz1xKGUuZWxlbWVudCk7aWYoby50eXBlLnRhZz09PSJiaXRmaWVsZCIpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBiaXRmaWVsZHMgY2Fubm90IGJlIGFycmF5IGVsZW1lbnRzIik7cmV0dXJue3NpemU6by5zaXplKm4sYWxpZ246by5hbGlnbix0eXBlOnt0YWc6ImFycmF5IixlbGVtZW50VHlwZTpvLnR5cGUsZWxlbWVudFNpemU6by5zaXplfX19aWYocj09PSJzdHJ1Y3QifHxyPT09InVuaW9uIil7bGV0IG49aHQodCk7cmV0dXJue3NpemU6bi5zaXplLGFsaWduOm4ubWF4RWZmZWN0aXZlQWxpZ24sdHlwZTp7dGFnOnIsZmllbGRzOm4uZmllbGRzfX19dGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiB1bmtub3duICcjJyBkZWNsYXJhdGlvbiAke0pTT04uc3RyaW5naWZ5KFN0cmluZyhyKSl9YCl9dGhyb3cgbmV3IEVycm9yKGBmZmktc3RydWN0OiBpbnZhbGlkIG1lbWJlciB2YWx1ZTogJHtTdHJpbmcodCl9YCl9ZnVuY3Rpb24gaHQodCl7bGV0IGU9dFsiIyJdPT09InN0cnVjdCIscj10WyIjcGFjayJdPz84LG49MSxvPTAsaT1bXSxjPTAscz0tMSx1PTAscD0wLGg9KCk9PntzPDB8fChjPVUocytNYXRoLmNlaWwodS84KSxwKSxzPS0xKX07Zm9yKGxldFtGLFRdb2YgT2JqZWN0LmVudHJpZXModCkpe2lmKEYuc3RhcnRzV2l0aCgiIyIpKWNvbnRpbnVlO2xldCBJPS9eKFteQF0rKUAoXGQrKSQvLmV4ZWMoRiksRT1JP0lbMV06RixQPUk/TnVtYmVyKElbMl0pOjAse3NpemU6dyxhbGlnbjpTLHR5cGU6YX09cShUKSxkPXR5cGVvZiBUPT0ic3RyaW5nIiYmVC5lbmRzV2l0aCgiISIpLG09UztpZihyPjAmJihtPU1hdGgubWluKHIsbSkpLFAmJihtPU1hdGgubWF4KG0sUCkpLGEudGFnPT09ImJpdGZpZWxkIil7aWYoRS5zdGFydHNXaXRoKCIkIikpdGhyb3cgbmV3IEVycm9yKCJmZmktc3RydWN0OiBiaXRmaWVsZCBtZW1iZXJzIG11c3QgYmUgbmFtZWQiKTtpZighZSl7aS5wdXNoKHtuYW1lOkUsb2Zmc2V0OjAsc2l6ZTp3LHR5cGU6ey4uLmEsYml0OjB9fSksbj1NYXRoLm1heChuLG0pLG89TWF0aC5tYXgobyx3KTtjb250aW51ZX1sZXQgbD1hLndpZHRoOyhzPDB8fHchPT1wfHx1K2w+cCo4KSYmKHM+PTAmJmgoKSxzPVUoYyxtKSx1PTAscD13KSxpLnB1c2goe25hbWU6RSxvZmZzZXQ6cyxzaXplOncsdHlwZTp7Li4uYSxiaXQ6dX19KSx1Kz1sLG49TWF0aC5tYXgobixtKSxvPU1hdGgubWF4KG8sdyk7Y29udGludWV9aCgpO2xldCBmPVUoYyxtKTtpZighRS5zdGFydHNXaXRoKCIkIikpaS5wdXNoKHtuYW1lOkUsb2Zmc2V0OmYsc2l6ZTp3LHR5cGU6YSwuLi5kP3tub25udWxsOiEwfTp7fX0pO2Vsc2V7aWYoYS50YWchPT0ic3RydWN0IiYmYS50YWchPT0idW5pb24iKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogYW5vbnltb3VzIG1lbWJlciAiJHtFfSIgbXVzdCBiZSBhIHN0cnVjdC91bmlvbmApO2ZvcihsZXQgbCBvZiBhLmZpZWxkcylpLnB1c2goey4uLmwsb2Zmc2V0Omwub2Zmc2V0K2Z9KX1lJiYoYz1mK3cpLG49TWF0aC5tYXgobixtKSxvPU1hdGgubWF4KG8sdyl9cmV0dXJuIGgoKSx7c2l6ZTpVKGU/YzpvLG4pLG1heEVmZmVjdGl2ZUFsaWduOm4sZmllbGRzOml9fWZ1bmN0aW9uIGd0KHQsZSxyKXtsZXQgbj1SW3JdO3JldHVybiBuPT09MT9CaWdJbnQodC5nZXRVaW50OChlKSk6bj09PTI/QmlnSW50KHQuZ2V0VWludDE2KGUsITApKTpuPT09ND9CaWdJbnQodC5nZXRVaW50MzIoZSwhMCkpOnQuZ2V0QmlnVWludDY0KGUsITApfWZ1bmN0aW9uIEd0KHQsZSxyLG4pe2xldCBvPVJbcl07aWYobz09PTEpe3Quc2V0VWludDgoZSxOdW1iZXIobiYweGZmbikpO3JldHVybn1pZihvPT09Mil7dC5zZXRVaW50MTYoZSxOdW1iZXIobiYweGZmZmZuKSwhMCk7cmV0dXJufWlmKG89PT00KXt0LnNldFVpbnQzMihlLE51bWJlcihuJjB4ZmZmZmZmZmZuKSwhMCk7cmV0dXJufXQuc2V0QmlnVWludDY0KGUsbiYweGZmZmZmZmZmZmZmZmZmZmZuLCEwKX1mdW5jdGlvbiBZdCh0LGUscil7bGV0IG49QmlnSW50KHIud2lkdGgpLG89Z3QodCxlLHIudW5pdCk+PkJpZ0ludChyLmJpdCkmKDFuPDxuKS0xbjtyZXR1cm4gci51bml0WzBdPT09ImkiJiZvJjFuPDxuLTFuJiYoby09MW48PG4pLHIud2lkdGg+NTM/bzpOdW1iZXIobyl9ZnVuY3Rpb24gVnQodCxlLHIsbil7bGV0IG89QmlnSW50KHIud2lkdGgpLGk9QmlnSW50KHIuYml0KSxjPSgxbjw8byktMW4scz1jPDxpLHU9Z3QodCxlLHIudW5pdCkscD0odHlwZW9mIG49PSJiaWdpbnQiP246QmlnSW50KE1hdGgudHJ1bmMobikpKSZjO0d0KHQsZSxyLnVuaXQsdSZ+c3xwPDxpKX12YXIgdnQ9eyJ1dGYtOCI6bmV3IFRleHRFbmNvZGVyKCJ1dGYtOCIpLCJ1dGYtMTZsZSI6bmV3IFRleHRFbmNvZGVyKCJ1dGYtMTZsZSIpfSxqdD17InV0Zi04IjpuZXcgVGV4dERlY29kZXIoInV0Zi04Iix7aWdub3JlQk9NOiEwfSksInV0Zi0xNmxlIjpuZXcgVGV4dERlY29kZXIoInV0Zi0xNmxlIix7aWdub3JlQk9NOiEwfSl9O2Z1bmN0aW9uIFh0KHQsZSxyLG4pe2xldCBvPW5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCtlLHIpLGk9bj09PSJ1dGYtMTZsZSI/MjoxLGM9cjtmb3IobGV0IHM9MDtzK2k8PXI7cys9aSlpZihvW3NdPT09MCYmKGk9PT0xfHxvW3MrMV09PT0wKSl7Yz1zO2JyZWFrfXJldHVybiBqdFtuXS5kZWNvZGUoby5zdWJhcnJheSgwLGMpKX1mdW5jdGlvbiBadCh0LGUscixuLG8pe2xldCBpPW5ldyBVaW50OEFycmF5KHQuYnVmZmVyLHQuYnl0ZU9mZnNldCtlLHIpO2kuZmlsbCgwKTtsZXQgcz1yLShuPT09InV0Zi0xNmxlIj8yOjEpO2lmKHM8PTApcmV0dXJuO2xldCB1PXZ0W25dLmVuY29kZShTdHJpbmcobz8/IiIpKTtpLnNldCh1LnN1YmFycmF5KDAsTWF0aC5taW4odS5sZW5ndGgscykpKX1mdW5jdGlvbiBxdCh0LGUscixuKXtsZXQgbz1uLmVsZW1lbnRTaXplPjA/ci9uLmVsZW1lbnRTaXplOjAsaT1bXTtmb3IobGV0IGM9MDtjPG87YysrKWkucHVzaCh3dCh0LGUrYypuLmVsZW1lbnRTaXplLG4uZWxlbWVudFR5cGUsbi5lbGVtZW50U2l6ZSkpO3JldHVybiBpfWZ1bmN0aW9uIEt0KHQsZSxyLG4sbyl7bGV0IGk9bi5lbGVtZW50U2l6ZT4wP3Ivbi5lbGVtZW50U2l6ZTowLGM9bz8/W107Zm9yKGxldCBzPTA7czxpO3MrKylUdCh0LGUrcypuLmVsZW1lbnRTaXplLG4uZWxlbWVudFR5cGUsbi5lbGVtZW50U2l6ZSxjW3NdKX1mdW5jdGlvbiB3dCh0LGUscixuKXtzd2l0Y2goci50YWcpe2Nhc2UiYmFzaWMiOnJldHVybiB6KHQsZSxyLmtpbmQpO2Nhc2UiYml0ZmllbGQiOnJldHVybiBZdCh0LGUscik7Y2FzZSJzdHJpbmciOnJldHVybiBYdCh0LGUsbixyLmVuY29kaW5nKTtjYXNlInN0cnVjdCI6Y2FzZSJ1bmlvbiI6cmV0dXJuIEsodCxlLHIuZmllbGRzKTtjYXNlImFycmF5IjpyZXR1cm4gcXQodCxlLG4scil9fWZ1bmN0aW9uIFR0KHQsZSxyLG4sbyl7c3dpdGNoKHIudGFnKXtjYXNlImJhc2ljIjpYKHQsZSx7azpyLmtpbmQsdjpvfSk7YnJlYWs7Y2FzZSJiaXRmaWVsZCI6VnQodCxlLHIsbz8/MCk7YnJlYWs7Y2FzZSJzdHJpbmciOlp0KHQsZSxuLHIuZW5jb2Rpbmcsbyk7YnJlYWs7Y2FzZSJzdHJ1Y3QiOmNhc2UidW5pb24iOkl0KHQsZSxyLmZpZWxkcyxvPz97fSk7YnJlYWs7Y2FzZSJhcnJheSI6S3QodCxlLG4scixvKTticmVha319ZnVuY3Rpb24gSyh0LGUscil7bGV0IG49e307Zm9yKGxldCBvIG9mIHIpe2xldCBpPXd0KHQsZStvLm9mZnNldCxvLnR5cGUsby5zaXplKTtpZihvLm5vbm51bGwmJmk9PT0wKXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogZGVjb2RlOiAnIScgZmllbGQgIiR7by5uYW1lfSIgZ290IDAgKEMgZGlkIG5vdCBmaWxsIGl0LCBvciBkZWNvZGUgd2FzIGNhbGxlZCBvbiBhbiB1bmZpbGxlZCBzbG90KWApO25bby5uYW1lXT1pfXJldHVybiBufWZ1bmN0aW9uIEl0KHQsZSxyLG4pe2ZvcihsZXQgbyBvZiByKW5bby5uYW1lXSE9PXZvaWQgMCYmVHQodCxlK28ub2Zmc2V0LG8udHlwZSxvLnNpemUsbltvLm5hbWVdKX1mdW5jdGlvbiBRdCh0KXtsZXR7ZmllbGRzOmUsc2l6ZTpyLG1heEVmZmVjdGl2ZUFsaWduOm59PWh0KHQpO3JldHVybntmaWVsZHM6ZSxzaXplOnIsc3RydWN0QWxpZ246bixkZWNvZGU6bz0+Syh0eXBlb2Ygbz09Im51bWJlciI/bmV3IERhdGFWaWV3KHh0LnJlYWRCeXRlcyhvLHIpKTpuZXcgRGF0YVZpZXcobyksMCxlKSxhbGxvYzoobz0+e2lmKG8hPT12b2lkIDAmJighTnVtYmVyLmlzSW50ZWdlcihvKXx8bzwxKSl0aHJvdyBuZXcgRXJyb3IoImZmaS1zdHJ1Y3Q6IGFsbG9jKG4pIHJlcXVpcmVzIGFuIGludGVnZXIgbiA+PSAxIChQQUIoMCkgbmV2ZXIgZXNjYXBlcyBcdTIwMTQgcGFzcyBOVUxMIGZvciBhbiBlbXB0eSBwb2ludGVyIHBvc2l0aW9uKSIpO3JldHVybiBuZXcgeChyKihvPz8xKSl9KSxlbmNvZGU6KChvLGksYyk9PntpZihvPT1udWxsKXRocm93IG5ldyBFcnJvcigiZmZpLXN0cnVjdDogZW5jb2RlKHYpIHJlcXVpcmVzIGFuIGFyZ3VtZW50OyB1c2UgYWxsb2MoKSBmb3IgYSB6ZXJvZWQgb3V0LXBhcmFtIHNsb3QiKTtsZXQgcz1pPz9uZXcgeChyKTtyZXR1cm4gSXQobmV3IERhdGFWaWV3KHMpLGM/PzAsZSxvKSxzfSksb2Zmc2V0T2Y6bz0+e2ZvcihsZXQgaSBvZiBlKWlmKGkubmFtZT09PW8pcmV0dXJuIGkub2Zmc2V0O3Rocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogbm8gZmllbGQgIiR7b30iYCl9fX1mdW5jdGlvbiBKdCh0LGUscil7bGV0IG49ZVsiIyJdO2lmKG4hPT12b2lkIDAmJm4hPT10KXRocm93IG5ldyBFcnJvcihgZmZpLXN0cnVjdDogJHt0fSgpIHJlY2VpdmVkIGEgJyR7U3RyaW5nKG4pfScgZGVjbGFyYXRpb24gKGtpbmQgbWlzbWF0Y2ggXHUyMDE0IHVzZSAke259KCkgZm9yIGl0KWApO2xldCBvPWVbIiNwYWNrIl07aWYocj09PXZvaWQgMCYmbyE9PXZvaWQgMClyPW87ZWxzZSBpZihyIT09dm9pZCAwJiZvIT09dm9pZCAwJiZyIT09byl0aHJvdyBuZXcgRXJyb3IoYGZmaS1zdHJ1Y3Q6ICNwYWNrIGNvbmZsaWN0OiBvcHRzLnBhY2s9JHtyfSB2cyBkZWNsYXJhdGlvbiAke1N0cmluZyhvKX1gKTtsZXQgaT17IiMiOnR9O3IhPT12b2lkIDAmJihpWyIjcGFjayJdPXIpO2ZvcihsZXRbYyxzXW9mIE9iamVjdC5lbnRyaWVzKGUpKWMuc3RhcnRzV2l0aCgiIyIpfHwoaVtjXT1zKTtyZXR1cm4gaX1mdW5jdGlvbiBIKHQsZSxyKXtsZXQgbj10eXBlb2YgdD09InN0cmluZyI7cmV0dXJuIFF0KEp0KCJzdHJ1Y3QiLG4/ZTp0LChuP3I6ZSk/LnBhY2spKX12YXIgdGU9eyIjIjoic3RydWN0IixjYjoidTMyIixscFJlc2VydmVkOiI8PnB0ciIsbHBEZXNrdG9wOiI8PnB0ciIsbHBUaXRsZToiPD5wdHIiLGR3WDoidTMyIixkd1k6InUzMiIsZHdYU2l6ZToidTMyIixkd1lTaXplOiJ1MzIiLGR3WENvdW50Q2hhcnM6InUzMiIsZHdZQ291bnRDaGFyczoidTMyIixkd0ZpbGxBdHRyaWJ1dGU6InUzMiIsZHdGbGFnczoidTMyIix3U2hvd1dpbmRvdzoidTE2QFNob3dXaW5kb3dDbWQiLGNiUmVzZXJ2ZWQyOiJ1MTYiLGxwUmVzZXJ2ZWQyOiI8PnB0ciIsaFN0ZElucHV0OiI8SEZJTEU+cHRyIixoU3RkT3V0cHV0OiI8SEZJTEU+cHRyIixoU3RkRXJyb3I6IjxIRklMRT5wdHIifSxHPUgoIlNUQVJUVVBJTkZPVyIsdGUpLGVlPXsiIyI6InN0cnVjdCIsaFByb2Nlc3M6IjxIUFJPQ0VTUz5wdHIhIixoVGhyZWFkOiI8SFRIUkVBRD5wdHIhIixkd1Byb2Nlc3NJZDoidTMyIixkd1RocmVhZElkOiJ1MzIifSxRPUgoIlBST0NFU1NfSU5GT1JNQVRJT04iLGVlKTt2YXIgTj0odCxlLHIpPT5tdCgia2VybmVsMzIuZGxsIix0LGUsciksRnQ9TigiQ3JlYXRlUGlwZSIsIjw+cHRyIDw+cHRyIDw+cHRyIHUzMiAtPiBpMzIiKSxKPU4oIlNldEhhbmRsZUluZm9ybWF0aW9uIiwiPEhGSUxFPnB0ciEgdTMyIHUzMiAtPiBpMzIiKSxTdD1OKCJDcmVhdGVQcm9jZXNzVyIsIjxXQ0hBUj5wdHIgPFdDSEFSPnB0ciA8PnB0ciA8PnB0ciBpMzIgdTMyIDw+cHRyIDxXQ0hBUj5wdHIgPFNUQVJUVVBJTkZPVz5wdHIgPFBST0NFU1NfSU5GT1JNQVRJT04+cHRyIC0+IGkzMiIse1NUQVJUVVBJTkZPVzpHfSksQ3Q9TigiV2FpdEZvclNpbmdsZU9iamVjdCIsIjw+cHRyIHUzMiAtPiB1MzIiKSxOdD1OKCJHZXRFeGl0Q29kZVByb2Nlc3MiLCI8SFBST0NFU1M+cHRyISA8QllURT5wdHIgLT4gaTMyIiksQT1OKCJDbG9zZUhhbmRsZSIsIjw+cHRyIC0+IGkzMiIpO3ZhciBidD1OKCJSZWFkRmlsZSIsIjxIRklMRT5wdHIhIDxCWVRFPnB0ciB1MzIgPEJZVEU+cHRyIDw+cHRyIC0+IGkzMiIpO3ZhciB0dD1OKCJHZXRMYXN0RXJyb3IiLCIgLT4gdTMyIikseXQ9TigiR2V0U3lzdGVtRGlyZWN0b3J5VyIsIjxCWVRFPnB0ciB1MzIgLT4gdTMyIik7dmFyIHJlPXQ9Pnt0cnl7bGV0IGU9T3Qub3BlbigiZGlhZy5sb2ciLCJhIik7ZSYmKGUucHV0cyhgJHtEYXRlLm5vdygpfSAke3R9CmApLGUuY2xvc2UoKSl9Y2F0Y2h7fX0sZXQ9MSxuZT0yNTYsb2U9NDI5NDk2NzI5NSxCPUR0Lldvcmtlci5wYXJlbnQsUHQ9IkM6XFxXaW5kb3dzXFxTeXN0ZW0zMiI7dHJ5e2xldCB0PSQuYWxsb2MoMjU2KSxyPXl0KHQsMjU2KT4wPyQuZGVjb2RlKHQpOiIiO3ImJihQdD1yKX1jYXRjaCh0KXtyZSgiU1lTLURJUi1GQUlMOiAiK1N0cmluZyh0KSl9dmFyIHJ0PUgoIlBJUEVfSEFORExFUyIse2hSZWFkOiI8SEZJTEU+cHRyISIsaFdyaXRlOiI8SEZJTEU+cHRyISJ9KTtmdW5jdGlvbiBpZSh0LGUpe2xldCByPXJ0LmFsbG9jKCk7aWYoIUZ0KHIucHRyLHIucHRyK3J0Lm9mZnNldE9mKCJoV3JpdGUiKSxPLDApKXRocm93IG5ldyBFcnJvcigiQ3JlYXRlUGlwZSBlcnI9Iit0dCgpKTtsZXR7aFJlYWQ6bixoV3JpdGU6b309cnQuZGVjb2RlKHIpO0oobyxldCxldCksSihuLGV0LDApO2xldCBpPVEuYWxsb2MoKSxjPWAke1B0fVxcY21kLmV4ZSAvdSAvYyAke2V9YDtpZighU3QoTyxjLE8sTywxLDAsTyxPLHtjYjpHLnNpemUsZHdGbGFnczpuZSxoU3RkT3V0cHV0Om8saFN0ZEVycm9yOm99LGkucHRyKSl0aHJvdyBBKG4pLEEobyksbmV3IEVycm9yKCJDcmVhdGVQcm9jZXNzVyBlcnI9Iit0dCgpKyIgY21kPSIrYyk7bGV0e2hQcm9jZXNzOnMsaFRocmVhZDp1LGR3UHJvY2Vzc0lkOnB9PVEuZGVjb2RlKGkpO0EodSksQShvKSxCLnBvc3RNZXNzYWdlKHt0eXBlOiJpbmZvIixpZDp0LHBpZDpwfSk7bGV0IGg9bmV3IHgoNDA5NiksRj1uZXcgVWludDhBcnJheShoKSxUPW5ldyB4KDQpLEk9bmV3IFVpbnQzMkFycmF5KFQpO2Zvcig7SVswXT0wLCEhYnQobixoLDQwOTYsVCxPKTspe2xldCBTPUlbMF07aWYoUz09PTApYnJlYWs7Qi5wb3N0TWVzc2FnZSh7dHlwZToiZGF0YSIsaWQ6dCxjaHVuazpGLnNsaWNlKDAsUyl9KX1DdChzLG9lKTtsZXQgRT1uZXcgeCg0KSxQPW5ldyBJbnQzMkFycmF5KEUpO050KHMsRSk7bGV0IHc9UFswXTtyZXR1cm4gQShuKSxBKHMpLHd9Qi5vbm1lc3NhZ2U9dD0+e2xldCBlPXQuZGF0YTtpZihlLnR5cGU9PT0icnVuIiYmdHlwZW9mIGUuY21kPT0ic3RyaW5nIil7bGV0IHI9LTEsbj1udWxsO3RyeXtyPWllKGUuaWQsZS5jbWQpfWNhdGNoKG8pe249U3RyaW5nKG8pfUIucG9zdE1lc3NhZ2Uoe3R5cGU6InJlc3VsdCIsaWQ6ZS5pZCxjb2RlOnIsZXJyb3I6bn0pfUIub25tZXNzYWdlPW51bGx9Owo=");
22295
22444
  bumpWorkers(1);
22296
22445
  const id = 1;
22297
22446
  let innerPid = null;
@@ -22431,7 +22580,6 @@ function parseShotOpts(params) {
22431
22580
  return { hwnd, area, mode };
22432
22581
  }
22433
22582
  var SRCCOPY = 13369376;
22434
- var DIB_RGB_COLORS = 0;
22435
22583
  var MAX_CAPTURE_PX = 4e7;
22436
22584
  var WIDE_BUF_CHARS = 512;
22437
22585
  var MAX_WINDOWS = 2e4;
@@ -22477,7 +22625,16 @@ function emitDib(hdc, hbm, w2, h2) {
22477
22625
  // biCompression 缺省 0 = BI_RGB
22478
22626
  biSizeImage: w2 * h2 * 4
22479
22627
  });
22480
- const got = GetDIBits(hdc, hbm, 0, h2, pxB, bmi.ptr, DIB_RGB_COLORS);
22628
+ const got = GetDIBits(
22629
+ hdc,
22630
+ hbm,
22631
+ 0,
22632
+ h2,
22633
+ pxB,
22634
+ bmi.ptr,
22635
+ 0
22636
+ /* ColorUse.RGB_COLORS */
22637
+ );
22481
22638
  if (got !== h2)
22482
22639
  return null;
22483
22640
  const out = new Uint8Array(BMP_HEADERS_SIZE + px.byteLength);
@@ -22744,7 +22901,14 @@ API\uFF08\u914D\u7F6E token \u540E\u9700 Authorization: Bearer <token>\uFF0C\u67
22744
22901
  POST /input body = JSON \u6570\u7EC4\uFF08\u6279\u91CF\u6CE8\u5165\uFF1Bx/y \u7269\u7406\u50CF\u7D20\uFF09\uFF1A
22745
22902
  {"t":"move","x":,"y":} | {"t":"down|up","btn":"left|right|middle|x1|x2","x":,"y":?} |
22746
22903
  {"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`;
22904
+ \u2192 JSON {sent,expected}\uFF1B\u6309 sleep \u5207\u6BB5\uFF0C\u6BB5\u5185\u4E00\u6B21 SendInput \u539F\u5B50\u6CE8\u5165
22905
+ POST /upload ?path=<\u76EE\u6807\u8DEF\u5F84>&mkdir=0 body=\u539F\u59CB\u5B57\u8282\uFF08\u975E\u7A7A\uFF09\u2192 JSON {bytes,path}
22906
+ \u9ED8\u8BA4\u9010\u5C42\u5EFA\u7236\u76EE\u5F55\uFF08mkdir=0 \u4E25\u683C\u8981\u6C42\u7236\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u9632\u8DEF\u5F84 typo\uFF09\uFF1B
22907
+ \u539F\u5B50\u5199\uFF1A\u5148\u5199 <path>.uploading \u518D MoveFileEx \u8986\u76D6\uFF0C\u770B\u4E0D\u5230\u534A\u622A\u6587\u4EF6\u3002
22908
+ \u65E0 SMB \u73AF\u5883\u7684\u4F20\u6587\u4EF6\u901A\u9053\uFF0C\u8DEF\u5F84\u5168\u653E\u5F00\u30028MB \u5206\u5757\u5199\u76D8\uFF08CRT \u5355\u5757\u5927\u5199
22909
+ \u5728 XP \u7F51\u7EDC\u76D8 ~64MiB \u8FB9\u754C\u4F1A\u88AB\u6574\u5757\u62D2\u7EDD\uFF09\uFF0CXP/win7 \u5B9E\u6D4B 100MB+ OK
22910
+ GET /download ?path=<\u6587\u4EF6\u8DEF\u5F84> \u2192 \u539F\u59CB\u5B57\u8282\u6D41\uFF08application/octet-stream\uFF0CX-Bytes \u5934\uFF1B
22911
+ \u5206\u5757\u8BFB\u5230 EOF \u65E0\u5927\u5C0F\u4E0A\u9650\uFF09\u2014\u2014type \u547D\u4EE4\u7684\u4E8C\u8FDB\u5236\u5B89\u5168\u7248`;
22748
22912
  function usageResponse() {
22749
22913
  return new Response(USAGE, { headers: { "Content-Type": "text/plain; charset=utf-8" } });
22750
22914
  }
@@ -22809,10 +22973,23 @@ function vkOf(key) {
22809
22973
  }
22810
22974
  throw new Error("bad key: " + JSON.stringify(key) + " (a-z/0-9|name|0..0xFFFF)");
22811
22975
  }
22976
+ function mkdirParents(dest) {
22977
+ const segs = dest.replace(/\//g, "\\").split("\\");
22978
+ let acc = "";
22979
+ for (let i2 = 0; i2 < segs.length - 1; i2++) {
22980
+ acc = acc === "" ? segs[i2] : acc + "\\" + segs[i2];
22981
+ if (acc === "" || /^[A-Za-z]:$/.test(acc))
22982
+ continue;
22983
+ try {
22984
+ os7.mkdir(acc);
22985
+ } catch {
22986
+ }
22987
+ }
22988
+ }
22812
22989
  var server = createServer(async (req) => {
22813
22990
  const t0 = Date.now();
22814
22991
  const path = new URL(req.url).pathname;
22815
- const isApi = req.method === "POST" && (path === "/exec" || path === "/set_resolution" || path === "/input") || req.method === "GET" && (path === "/window_list" || path === "/screenshot" || path === "/tray_list");
22992
+ const isApi = req.method === "POST" && (path === "/exec" || path === "/set_resolution" || path === "/input" || path === "/upload") || req.method === "GET" && (path === "/window_list" || path === "/screenshot" || path === "/tray_list" || path === "/download");
22816
22993
  if (!isApi)
22817
22994
  return usageResponse();
22818
22995
  const denied = authCheck(req);
@@ -23031,6 +23208,103 @@ var server = createServer(async (req) => {
23031
23208
  return jsonError(504, String(ex));
23032
23209
  }
23033
23210
  }
23211
+ if (req.method === "POST" && path === "/upload") {
23212
+ const bad = (msg) => {
23213
+ logReq(t0, "POST /upload", 400, msg);
23214
+ return jsonError(400, msg);
23215
+ };
23216
+ const params = new URL(req.url).searchParams;
23217
+ const dest = params.get("path");
23218
+ if (!dest)
23219
+ return bad("path=<\u76EE\u6807\u8DEF\u5F84>");
23220
+ let bytes;
23221
+ try {
23222
+ bytes = new Uint8Array(await req.arrayBuffer());
23223
+ } catch (ex) {
23224
+ return bad("bad body: " + String(ex));
23225
+ }
23226
+ if (bytes.length === 0)
23227
+ return bad("empty body");
23228
+ try {
23229
+ if (params.get("mkdir") !== "0")
23230
+ mkdirParents(dest);
23231
+ const tmp = dest + ".uploading";
23232
+ const f2 = std2.open(tmp, "wb");
23233
+ if (!f2)
23234
+ throw new Error("open for write failed: " + tmp);
23235
+ let w2 = 0;
23236
+ try {
23237
+ const CHUNK = 8 * 1024 * 1024;
23238
+ for (let off = 0; off < bytes.length; off += CHUNK) {
23239
+ const n2 = f2.write(bytes.buffer, off, Math.min(CHUNK, bytes.length - off));
23240
+ if (n2 <= 0)
23241
+ break;
23242
+ w2 += n2;
23243
+ }
23244
+ } finally {
23245
+ f2.close();
23246
+ }
23247
+ if (w2 !== bytes.length)
23248
+ throw new Error("short write: " + w2 + "/" + bytes.length);
23249
+ if (!MoveFileEx(
23250
+ tmp,
23251
+ dest,
23252
+ 1
23253
+ /* MoveFileFlag.REPLACE_EXISTING */
23254
+ ))
23255
+ throw new Error("MoveFileEx failed (GetLastError " + GetLastError() + "): " + tmp + " -> " + dest);
23256
+ } catch (ex) {
23257
+ logReq(t0, "POST /upload", 500, String(ex));
23258
+ return jsonError(500, String(ex));
23259
+ }
23260
+ logReq(t0, "POST /upload", 200, bytes.length + "B -> " + dest);
23261
+ return new Response(JSON.stringify({ bytes: bytes.length, path: dest }), { headers: { "Content-Type": "application/json" } });
23262
+ }
23263
+ if (req.method === "GET" && path === "/download") {
23264
+ const p2 = new URL(req.url).searchParams.get("path");
23265
+ if (!p2) {
23266
+ logReq(t0, "GET /download", 400, "path=<\u6587\u4EF6\u8DEF\u5F84>");
23267
+ return jsonError(400, "path=<\u6587\u4EF6\u8DEF\u5F84>");
23268
+ }
23269
+ let f2 = null;
23270
+ try {
23271
+ f2 = std2.open(p2, "rb");
23272
+ } catch (ex) {
23273
+ logReq(t0, "GET /download", 500, String(ex));
23274
+ return jsonError(500, String(ex));
23275
+ }
23276
+ if (f2 === null) {
23277
+ logReq(t0, "GET /download", 404, p2);
23278
+ return jsonError(404, "cannot open: " + p2);
23279
+ }
23280
+ try {
23281
+ const chunks = [];
23282
+ const buf = new Uint8Array(64 * 1024);
23283
+ let total = 0;
23284
+ for (; ; ) {
23285
+ const n2 = f2.read(buf.buffer, 0, buf.length);
23286
+ if (n2 <= 0)
23287
+ break;
23288
+ chunks.push(n2 === buf.length ? buf.slice() : buf.slice(0, n2));
23289
+ total += n2;
23290
+ }
23291
+ const all = new Uint8Array(total);
23292
+ let off = 0;
23293
+ for (const c2 of chunks) {
23294
+ all.set(c2, off);
23295
+ off += c2.length;
23296
+ }
23297
+ logReq(t0, "GET /download", 200, total + "B <- " + p2);
23298
+ return new Response(all, {
23299
+ headers: { "Content-Type": "application/octet-stream", "X-Bytes": String(total) }
23300
+ });
23301
+ } catch (ex) {
23302
+ logReq(t0, "GET /download", 500, String(ex));
23303
+ return jsonError(500, String(ex));
23304
+ } finally {
23305
+ f2.close();
23306
+ }
23307
+ }
23034
23308
  return usageResponse();
23035
23309
  });
23036
23310
  var rc = server.listen(8080, "0.0.0.0");