| 'use strict'; |
|
|
| const { kForOnEventAttribute, kListener } = require('./constants'); |
|
|
| const kCode = Symbol('kCode'); |
| const kData = Symbol('kData'); |
| const kError = Symbol('kError'); |
| const kMessage = Symbol('kMessage'); |
| const kReason = Symbol('kReason'); |
| const kTarget = Symbol('kTarget'); |
| const kType = Symbol('kType'); |
| const kWasClean = Symbol('kWasClean'); |
|
|
| |
| |
| |
| class Event { |
| |
| |
| |
| |
| |
| |
| constructor(type) { |
| this[kTarget] = null; |
| this[kType] = type; |
| } |
|
|
| |
| |
| |
| get target() { |
| return this[kTarget]; |
| } |
|
|
| |
| |
| |
| get type() { |
| return this[kType]; |
| } |
| } |
|
|
| Object.defineProperty(Event.prototype, 'target', { enumerable: true }); |
| Object.defineProperty(Event.prototype, 'type', { enumerable: true }); |
|
|
| |
| |
| |
| |
| |
| class CloseEvent extends Event { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| constructor(type, options = {}) { |
| super(type); |
|
|
| this[kCode] = options.code === undefined ? 0 : options.code; |
| this[kReason] = options.reason === undefined ? '' : options.reason; |
| this[kWasClean] = options.wasClean === undefined ? false : options.wasClean; |
| } |
|
|
| |
| |
| |
| get code() { |
| return this[kCode]; |
| } |
|
|
| |
| |
| |
| get reason() { |
| return this[kReason]; |
| } |
|
|
| |
| |
| |
| get wasClean() { |
| return this[kWasClean]; |
| } |
| } |
|
|
| Object.defineProperty(CloseEvent.prototype, 'code', { enumerable: true }); |
| Object.defineProperty(CloseEvent.prototype, 'reason', { enumerable: true }); |
| Object.defineProperty(CloseEvent.prototype, 'wasClean', { enumerable: true }); |
|
|
| |
| |
| |
| |
| |
| class ErrorEvent extends Event { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| constructor(type, options = {}) { |
| super(type); |
|
|
| this[kError] = options.error === undefined ? null : options.error; |
| this[kMessage] = options.message === undefined ? '' : options.message; |
| } |
|
|
| |
| |
| |
| get error() { |
| return this[kError]; |
| } |
|
|
| |
| |
| |
| get message() { |
| return this[kMessage]; |
| } |
| } |
|
|
| Object.defineProperty(ErrorEvent.prototype, 'error', { enumerable: true }); |
| Object.defineProperty(ErrorEvent.prototype, 'message', { enumerable: true }); |
|
|
| |
| |
| |
| |
| |
| class MessageEvent extends Event { |
| |
| |
| |
| |
| |
| |
| |
| |
| constructor(type, options = {}) { |
| super(type); |
|
|
| this[kData] = options.data === undefined ? null : options.data; |
| } |
|
|
| |
| |
| |
| get data() { |
| return this[kData]; |
| } |
| } |
|
|
| Object.defineProperty(MessageEvent.prototype, 'data', { enumerable: true }); |
|
|
| |
| |
| |
| |
| |
| |
| const EventTarget = { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| addEventListener(type, handler, options = {}) { |
| for (const listener of this.listeners(type)) { |
| if ( |
| !options[kForOnEventAttribute] && |
| listener[kListener] === handler && |
| !listener[kForOnEventAttribute] |
| ) { |
| return; |
| } |
| } |
|
|
| let wrapper; |
|
|
| if (type === 'message') { |
| wrapper = function onMessage(data, isBinary) { |
| const event = new MessageEvent('message', { |
| data: isBinary ? data : data.toString() |
| }); |
|
|
| event[kTarget] = this; |
| callListener(handler, this, event); |
| }; |
| } else if (type === 'close') { |
| wrapper = function onClose(code, message) { |
| const event = new CloseEvent('close', { |
| code, |
| reason: message.toString(), |
| wasClean: this._closeFrameReceived && this._closeFrameSent |
| }); |
|
|
| event[kTarget] = this; |
| callListener(handler, this, event); |
| }; |
| } else if (type === 'error') { |
| wrapper = function onError(error) { |
| const event = new ErrorEvent('error', { |
| error, |
| message: error.message |
| }); |
|
|
| event[kTarget] = this; |
| callListener(handler, this, event); |
| }; |
| } else if (type === 'open') { |
| wrapper = function onOpen() { |
| const event = new Event('open'); |
|
|
| event[kTarget] = this; |
| callListener(handler, this, event); |
| }; |
| } else { |
| return; |
| } |
|
|
| wrapper[kForOnEventAttribute] = !!options[kForOnEventAttribute]; |
| wrapper[kListener] = handler; |
|
|
| if (options.once) { |
| this.once(type, wrapper); |
| } else { |
| this.on(type, wrapper); |
| } |
| }, |
|
|
| |
| |
| |
| |
| |
| |
| |
| removeEventListener(type, handler) { |
| for (const listener of this.listeners(type)) { |
| if (listener[kListener] === handler && !listener[kForOnEventAttribute]) { |
| this.removeListener(type, listener); |
| break; |
| } |
| } |
| } |
| }; |
|
|
| module.exports = { |
| CloseEvent, |
| ErrorEvent, |
| Event, |
| EventTarget, |
| MessageEvent |
| }; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| function callListener(listener, thisArg, event) { |
| if (typeof listener === 'object' && listener.handleEvent) { |
| listener.handleEvent.call(listener, event); |
| } else { |
| listener.call(thisArg, event); |
| } |
| } |
|
|