codekingpro/portable-devtools
114k
1'use strict'
2
3const { webidl } = require('../fetch/webidl')
4const { kEnumerableProperty } = require('../../core/util')
5const { kConstruct } = require('../../core/symbols')
6const { MessagePort } = require('node:worker_threads')
7
8/**
9 * @see https://html.spec.whatwg.org/multipage/comms.html#messageevent
10 */
11class MessageEvent extends Event {
12 #eventInit
13
14 constructor (type, eventInitDict = {}) {
15 if (type === kConstruct) {
16 super(arguments[1], arguments[2])
17 webidl.util.markAsUncloneable(this)
18 return
19 }
20
21 const prefix = 'MessageEvent constructor'
22 webidl.argumentLengthCheck(arguments, 1, prefix)
23
24 type = webidl.converters.DOMString(type, prefix, 'type')
25 eventInitDict = webidl.converters.MessageEventInit(eventInitDict, prefix, 'eventInitDict')
26
27 super(type, eventInitDict)
28
29 this.#eventInit = eventInitDict
30 webidl.util.markAsUncloneable(this)
31 }
32
33 get data () {
34 webidl.brandCheck(this, MessageEvent)
35
36 return this.#eventInit.data
37 }
38
39 get origin () {
40 webidl.brandCheck(this, MessageEvent)
41
42 return this.#eventInit.origin
43 }
44
45 get lastEventId () {
46 webidl.brandCheck(this, MessageEvent)
47
48 return this.#eventInit.lastEventId
49 }
50
51 get source () {
52 webidl.brandCheck(this, MessageEvent)
53
54 return this.#eventInit.source
55 }
56
57 get ports () {
58 webidl.brandCheck(this, MessageEvent)
59
60 if (!Object.isFrozen(this.#eventInit.ports)) {
61 Object.freeze(this.#eventInit.ports)
62 }
63
64 return this.#eventInit.ports
65 }
66
67 initMessageEvent (
68 type,
69 bubbles = false,
70 cancelable = false,
71 data = null,
72 origin = '',
73 lastEventId = '',
74 source = null,
75 ports = []
76 ) {
77 webidl.brandCheck(this, MessageEvent)
78
79 webidl.argumentLengthCheck(arguments, 1, 'MessageEvent.initMessageEvent')
80
81 return new MessageEvent(type, {
82 bubbles, cancelable, data, origin, lastEventId, source, ports
83 })
84 }
85
86 static createFastMessageEvent (type, init) {
87 const messageEvent = new MessageEvent(kConstruct, type, init)
88 messageEvent.#eventInit = init
89 messageEvent.#eventInit.data ??= null
90 messageEvent.#eventInit.origin ??= ''
91 messageEvent.#eventInit.lastEventId ??= ''
92 messageEvent.#eventInit.source ??= null
93 messageEvent.#eventInit.ports ??= []
94 return messageEvent
95 }
96}
97
98const { createFastMessageEvent } = MessageEvent
99delete MessageEvent.createFastMessageEvent
100
101/**
102 * @see https://websockets.spec.whatwg.org/#the-closeevent-interface
103 */
104class CloseEvent extends Event {
105 #eventInit
106
107 constructor (type, eventInitDict = {}) {
108 const prefix = 'CloseEvent constructor'
109 webidl.argumentLengthCheck(arguments, 1, prefix)
110
111 type = webidl.converters.DOMString(type, prefix, 'type')
112 eventInitDict = webidl.converters.CloseEventInit(eventInitDict)
113
114 super(type, eventInitDict)
115
116 this.#eventInit = eventInitDict
117 webidl.util.markAsUncloneable(this)
118 }
119
120 get wasClean () {
121 webidl.brandCheck(this, CloseEvent)
122
123 return this.#eventInit.wasClean
124 }
125
126 get code () {
127 webidl.brandCheck(this, CloseEvent)
128
129 return this.#eventInit.code
130 }
131
132 get reason () {
133 webidl.brandCheck(this, CloseEvent)
134
135 return this.#eventInit.reason
136 }
137}
138
139// https://html.spec.whatwg.org/multipage/webappapis.html#the-errorevent-interface
140class ErrorEvent extends Event {
141 #eventInit
142
143 constructor (type, eventInitDict) {
144 const prefix = 'ErrorEvent constructor'
145 webidl.argumentLengthCheck(arguments, 1, prefix)
146
147 super(type, eventInitDict)
148 webidl.util.markAsUncloneable(this)
149
150 type = webidl.converters.DOMString(type, prefix, 'type')
151 eventInitDict = webidl.converters.ErrorEventInit(eventInitDict ?? {})
152
153 this.#eventInit = eventInitDict
154 }
155
156 get message () {
157 webidl.brandCheck(this, ErrorEvent)
158
159 return this.#eventInit.message
160 }
161
162 get filename () {
163 webidl.brandCheck(this, ErrorEvent)
164
165 return this.#eventInit.filename
166 }
167
168 get lineno () {
169 webidl.brandCheck(this, ErrorEvent)
170
171 return this.#eventInit.lineno
172 }
173
174 get colno () {
175 webidl.brandCheck(this, ErrorEvent)
176
177 return this.#eventInit.colno
178 }
179
180 get error () {
181 webidl.brandCheck(this, ErrorEvent)
182
183 return this.#eventInit.error
184 }
185}
186
187Object.defineProperties(MessageEvent.prototype, {
188 [Symbol.toStringTag]: {
189 value: 'MessageEvent',
190 configurable: true
191 },
192 data: kEnumerableProperty,
193 origin: kEnumerableProperty,
194 lastEventId: kEnumerableProperty,
195 source: kEnumerableProperty,
196 ports: kEnumerableProperty,
197 initMessageEvent: kEnumerableProperty
198})
199
200Object.defineProperties(CloseEvent.prototype, {
201 [Symbol.toStringTag]: {
202 value: 'CloseEvent',
203 configurable: true
204 },
205 reason: kEnumerableProperty,
206 code: kEnumerableProperty,
207 wasClean: kEnumerableProperty
208})
209
210Object.defineProperties(ErrorEvent.prototype, {
211 [Symbol.toStringTag]: {
212 value: 'ErrorEvent',
213 configurable: true
214 },
215 message: kEnumerableProperty,
216 filename: kEnumerableProperty,
217 lineno: kEnumerableProperty,
218 colno: kEnumerableProperty,
219 error: kEnumerableProperty
220})
221
222webidl.converters.MessagePort = webidl.interfaceConverter(MessagePort)
223
224webidl.converters['sequence<MessagePort>'] = webidl.sequenceConverter(
225 webidl.converters.MessagePort
226)
227
228const eventInit = [
229 {
230 key: 'bubbles',
231 converter: webidl.converters.boolean,
232 defaultValue: () => false
233 },
234 {
235 key: 'cancelable',
236 converter: webidl.converters.boolean,
237 defaultValue: () => false
238 },
239 {
240 key: 'composed',
241 converter: webidl.converters.boolean,
242 defaultValue: () => false
243 }
244]
245
246webidl.converters.MessageEventInit = webidl.dictionaryConverter([
247 ...eventInit,
248 {
249 key: 'data',
250 converter: webidl.converters.any,
251 defaultValue: () => null
252 },
253 {
254 key: 'origin',
255 converter: webidl.converters.USVString,
256 defaultValue: () => ''
257 },
258 {
259 key: 'lastEventId',
260 converter: webidl.converters.DOMString,
261 defaultValue: () => ''
262 },
263 {
264 key: 'source',
265 // Node doesn't implement WindowProxy or ServiceWorker, so the only
266 // valid value for source is a MessagePort.
267 converter: webidl.nullableConverter(webidl.converters.MessagePort),
268 defaultValue: () => null
269 },
270 {
271 key: 'ports',
272 converter: webidl.converters['sequence<MessagePort>'],
273 defaultValue: () => new Array(0)
274 }
275])
276
277webidl.converters.CloseEventInit = webidl.dictionaryConverter([
278 ...eventInit,
279 {
280 key: 'wasClean',
281 converter: webidl.converters.boolean,
282 defaultValue: () => false
283 },
284 {
285 key: 'code',
286 converter: webidl.converters['unsigned short'],
287 defaultValue: () => 0
288 },
289 {
290 key: 'reason',
291 converter: webidl.converters.USVString,
292 defaultValue: () => ''
293 }
294])
295
296webidl.converters.ErrorEventInit = webidl.dictionaryConverter([
297 ...eventInit,
298 {
299 key: 'message',
300 converter: webidl.converters.DOMString,
301 defaultValue: () => ''
302 },
303 {
304 key: 'filename',
305 converter: webidl.converters.USVString,
306 defaultValue: () => ''
307 },
308 {
309 key: 'lineno',
310 converter: webidl.converters['unsigned long'],
311 defaultValue: () => 0
312 },
313 {
314 key: 'colno',
315 converter: webidl.converters['unsigned long'],
316 defaultValue: () => 0
317 },
318 {
319 key: 'error',
320 converter: webidl.converters.any
321 }
322])
323
324module.exports = {
325 MessageEvent,
326 CloseEvent,
327 ErrorEvent,
328 createFastMessageEvent
329}
330 