JonFerraiolo Hub Proposals 2007-02-01

From MemberWiki

Jump to: navigation, search

Contents

About this wiki page

Please do not change this wiki page. It is now a historical document that reflect a proposal that was discussed within the Interoperability Committee.

This wiki page describes a set of proposed changes to:

The impetus behind these proposed changes are feedback from various members who have attempted to support the Hub with their toolkits and to pass the InteropFest test case.

The contents of this wiki page was discussed at the 07 Feb 07 Interoperability phone call.


Proposed changes

General

Miscellaneous fixes to reference implementation that do not change spec or functionality, but simply make the code smaller

Adam Peller has a set of proposed improvements to the open source project where different JavaScript approaches would be used in some of the open source project which accomplish the same thing but with fewer bytes of source code. For example, replace:

if (typeof foo.bar == "undefined") {
	foo.bar = {};
}

with

foo.bar = foo.bar || {};

this isn't strictly the same treatment, but generally accomplishes the goal of assuring the property is an Object. Adam has a handful of similar improvements which result in smaller code size but implement the same features, such as avoiding unnecessary if/then/else clauses, or using array or hash syntax to declare objects inline instead of using individual element assignments.

Of course, this proposal was accepted.

Remove most argument checks

A significant percentage of the source code right now has to do with checking the correctness of the arguments passed to a given method. By far, the single easiest way to have a major impact on the size of the reference implementation is to remove these checks. The checks are particularly long-winded because if the check fails, an error gets thrown, and error strings take up considerable space. (Besides which, there would be localization issues with the error strings.)

Right now there are checks on the number of arguments passed and the types of the arguments. There is some inconsistency in the current code where some methods do a more thorough job of checking arguments than others. To make the codebase consistent and logically complete would probably result in a significant addition of additional JavaScript (thus making the reference implementation ever bigger). Here is an example of some argument checking from the code as it exists now:

if (arguments.length < 1)
	throw new Error("Insufficient number of arguments");
if(!scope){
	scope = window;
}
if(typeof refOrName == "string"){
	// get a function object
	refOrName = scope[refOrName];
}
if(typeof refOrName != "function"){
	throw new Error("invalid function reference passed to OpenAjax.addOnLoad()");
}
if (!phase || phase=="application") {
	OpenAjax._applicationLoadCBs.push(refOrName);
} else if (phase == "library") {
	OpenAjax._libraryLoadCBs.push(refOrName);
} else if (phase == "component") {
	OpenAjax._componentLoadCBs.push(refOrName);
} else {
	throw new Error("invalid phase value passed to OpenAjax.addOnLoad()");
}

The proposal is to remove most (if not all) of the logic that checks the arguments passed into our public methods and include words in the Specification that it is OK for implementations of the Hub to do no argument checking.

The justification for this approach is that the Hub is that it is critical that the Hub be very small in order for the toolkit developers to feel comfortable about shipping the Hub within their toolkits, and that if the Hub is too big, its sheer size might prevent it from being used by toolkits and thus cause us to fail in our interoperability objectives. Also:

  • The APIs within the Hub will almost always be invoked by toolkit developers, not application developers. Toolkit developers generally know what they are doing and are more likely to be able to debug into the Hub's logic should problems arise.
  • Down the road, someone (including us) can deliver an alternate implementation of the Hub which includes argument checks to add developers who need these facilities. In other words, we aren't precluding implementations of the Hub spec from performing argument checks, we are just not requiring argument checks.
  • Eliminates the localization problem for the various error strings.

This proposal was accepted. As a low priority task, we decided to have an optional ArgChecks.js module (or something like that) that developers can include in interpose wrappers on all of the OpenAjax.* functions that perform arg checks and then invoke the function without the arg checks.

Remove OpenAjax.get***() and OpenAjax.query***(), and instead make data structures public

