happy-dom
Version:
Happy DOM is a JavaScript implementation of a web browser without its graphical user interface. It includes many web standards from WHATWG DOM and HTML.
90 lines (75 loc) • 2.29 kB
text/typescript
import BrowserErrorCaptureEnum from '../../browser/enums/BrowserErrorCaptureEnum.js';
import WindowBrowserContext from '../../window/WindowBrowserContext.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import Event from '../../event/Event.js';
import Element from './Element.js';
/**
* ECMAScript module compiler.
*/
export default class ElementEventAttributeUtility {
/**
* Evaluates code in attribute and returns event listener.
*
* @param element
* @param property Property.
* @returns Result.
*/
public static getEventListener(
element: Element,
property: string
): ((event: Event) => void) | null {
const cached = element[PropertySymbol.propertyEventListeners].get(property);
if (cached) {
return cached;
}
const window = element[PropertySymbol.ownerDocument][PropertySymbol.defaultView];
const browserSettings = new WindowBrowserContext(window).getSettings();
if (!browserSettings) {
return null;
}
const code = element.getAttribute(property);
if (!code) {
return null;
}
let newCode = `(function anonymous($happy_dom, event) {\n//# sourceURL=${window.location.href}\n`;
if (
browserSettings &&
!browserSettings.disableErrorCapturing &&
browserSettings.errorCapture === BrowserErrorCaptureEnum.tryAndCatch
) {
newCode += 'try {\n';
}
newCode += code;
if (
browserSettings &&
!browserSettings.disableErrorCapturing &&
browserSettings.errorCapture === BrowserErrorCaptureEnum.tryAndCatch
) {
newCode += '\n} catch(e) { $happy_dom.dispatchError(e); }\n';
}
newCode += '})';
let listener: ((event: Event) => void) | null = null;
try {
listener = window.eval(newCode).bind(element, {
dispatchError: window[PropertySymbol.dispatchError]
});
} catch (e) {
const error = new window.SyntaxError(
`Failed to read the '${property}' property from '${element.constructor.name}': ${e.message}`
);
if (
browserSettings.disableErrorCapturing ||
browserSettings.errorCapture !== BrowserErrorCaptureEnum.tryAndCatch
) {
throw error;
} else {
window[PropertySymbol.dispatchError](error);
return null;
}
}
if (listener) {
element[PropertySymbol.propertyEventListeners].set(property, listener);
}
return listener;
}
}