Proxies in JavaScript

AspectJS is a professional programming-library that allows you to exploit the rich benefits of method-call interception in your JavaScript applications via proxy functions, and this site caters to all facets of the product.

In addition to supporting arbitrary aspect-oriented techniques (AOP), the library provides direct support for method-call and system-state validation, locally and remotely, along with local and remote method-call instrumentation (i.e. logging and profiling), and the retrieval of resources on demand.

To understand how AspectJS can benefit you, read the various motivation pages for each component, and see below for the broad-brush design-and-implementation picture. See too the Site Map for links to all sections in this site, along with information on its cookies policy.

AspectJS was designed and developed by Richard Vaughan, and is distributed by Dodeca Technologies Ltd., a software development and training company that is based in South-West London in the UK.

Words from a Satisfied User

Beautiful, I admire the quality of your work. Your implementation looks really natural [and] it's very nice to see someone working on high-quality software that is backed by good ideas and tests.

R Cooke

Contents Principal Components
Auxiliaries: Definition-Object Management
Auxiliaries: Exception Management
Dog-Food Consumption
Test Suite
ECMAScript Proxies
Defects and Inaccuracies
Copyright

Principal Components

AspectJS is distributed as a zip file, the contents of which are itemised in the second table you see here, and comprises four principal components.

These comprise the AJS object, which implements the basic method-call-interception mechanism, and three client-resources that use the services of that object. While it is entirely possible to use the AJS object directly, the clients automate its use in the implementation of techniques that, otherwise, would require a mass of proprietary code on your part.

The nature of those clients is as follows:

  • AJS_Validator: supports sophisticated Design by Contract techniques that allow you to test and debug both locally and remotely during development, but to deploy your application with none of the overhead those techniques incur.
  • AJS_Logger: allows you to instrument method calls within your application in order to debug and profile it locally or remotely.
  • AJS_ODL: allows you to employ on-demand loading of JSON, JavaScript, CSS and HTML code, as well as image, video/audio and other resources.

Note that the use of a given client does not require a good understanding of the AJS object, nor does independent use of that object require an understanding of its clients.

Note too that the AJS and AJS_Validator objects make no use of native or host types, nor does AJS_Logger unless you use the 'default stream', which relies only upon the console object. This means that all those elements of the product will run on any platform, not just web browsers (AJS_ODL is, by definition, a browser-related component).

Auxiliaries: Definition-Object Management

The three clients conform to a common model, in that their operation pivots on the concept of user-defined 'definition objects', which for AJS_Validator, AJS_Logger and AJS_ODL are dubbed 'ValidationDefs', 'LogDefs' and 'LoadDefs' respectively.

Definition objects act as 'instruction packets' that guide the operation of a given AJS-client, and all the clients need to manage such packets in exactly the same way. Given this, a component that forms an auxiliary to the clients is provided in the form of AJS_DefMgr, which implements that common management-functionality in a single place.

You need not understand the use of AJS_DefMgr when working with the clients – just follow the very simple instructions in the relevant user-guide – but do be aware that the behaviour of definition queues etc. is common to all the clients. Given this, the documentation pertaining to that behaviour is carried in the Overview page for AJS_DefMgr, which avoids repetition in the client user-guides, and which you are advised to read before doing anything substantive with a given client.

Note also that you do not need to use AJS_DefMgr at all if you are working with the AJS object directly.

Auxiliaries: Exception Management

The clients also delegate exception management to a discrete handler that, from their point of view, is a simple call-back function reference that you must provide at the point of instantiation, and which they call whenever an exceptional condition has arisen, instead of simply throwing an exception natively themselves.

This indirection permits arbitrary, user-defined behaviour when a problem arises. You may, for example, wish that an exception object be thrown with an informative message, a detailed stack analysis and, critically, information that indicates the location of the trouble within the application, rather than the location at which it was detected. Alternatively, you may wish to deploy an application where such notifications are piped back to you from client to server rather than being reported to your user.

Given this, AspectJS furnishes you with two other auxiliary components, in the form of ThrowException.js and ThrowExeption_Remote.js, which implement exactly the functionality described above. If you wish to see a sample of the kind of exception notifications you receive when using either of these two resources, see the Exception Notification Gallery in the AJS_Validator user-guide. Like AJS_DefMgr, these are free-standing components that you can use independently from all other elements of AspectJS, and do note here that the delegation of exception management allows you to use proprietary exception-handler implementations of your own.

Note that, as with AJS_DefMgr, you do not need to use the stock exception-managers if you are working with the AJS object directly.

Note also that the exception-management indirection that the clients support allows you to link the functionality of AJS_Validator and AJS_Logger together to yield an equivalent to the cockpit voice recorders that modern aircraft carry. This idea is explored in depth on the Client Synergy page.

Component Code User Guide API Docs
Version
Numbers
and
Release
Dates
AJS
AJS_Validator
AJS_Logger
AJS_ODL
AJS_DefMgr
ThrowException
v1.2.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v2.0.0 - 27/03/15
v1.1.0 - 08/04/15
v1.1.1 - 18/04/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v2.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
v1.0.0 - 27/03/15
Filename Lines Size
Code

AJS.js

AJS_Validator.js
AJS_Logger.js
AJS_ODL.js

AJS.val.js
AJS_Logger.val.js
AJS_ODL.val.js

AJS_DefMgr.js

ThrowException.js
ThrowException_Remote.js

800

1,540
130
447

460
200
380

400

130
110

31.3 k

123.5 k
7.1 k
22.5 K

32.7 k
11.6 k
27.0 k

16.9k

6.0 k
3.5 k