As the Hub exists now, there are some APIs for querying the Hub, such as OpenAjax.getGlobals(prefix) and OpenAjax.queryLibrary(prefix), and the implementation stored its lists of globals and libraries in "private" variables OpenAjax._globals and OpenAjax._libraries. Adam Peller noticed that without the error checking, these methods were typically wrappers for Array or Object hashes, which themselves are a reasonable way to access the information. He questioned whether providing a public "interface" was truly necessary. If it ever might be a design goal to hide the private data structure, the private variable should be hidden via closure and the accessor methods can remain. Otherwise, a public variable might just as well replace the public accessor methods and we can slightly reduce the API specification as well as the codebase.

Another issue is whether deep copies of Object/Array structures is necessary, or whether we can state in the specification that the user is not to modify the returned Objects. The latter approach would again help us minimize the codebase.

(NOTE: This requires various small changes to the Specification. The Specification will have to explain that these variables are public, but developers must not change the values of these arrays and thus treat them as read-only.)

After long discussion, this proposal was accepted. Small footprint was deemed to be an overriding goal.

Remove all references to OpenAjax._error

Right now, the open source codebase has every method checking the status of OpenAjax._error to see if the Hub is in an error state; however, there is no logic right now that ever puts the Hub into an error state. Therefore, let's make the code smaller by removing these checks (which right now can never be true).

Of course, this proposal was accepted.

OpenAjaxBootstrap.js

Use different URI for implementer

The current code base says implementer: "http://openajaxallianc.sourceforge.net". Adam Peller proposes that we use a domain we own instead: implementer: "http://openajax.org"

Of course, this proposal was accepted.

Globals.js

Separate out collision check logic into a different JavaScript file

Right now most of the logic in Globals.js is the collision check logic. This logic is not needed in all cases. For example, if Dojo embeds the Hub and a particular application only uses Dojo, there isn't a real need to invoke collision checks, and thus the collision check logic download would be wasteful and waste time at initialization time.

So, the proposal is to move the collision check logic into a separate JavaScript file (Collision.js) and treat it as a separate module within the Hub that can be loaded or not at the discretion of particular toolkits and applications.

Also, remove the line of code in registerGlobals() that invokes globalsCollisionCheck() and instead require the toolkit or application to manually invoke the collision check method.

This proposal was accepted, but at the time of writing this, the proposal has not yet been implemented.

LoadUnload.js

Right now, the logic here always invokes OpenAjax.scanDocument(), but this API may not be available if the markup scanner module has not been included. Therefore, the proposal is to check to only invoke OpenAjax.scanDocument() if the markup scanner has been loaded.

Of course, this proposal was accepted.

InteropFest Test Case Changes

Allow toolkit JavaScript to be loaded in BODY and after 'load' event

Per email discussion with toolkit implementers who have attempted to integrate with the Hub and pass the InteropFest test, some scenarios (such as portlets) require that the Ajax toolkit's JavaScript be loaded within the BODY (instead of the HEAD) and that their initialization logic get invoked after the document 'load' event. The proposal is to make minor changes to the InteropFest test case, primarily in the comments that talk about what is allowed and not allowed, to address these scenarios.

This proposal was accepted.

Issues

These are open issues which we will discuss at our next phone call (Feb. 7) before the Specification or source code project are modified.

ISSUE: Remove 'load' handlers after 'load' event has occurred?

Jesse has suggested that we clean the list of 'load' handlers after the 'load' event has been processed. I can't think of any reasons why we should not do this, beyond a very small increase in code size for Hub to empty the list:

this.callbacks.load={};

And might help out the garbage collector in some circumstances.

This proposal was accepted.

ISSUE: Add API to see if 'load' event has already occurred?

Jesse has indicated that it would be useful to have a way to know if the 'load' event has already occurred. The most compact way to achieve this would be to define a public property OpenAjax.docLoaded which holds either true or false, and becomes true when the document 'load' event has happened. (The Specification would have to tell developers that they must not set this property themselves and instead treat this property as read-only.)

This proposal was accepted. Someone pointed out that it is not easy to determine when the browser has really finished 'load' processing, so instead we will have a variable that indicates when the Hub's load (and unload) processing is done. Implemented as OpenAjax.loadDone and OpenAjax.unloadDone.

Personal tools