AJS_ODL User-Guide

Browsers and Event Handling

Two exceptional conditions may arise when loading resources using link and script elements, which is that the desired resource may not exist, or that it exists but may be malformed (i.e. it has a syntax error). In principle, and under either of these conditions, the browser should call the onerror event-handler (if present) for the object in question.

AJS_ODL provides a handler for this event (for both element types), execution of which causes the execution of any function that you provide as the onError handler in the LoadDef in question. However, we live in the real world, and so (sadly) support across the browser spectrum, and through the various versions of each browser varies. Given this, and given the platform on which AJS_ODL finds itself running, you may find that your error handlers do not execute under exceptional conditions.

You can find an extensive and very useful comparison-chart on https://pie.gd/test/script-link-events/. This shows the variance among the major browers at a glance.

Despite this problem, do note that, in respect of the IMG, LINK and SCRIPT loading-methods, AJS_ODL removes its event handlers from the HTML element-object concerned once the loading transaction has terminated (successfully or in error). This means that AJS_ODL has nothing more to do with those elements subsequently, and that client-code is therefore free to do what it wants with them, including assigning new event-handlers.

Contents Browser and Event-Handling
Script-Tag Hack Drawbacks
Concurrency
Security
onload onerror
img Yes Yes
link Yes Yes
script Yes Yes
iframe Yes Redundant (apparently)
audio No Yes
video No Yes
object No No
embed No No

Script-Tag Hack Drawbacks

Aside from patchy support for the onerror handler, the use of script-element injection carries a sizable number of drawbacks, some of which are serious. These are as follows:

  • It is suitable only for retrieving executable code (typically JavaScript), whereas, as noted previously, the XHR route is far more flexible.
  • As noted in the previous section, a malformed script may not be reported to the application by the run-time.
  • There is no way to impose a time-out limit on the loading process. Instantiating a timer when loading is initiated is pointless because script elements have no abort method for the timer to invoke once time is up.
  • Browsers differ in their caching behaviour.
  • Internet Explorer v9.0 (and, presumably, previous versions) differs from the other major-browsers in the order in which it:

    • Evaluates loaded-code
    • Continues executing code after loading has been initiated
    • Issues a call to the onload event-handler of the script element concerned (which, in turn, causes AJS_ODL to call the onLoad event-handler for a given LoadDef)
  • It constitutes a security risk in that it allows the download of code from any domain (it is pivotal in cross-site scripting attacks). Given that all code runs in the browser with the same privileges, including access to cookies, downloading from a non-originating domain is secure only if the trustworthiness of the downloaded code is guaranteed. (See the section below for more on this.)

These factors constitute a serious disincentive to using the SCRIPT LoadMethod in a LoadDef, although it should be said that using eval to evaluate JavaScript-code that has been imported using XHR carries its own risk.

Concurrency

Given that AJS_ODL allows the application of multiple LoadDefs to a given object (which, collectively, may load a mix of resource types), and given the inherent asynchrony of network communications, the problem of race-conditions may arise.

Consider the two UML sequence-diagrams. In the first, AJS_ODL issues a request for an image-object, followed closely by a request for some code that, when it arrives, is evaluated and executed, at which point it performs an operation of some sort on the image object.

Given that the two resources arrive at the client in the order in which they were requested, all is well. However, the code request and the image request are in a race with each other, and the second diagram shows a different outcome, where the code arrives before the image. This is disastrous because the code then attempts to operate on an image object that has yet to enter the execution environment.

The only way to ward-off such problems is careful application-design, and do note that AJS_Logger may be of value here in tracing the sequence of events that lead to this kind of trouble. Similarly, AJS_Validator can assist also, in that it allows you to place guards upon the execution of one or more methods, such that unsatisfied conditions at the time of invocation of those methods cause a run-time exception.

Note also that, if this kind of problem arises through the use of two SCRIPT LoadDefs, a solution is to use some form of event marshalling such that execution of retrieved-code occurs only when all interdependent elements have arrived on the client platform (and a small, free library that is dedicated to such things is available on dodeca.co.uk). Alternatively you can use the asynch attribute with a value of false, as this will force the browser to evaluate scripts only in the order in which loading requests are issued, although this is available only in HTML5-compliant browsers.

If, however, multiple code-loading operations occur through the use of an XHR LoadDef, AJS_ODL dispatches each request only when the previous one has returned (i.e. no event marshalling is necessary). AJS_ODL can also handle situations where the return and execution of a given piece of JavaScript triggers the retrieval of a second piece of JavaScript, and so on. That is, it is possible (and non-troublesome) for an XHR LoadDef's onLoad handler to trigger the action of a second XHR-LoadDef.

Note that, in such scenarios, and where a given XHR retrieval fails, AJS_ODL will flush its queue of pending XHR-requests (i.e. pending requests are not dispatched).

Diagram showing the potential for race-conditions that arises with asynchronous communications

Security

Security is an ever-present concern in modern web-sites and -applications, and you should note that AJS_ODL constitutes only a range of options for implementing the automatic retrieval of resources. It provides no inherent security checks or mechanisms – it is simply a retrieval framework – and this means that, when you employ AJS_ODL in your applications, you must be aware of the potential exploits that are available to blackhat developers. This is your responsibility alone, and does not fall within AJS_ODL's remit.

Note also that the very appeal of AJS_ODL – that it can make things appear within the execution environment automatically and transparently – adds to our concerns here, in that it make it easy to forget that an on-demand loading mechanism is in place. In principle, this can make it easier to expose security holes to an attacker inadvertently, and the only genuine solution to this is relentless vigilance on your part.

If you are working on a security-sensitive application, you should avail yourself of the Open Web-Application Security Project, which details exhaustively the loopholes that attackers can exploit, and which provides a wealth of information on how to guard against such nefarious practices.