Test
Files
Test_AspectJS.htm
Test_AJS.js
Test_AJS_Validator.js
Test_AJS_Logger.js
Test_AJS_ODL.js
Test_AJS_Original.js
-
1,560
10,290
1,230
2,470
438
-
75.5 k
514.3 k
49.5 k
95.3 k
24.1 k
Docs Read Me.txt

-

-

Dog-Food Consumption

Clearly, the components that comprise AspectJS at run-time are objects like any other, and (obviously) those objects have methods. Given this, and given that AspectJS is a method-call interception tool, it follows that you can cause it to intercept calls to those methods. Given from there that AJS_Validator performs method-call validation, it follows that we can use that component to validate calls to the methods of AJS_ODL, AJS_Logger and the AJS object itself.

This intriguing concept – a recursive application of the product – means that the various components (other than AJS_Validator – see below) need not perform a mass of argument-checking internally, with all the concomitant fixed-overhead of such technology, and this makes them considerably leaner. You can turn the validation on and off (see the relevant section in the AJS_Validator user-guide), which allows you in turn to enjoy full validation of all AspectJS-related calls during development, yet to rid yourself and your users of that validation trivially at the point of deployment – method-call interception and system-validation are a marriage made in programming heaven.

Given this, and as a sterling example of eating one's own dog-food, AspectJS provides ValidationDefs that you can apply to its own components as and when required. Gratifyingly, this feature also gives excellent product-quality assurance, which is to say that the library's implementation must be sound, otherwise it would fail the plethora of tests that the test suite throws at it.

The complete set of these supplementary validation-resources is shown in the table, and instructions on using these ValidationDefs are given in the user guides for the three principal components of the library. Note that there is no AJS_Validator.val.js. If such a resource existed, it would validate calls to AJS_Validator's methods, but the internal design of that client renders such a concept redundant. It does, however, use a set of internal ValidationDefs to police calls to its ancillary methods – a further recursive application of the product – and you can read more on this rather elegant notion in the relevant page in that component's user guide, and in the section on re-using Arg-/Rtn-Def code.

Similarly, there are no ValidationDefs for AJS_DefMgr, throwExeception and throwException_Remote because AJS_Validator uses those auxiliary components to apply ValidationDefs, and to report exceptions when validation errors occur. This circular relationship precludes the use of ValidationDefs for the auxiliaries, and so those components do perform internal validation.

Do note that you are advised strongly to use the ValidationDefs described here during application development. They are not just a curiosity as, without them, most mistakes you make when working with the AJS object, AJS_Logger or AJS_ODL will be detected only when they cause some form of low-level language-related exception within the object in question. This will do no more than waste your time.

Finally in this section, note that you need to use the contents of AJS.val.js only if you are calling methods of the AJS object yourself. It is unecessary when using the client components.

Supplement Purpose Uses
AJS.val.js Validates calls to the AJS object AJS_Validator
AJS_Logger.val.js Validates calls to AJS_Logger objectsAJS_Validator
AJS_ODL.val.js Validates calls to AJS_ODL AJS_Validator

Test Suite

The zip file also contains a full test-suite, a screen-shot of which is presented here, and which you can operate by loading Test_AspectJS.htm into your favourite browser.

The main test-suite conducts 1,160 tests, all of which the various components pass completely. Principally, these test the ValidationDefs (and thus the AJS_Validator object indirectly) that are provided for use with the AJS object, AJS_Logger and AJS_ODL. In contrast, a modified version of an older test routine is provided too, which was bundled originally with the previous version of AspectJS (v1.2). This works in a different fashion to the principal test block, and gives the AJS object's raw functionality, its ValidationDef and AJS_Validator a thorough shakedown by performing 16,307 tests, all of which the product passes in full.

You can execute this test by clicking the 'AJS v1.2' button, and do note that it employs an eye-watering degree of recursion, hence the warning about execution duration that the button-legend carries. Coincidentally, this means that it is also an excellent stress and performance test for a given JavaScript run-time, and in the event that your platform has difficulty in running this test (certain older browsers would struggle noticeably), its code includes instructions for breaking up the regimen so that it runs in discrete sections that will be easier for your run-time to execute.

Note also that, on clicking a given test-button, the caller (the JS code in Test_AspectJS.htm) passes to the corresponding bulk-test function a reference to the throwException function held in ThrowException.js, rather than forcing the bulk-test function in question to take that reference from the global scope. This is of benefit to you because it means that a small change to a single line of code in Test_AspectJS.htm will pass an instance of your own exception handler to the various elements of the test regimen. That is: you can use the test suite trivially as a test platform for your own exception handlers.

Screenshot of the AspectJS Test Suite

ECMAScript Proxies

Note that the mechanism that the AJS object implements does not utilise the native proxy-mechanism that has been introduced into JavaScript in recent years. If that mechanism proves to be superior in terms of utility and power then it may be possible to develop an alternative to the AJS object that would present the same interface to the AspectJS client components that the current AJS object implements. This would allow the client components to operate unchanged.

However, initial, cursory experiments with the native support for proxies proved rather disappointing (to this developer), and so it may be that the AJS object will remain as the interception mechanism of choice, given the advanced and powerful features it offers currently. Certainly, key issues remain constant whether you use the AJS object or the native interception-mechanism, such as the considerations that minification brings, and so, in this respect, the native proxy-mechanism will never offer a better alternative.

Defects and Inaccuracies

Should you discover a bug in any of the components that comprise AspectJS, please report it via the contact form, providing as much information as possible to enable reproduction of the defect. Similarly, do get in touch should you discover an inaccuracy, inconsistency or other deficiency in any of the material on this site, or if you have suggestions for improvements to any facet of the AspectJS product.

Copyright

All content available from this domain, and the code that comprises the AspectJS product itself, is copyright © Dodeca Technologies Ltd. 2007 – 2015.