Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
titaniumnetwork-dev
GitHub Repository: titaniumnetwork-dev/Ultraviolet
Path: blob/main/src/client/location.js
304 views
1
import EventEmitter from "events";
2
3
/**
4
* @typedef {import('./index').default} UVClient
5
*/
6
7
class LocationApi extends EventEmitter {
8
/**
9
*
10
* @param {UVClient} ctx
11
*/
12
constructor(ctx) {
13
super();
14
this.ctx = ctx;
15
this.window = ctx.window;
16
this.location = this.window.location;
17
this.WorkerLocation = this.ctx.worker ? this.window.WorkerLocation : null;
18
this.workerLocProto = this.WorkerLocation
19
? this.WorkerLocation.prototype
20
: {};
21
this.keys = [
22
"href",
23
"protocol",
24
"host",
25
"hostname",
26
"port",
27
"pathname",
28
"search",
29
"hash",
30
"origin",
31
];
32
this.HashChangeEvent = this.window.HashChangeEvent || null;
33
this.href = this.WorkerLocation
34
? ctx.nativeMethods.getOwnPropertyDescriptor(this.workerLocProto, "href")
35
: ctx.nativeMethods.getOwnPropertyDescriptor(this.location, "href");
36
}
37
overrideWorkerLocation(parse) {
38
if (!this.WorkerLocation) return false;
39
const uv = this;
40
41
for (const key of this.keys) {
42
this.ctx.overrideDescriptor(this.workerLocProto, key, {
43
get: () => {
44
return parse(uv.href.get.call(this.location))[key];
45
},
46
});
47
}
48
49
return true;
50
}
51
emulate(parse, wrap) {
52
const emulation = {};
53
const that = this;
54
55
for (const key of that.keys) {
56
this.ctx.nativeMethods.defineProperty(emulation, key, {
57
get() {
58
return parse(that.href.get.call(that.location))[key];
59
},
60
set:
61
key !== "origin"
62
? function (val) {
63
switch (key) {
64
case "href":
65
that.location.href = wrap(val);
66
break;
67
case "hash":
68
that.emit(
69
"hashchange",
70
emulation.href,
71
val.trim().startsWith("#")
72
? new URL(val.trim(), emulation.href).href
73
: new URL("#" + val.trim(), emulation.href).href,
74
that
75
);
76
break;
77
default:
78
{
79
const url = new URL(emulation.href);
80
url[key] = val;
81
that.location.href = wrap(url.href);
82
}
83
break;
84
}
85
}
86
: undefined,
87
configurable: false,
88
enumerable: true,
89
});
90
}
91
92
if ("reload" in this.location) {
93
this.ctx.nativeMethods.defineProperty(emulation, "reload", {
94
value: this.ctx.wrap(this.location, "reload", (target, that) => {
95
return target.call(that === emulation ? this.location : that);
96
}),
97
writable: false,
98
enumerable: true,
99
});
100
}
101
102
if ("replace" in this.location) {
103
this.ctx.nativeMethods.defineProperty(emulation, "replace", {
104
value: this.ctx.wrap(this.location, "assign", (target, that, args) => {
105
if (!args.length || that !== emulation) target.call(that);
106
that = this.location;
107
let [input] = args;
108
109
const url = new URL(input, emulation.href);
110
return target.call(
111
that === emulation ? this.location : that,
112
wrap(url.href)
113
);
114
}),
115
writable: false,
116
enumerable: true,
117
});
118
}
119
120
if ("assign" in this.location) {
121
this.ctx.nativeMethods.defineProperty(emulation, "assign", {
122
value: this.ctx.wrap(this.location, "assign", (target, that, args) => {
123
if (!args.length || that !== emulation) target.call(that);
124
that = this.location;
125
let [input] = args;
126
127
const url = new URL(input, emulation.href);
128
return target.call(
129
that === emulation ? this.location : that,
130
wrap(url.href)
131
);
132
}),
133
writable: false,
134
enumerable: true,
135
});
136
}
137
138
if ("ancestorOrigins" in this.location) {
139
this.ctx.nativeMethods.defineProperty(emulation, "ancestorOrigins", {
140
get() {
141
const arr = [];
142
if (that.window.DOMStringList)
143
that.ctx.nativeMethods.setPrototypeOf(
144
arr,
145
that.window.DOMStringList.prototype
146
);
147
return arr;
148
},
149
set: undefined,
150
enumerable: true,
151
});
152
}
153
154
this.ctx.nativeMethods.defineProperty(emulation, "toString", {
155
value: this.ctx.wrap(this.location, "toString", () => {
156
return emulation.href;
157
}),
158
enumerable: true,
159
writable: false,
160
});
161
162
this.ctx.nativeMethods.defineProperty(emulation, Symbol.toPrimitive, {
163
value: () => emulation.href,
164
writable: false,
165
enumerable: false,
166
});
167
168
if (this.ctx.window.Location)
169
this.ctx.nativeMethods.setPrototypeOf(
170
emulation,
171
this.ctx.window.Location.prototype
172
);
173
174
return emulation;
175
}
176
}
177
178
export default LocationApi;
179
180