UNPKG

3.67 kBJavaScriptView Raw
1"use strict";
2
3const Element = require("./Element");
4const getLocation = require("./getLocation");
5const Navigator = require("./Navigator");
6const url = require("url");
7const {atob, btoa} = require("./atobtoa");
8const {Event, CustomEvent} = require("./Events");
9const {EventEmitter} = require("events");
10const {performance} = require("perf_hooks");
11
12module.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};