events.js 7.2 KB

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