Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#849@minor: Adds support for triggering an error event when attemptin…
…g to fetch a CSS file or Javascript file when it has been disabled using "window.happyDOM.settings.*".
- Loading branch information
1 parent
0744805
commit b02520b
Showing
8 changed files
with
444 additions
and
355 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
82 changes: 82 additions & 0 deletions
82
packages/happy-dom/src/nodes/html-link-element/HTMLLinkElementUtility.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import Document from '../document/Document'; | ||
import Event from '../../event/Event'; | ||
import ErrorEvent from '../../event/events/ErrorEvent'; | ||
import ResourceFetch from '../../fetch/ResourceFetch'; | ||
import HTMLLinkElement from './HTMLLinkElement'; | ||
import CSSStyleSheet from '../../css/CSSStyleSheet'; | ||
import DOMException from '../../exception/DOMException'; | ||
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum'; | ||
|
||
/** | ||
* Helper class for getting the URL relative to a Location object. | ||
*/ | ||
export default class HTMLLinkElementUtility { | ||
/** | ||
* Returns a URL relative to the given Location object. | ||
* | ||
* @param options Options. | ||
* @param options.element Element. | ||
* @param element | ||
*/ | ||
public static async loadExternalStylesheet(element: HTMLLinkElement): Promise<void> { | ||
const href = element.getAttribute('href'); | ||
const rel = element.getAttribute('rel'); | ||
|
||
if (href !== null && rel && rel.toLowerCase() === 'stylesheet' && element.isConnected) { | ||
if (element.ownerDocument.defaultView.happyDOM.settings.disableCSSFileLoading) { | ||
this.onError( | ||
element, | ||
new DOMException( | ||
`Failed to load external stylesheet "${href}". CSS file loading is disabled.`, | ||
DOMExceptionNameEnum.notSupportedError | ||
) | ||
); | ||
return; | ||
} | ||
|
||
(<Document>element.ownerDocument)._readyStateManager.startTask(); | ||
|
||
let code: string; | ||
try { | ||
code = await ResourceFetch.fetch(element.ownerDocument, href); | ||
} catch (error) { | ||
this.onError(element, error); | ||
return; | ||
} | ||
|
||
const styleSheet = new CSSStyleSheet(); | ||
styleSheet.replaceSync(code); | ||
(<CSSStyleSheet>element.sheet) = styleSheet; | ||
element.dispatchEvent(new Event('load')); | ||
(<Document>element.ownerDocument)._readyStateManager.endTask(); | ||
} | ||
} | ||
|
||
/** | ||
* Triggered when an error occurs. | ||
* | ||
* @param element Element. | ||
* @param error Error. | ||
*/ | ||
private static onError(element: HTMLLinkElement, error: Error): void { | ||
element.dispatchEvent( | ||
new ErrorEvent('error', { | ||
message: error.message, | ||
error | ||
}) | ||
); | ||
element.ownerDocument.defaultView.dispatchEvent( | ||
new ErrorEvent('error', { | ||
message: error.message, | ||
error | ||
}) | ||
); | ||
(<Document>element.ownerDocument)._readyStateManager.endTask(); | ||
if ( | ||
!element['_listeners']['error'] && | ||
!element.ownerDocument.defaultView['_listeners']['error'] | ||
) { | ||
element.ownerDocument.defaultView.console.error(error); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 94 additions & 0 deletions
94
packages/happy-dom/src/nodes/html-script-element/HTMLScriptElementUtility.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import Document from '../document/Document'; | ||
import Event from '../../event/Event'; | ||
import ErrorEvent from '../../event/events/ErrorEvent'; | ||
import DOMException from '../../exception/DOMException'; | ||
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum'; | ||
import ResourceFetch from '../../fetch/ResourceFetch'; | ||
import HTMLScriptElement from './HTMLScriptElement'; | ||
|
||
/** | ||
* Helper class for getting the URL relative to a Location object. | ||
*/ | ||
export default class HTMLScriptElementUtility { | ||
/** | ||
* Returns a URL relative to the given Location object. | ||
* | ||
* @param options Options. | ||
* @param options.element Element. | ||
* @param element | ||
*/ | ||
public static async loadExternalScript(element: HTMLScriptElement): Promise<void> { | ||
const src = element.getAttribute('src'); | ||
const async = element.getAttribute('async') !== null; | ||
|
||
if ( | ||
element.ownerDocument.defaultView.happyDOM.settings.disableJavaScriptFileLoading || | ||
element.ownerDocument.defaultView.happyDOM.settings.disableJavaScriptEvaluation | ||
) { | ||
this.onError( | ||
element, | ||
new DOMException( | ||
`Failed to load external script "${src}". JavaScript file loading is disabled.`, | ||
DOMExceptionNameEnum.notSupportedError | ||
) | ||
); | ||
return; | ||
} | ||
|
||
if (async) { | ||
(<Document>element.ownerDocument)._readyStateManager.startTask(); | ||
|
||
let code = null; | ||
|
||
try { | ||
code = await ResourceFetch.fetch(element.ownerDocument, src); | ||
} catch (error) { | ||
this.onError(element, error); | ||
return; | ||
} | ||
|
||
element.ownerDocument.defaultView.eval(code); | ||
element.dispatchEvent(new Event('load')); | ||
(<Document>element.ownerDocument)._readyStateManager.endTask(); | ||
} else { | ||
let code = null; | ||
|
||
try { | ||
code = ResourceFetch.fetchSync(element.ownerDocument, src); | ||
} catch (error) { | ||
this.onError(element, error); | ||
return; | ||
} | ||
|
||
element.ownerDocument.defaultView.eval(code); | ||
element.dispatchEvent(new Event('load')); | ||
} | ||
} | ||
|
||
/** | ||
* Triggered when an error occurs. | ||
* | ||
* @param element Element. | ||
* @param error Error. | ||
*/ | ||
private static onError(element: HTMLScriptElement, error: Error): void { | ||
element.dispatchEvent( | ||
new ErrorEvent('error', { | ||
message: error.message, | ||
error | ||
}) | ||
); | ||
element.ownerDocument.defaultView.dispatchEvent( | ||
new ErrorEvent('error', { | ||
message: error.message, | ||
error | ||
}) | ||
); | ||
if ( | ||
!element['_listeners']['error'] && | ||
!element.ownerDocument.defaultView['_listeners']['error'] | ||
) { | ||
element.ownerDocument.defaultView.console.error(error); | ||
} | ||
} | ||
} |
Oops, something went wrong.