1 | "use strict";
|
2 |
|
3 | const Element = require("./Element");
|
4 | const getLocation = require("./getLocation");
|
5 | const Navigator = require("./Navigator");
|
6 | const url = require("url");
|
7 | const {atob, btoa} = require("./atobtoa");
|
8 | const {Event, CustomEvent} = require("./Events");
|
9 | const {EventEmitter} = require("events");
|
10 | const {performance} = require("perf_hooks");
|
11 |
|
12 | module.exports = function Window(resp, windowObjects = {console}, innerWidth = 760, innerHeight = 760) {
|
13 | const emitter = new EventEmitter();
|
14 | const navigator = Navigator(resp);
|
15 | let location = getLocation(resp.request);
|
16 |
|
17 | let pageXOffset = 0;
|
18 | let pageYOffset = 0;
|
19 |
|
20 | const window = {
|
21 | _resize: resizeWindow,
|
22 | addEventListener,
|
23 | dispatchEvent,
|
24 | matchMedia,
|
25 | history: {
|
26 | replaceState
|
27 | },
|
28 | innerHeight,
|
29 | innerWidth,
|
30 | location,
|
31 | navigator,
|
32 | removeEventListener,
|
33 | scroll,
|
34 | requestAnimationFrame: (callback) => {
|
35 | callback(performance.now());
|
36 | return 0;
|
37 | },
|
38 | cancelAnimationFrame: () => {},
|
39 | get window() {
|
40 | return this;
|
41 | },
|
42 | Element,
|
43 | Event,
|
44 | CustomEvent,
|
45 | atob,
|
46 | btoa,
|
47 | ...windowObjects,
|
48 | };
|
49 |
|
50 | Object.defineProperty(window, "pageXOffset", {
|
51 | get: () => pageXOffset
|
52 | });
|
53 |
|
54 | Object.defineProperty(window, "pageYOffset", {
|
55 | get: () => pageYOffset
|
56 | });
|
57 |
|
58 | Object.defineProperty(window, "self", {
|
59 | get: () => window
|
60 | });
|
61 |
|
62 | Object.defineProperty(window, "location", {
|
63 | get: () => location,
|
64 | set(value) {
|
65 | const previousHref = location.href;
|
66 | let newLocation = getLocation({url: value});
|
67 |
|
68 | if (!newLocation.host) {
|
69 | newLocation = getLocation({url: url.resolve(previousHref, value)});
|
70 | }
|
71 |
|
72 | if (previousHref + newLocation.hash !== newLocation.href) {
|
73 | emitter.emit("unload");
|
74 | }
|
75 |
|
76 | location = newLocation;
|
77 | }
|
78 | });
|
79 |
|
80 | return window;
|
81 |
|
82 | function addEventListener(...args) {
|
83 | emitter.on(...args);
|
84 | }
|
85 |
|
86 | function dispatchEvent(event, ...args) {
|
87 | if (event === undefined) throw new TypeError("Failed to execute 'dispatchEvent' on 'EventTarget': 1 argument required, but only 0 present.");
|
88 | if (typeof event === "string") {
|
89 | return emitter.emit(event, ...args);
|
90 | }
|
91 |
|
92 | if (!event.type) return;
|
93 | return emitter.emit(event.type, event);
|
94 | }
|
95 |
|
96 | function removeEventListener(...args) {
|
97 | emitter.removeListener(...args);
|
98 | }
|
99 |
|
100 | function matchMedia(media) {
|
101 | if (media === undefined) throw new TypeError("Failed to execute 'matchMedia' on 'Window': 1 argument required, but only 0 present.");
|
102 | if (typeof media === "string") {
|
103 | window.styleMedia = window.styleMedia || { type: "screen" };
|
104 | return {
|
105 | media,
|
106 | matches: media === window.styleMedia.type
|
107 | };
|
108 | }
|
109 | }
|
110 |
|
111 | function replaceState(ign1, ign2, relativeUrl) {
|
112 | const newUrl = url.parse(relativeUrl);
|
113 | location.path = newUrl.path;
|
114 | location.pathname = newUrl.pathname;
|
115 | location.search = newUrl.search;
|
116 | location.href = url.format(location);
|
117 | }
|
118 |
|
119 | function scroll(xCoord, yCoord) {
|
120 | if (xCoord && typeof xCoord === "object") {
|
121 | const {top, left} = xCoord;
|
122 | pageYOffset = !isNaN(top) ? top : pageYOffset;
|
123 | pageXOffset = !isNaN(left) ? left : pageXOffset;
|
124 | } else {
|
125 | if (xCoord !== undefined) pageXOffset = xCoord;
|
126 | if (yCoord !== undefined) pageYOffset = yCoord;
|
127 | }
|
128 | dispatchEvent("scroll");
|
129 | }
|
130 |
|
131 | function resizeWindow(newInnerWidth, newInnerHeight) {
|
132 | if (newInnerWidth !== undefined) {
|
133 | window.innerWidth = newInnerWidth;
|
134 | }
|
135 | if (newInnerHeight !== undefined) {
|
136 | window.innerHeight = newInnerHeight;
|
137 | }
|
138 | window.dispatchEvent("resize");
|
139 | }
|
140 | };
|