window.js 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this
  3. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. "use strict";
  5. const { windows, isInteractive, isDocumentLoaded,
  6. getOuterId, isTopLevel } = require("../window/utils");
  7. const { InputPort } = require("./system");
  8. const { lift, merges, foldp, keepIf, start, Input } = require("../event/utils");
  9. const { patch } = require("diffpatcher/index");
  10. const { on } = require("../event/core");
  11. const { Sequence, seq, filter, object, pairs } = require("../util/sequence");
  12. // Create lazy iterators from the regular arrays, although
  13. // once https://github.com/mozilla/addon-sdk/pull/1314 lands
  14. // `windows` will be transforme to lazy iterators.
  15. // When iterated over belowe sequences items will represent
  16. // state of windows at the time of iteration.
  17. const opened = seq(function*() {
  18. const items = windows(null, {includePrivates: true});
  19. for (let item of items)
  20. yield [getOuterId(item), item];
  21. });
  22. const interactive = filter(([_, window]) => isInteractive(window), opened);
  23. const loaded = filter(([_, window]) => isDocumentLoaded(window), opened);
  24. // Helper function that converts given argument to a delta.
  25. const Update = window => window && object([getOuterId(window), window]);
  26. const Delete = window => window && object([getOuterId(window), null]);
  27. // Signal represents delta for last opened top level window.
  28. const LastOpened = lift(Update, new InputPort({topic: "domwindowopened"}));
  29. exports.LastOpened = LastOpened;
  30. // Signal represents delta for last top level window close.
  31. const LastClosed = lift(Delete, new InputPort({topic: "domwindowclosed"}));
  32. exports.LastClosed = LastClosed;
  33. const windowFor = document => document && document.defaultView;
  34. // Signal represent delta for last top level window document becoming interactive.
  35. const InteractiveDoc = new InputPort({topic: "chrome-document-interactive"});
  36. const InteractiveWin = lift(windowFor, InteractiveDoc);
  37. const LastInteractive = lift(Update, keepIf(isTopLevel, null, InteractiveWin));
  38. exports.LastInteractive = LastInteractive;
  39. // Signal represent delta for last top level window loaded.
  40. const LoadedDoc = new InputPort({topic: "chrome-document-loaded"});
  41. const LoadedWin = lift(windowFor, LoadedDoc);
  42. const LastLoaded = lift(Update, keepIf(isTopLevel, null, LoadedWin));
  43. exports.LastLoaded = LastLoaded;
  44. const initialize = input => {
  45. if (!input.initialized) {
  46. input.value = object(...input.value);
  47. Input.start(input);
  48. input.initialized = true;
  49. }
  50. };
  51. // Signal represents set of currently opened top level windows, updated
  52. // to new set any time window is opened or closed.
  53. const Opened = foldp(patch, opened, merges([LastOpened, LastClosed]));
  54. Opened[start] = initialize;
  55. exports.Opened = Opened;
  56. // Signal represents set of top level interactive windows, updated any
  57. // time new window becomes interactive or one get's closed.
  58. const Interactive = foldp(patch, interactive, merges([LastInteractive,
  59. LastClosed]));
  60. Interactive[start] = initialize;
  61. exports.Interactive = Interactive;
  62. // Signal represents set of top level loaded window, updated any time
  63. // new window becomes interactive or one get's closed.
  64. const Loaded = foldp(patch, loaded, merges([LastLoaded, LastClosed]));
  65. Loaded[start] = initialize;
  66. exports.Loaded = Loaded;