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