text: dojo.provide("dojox.lang.observable");
  // Used to create a wrapper object with monitored reads and writes
  // 
  dojo.experimental("dojox.lang.observable");
  // IMPORTANT DISCLAIMER: 
  // This is experimental and based on hideous hacks. 
  // There are severe limitations on the ability of wrapper objects:
  // Only properties that have vbscript-legal names are accessible (similar to JavaScript, but they can't start with an underscore).
  // The wrapper objects are not expando in IE, because they are built
  // from VBScript objects. This means you can't add new properties after an object is created.
  // The wrapper objects can not be used a prototype for other objects.
  // Only properties with primitive values can be wrapped.
  // This has performance implications as well.
  dojox.lang.observable = function(/*Object*/wrapped,/*function*/onRead,/*function*/onWrite,/*function*/onInvoke){
  	// 	summary:
  	// 		Creates a wrapper object, which can be observed. The wrapper object 
  	// 		is a proxy to the wrapped object. If you will be making multiple wrapper
  	// 		objects with the same set of listeners, it is recommended that you
  	// 		use makeObservable, as it is more memory efficient.	
  	// 
  	// 	wrapped:
  	// 		The object to be wrapped and monitored for property access and modification
  	//	
  	// onRead:
  	//		See dojox.lang.makeObservable.onRead
  	// onWrite:
  	//		See dojox.lang.makeObservable.onWrite
  	// onInvoke:
  	//		See dojox.lang.makeObservable.onInvoke
  	
  	return dojox.lang.makeObservable(onRead,onWrite,onInvoke)(wrapped);
  }
  dojox.lang.makeObservable = function(/*function*/onRead,/*function*/onWrite,/*function*/onInvoke,/*Object*/hiddenFunctions){
  		
  	// 	summary:
  	// 		Creates and returns an observable creator function. All the objects that 
  	// 		are created with the returned constructor will use the provided onRead and
  	// 		onWrite listeners.
  	// 		The created constructor should be called with a single argument,
  	// 		the object that will be wrapped to be observed. The constructor will 
  	// 		return the wrapper object.
  	//
  	// onRead:
  	// 		This is called whenever one of the wrapper objects created 
  	// 		from the constructor has a property that is accessed. onRead
  	// 		will be called with two arguments, the first being the wrapped object,
  	// 		and the second is the name of property that is being accessed.
  	// 		The value that onRead returns will be used as the value returned 
  	// 		by the property access
  	//  
  	// onWrite:
  	// 		This is called whenever one of the wrapper objects created 
  	// 		from the constructor has a property that is modified. onWrite
  	// 		will be called with three arguments, the first being the wrapped object,
  	// 		the second is the name of property that is being modified, and the
  	// 		third is the value that is being set on the property.
  	// 
  	// 	onInvoke: 
  	// 		This is called when a method on the object is invoked. The first 
  	// 		argument is the wrapper object, the second is the original wrapped object, 
  	// 		the third is the method name, and the fourth is the arguments.
  	//
  	// hiddenFunctions: 
  	// 		allows you to define functions that should be delegated 
  	// 		but may not be enumerable on the wrapped objects, so they must be 
  	// 		explicitly included
  	//
  	// example:
  	// 		The following could be used to create a wrapper that would
  	// 		prevent functions from being accessed on an object:
  	// 	|	function onRead(obj,prop){
  	//	|		return typeof obj[prop] == 'function' ? null : obj[prop];
  	//	|	} 
  	//	|	var observable = dojox.lang.makeObservable(onRead,onWrite);
  	//	|	var obj = {foo:1,bar:function(){}};
  	//	|	obj = observable(obj);
  	//	|	obj.foo -> 1
  	//	|	obj.bar -> null
  	//
  	hiddenFunctions = hiddenFunctions || {};
  	onInvoke = onInvoke || function(scope,obj,method,args){
  		// default implementation for onInvoke, just passes the call through
  		return obj[method].apply(scope,args);
  	};
  	function makeInvoker(scope,wrapped,i){
  		return function(){
  			// this is function used for all methods in the wrapper object
  			return onInvoke(scope,wrapped,i,arguments);
  		};
  	}
  	
  	if(dojox.lang.lettableWin){ // create the vb class
  		var factory = dojox.lang.makeObservable;
  		factory.inc = (factory.inc || 0) + 1;
  		// create globals for the getters and setters so they can be accessed from the vbscript
  		var getName = "gettable_"+factory.inc;
  		dojox.lang.lettableWin[getName] = onRead;
  		var setName = "settable_"+factory.inc;
  		dojox.lang.lettableWin[setName] = onWrite;
  		var cache = {};
  		return function(wrapped){
  			if(wrapped.__observable){ // if it already has an observable, use that
  				return wrapped.__observable;
  			}
  			if(wrapped.data__){
  				throw new Error("Can wrap an object that is already wrapped");
  			}			
  			// create the class
  			var props = [];
  			for(var i in hiddenFunctions){
  				props.push(i);
  			}
  			vbReservedWords = {type:1,event:1};
  			// find the unique signature for the class so we can reuse it if possible
  			for(i in wrapped){ 
  				if(i.match(/^[a-zA-Z][\w\$_]*$/) && !(i in hiddenFunctions) && !(i in vbReservedWords)){ //can only do properties with valid vb names/tokens and primitive values
  					props.push(i);
  				}
  			}
  			var signature = props.join(",");
  			var prop,clazz = cache[signature]; 
  			if(!clazz){ 
  				var tname = "dj_lettable_"+(factory.inc++);
  				var gtname = tname+"_dj_getter";
  				var cParts = [
  					"Class "+tname,
  					"	Public data__" // this our reference to the original object
  				];
  				for(i = 0,  l = props.length; i < l; i++){
  					prop = props[i];
  					var type = typeof wrapped[prop];
  					if(type == 'function' || hiddenFunctions[prop]){ // functions must go in regular properties for delegation:/
  						cParts.push("  Public " + prop);
  					}else if(type != 'object'){ // the getters/setters can only be applied to primitives
  						cParts.push(
  							"	Public Property Let "+prop+"(val)",
  							"		Call "+setName+"(me.data__,\""+prop+"\",val)",
  							"	End Property",
  							"	Public Property Get "+prop,
  							"		"+prop+" = "+getName+"(me.data__,\""+prop+"\")",
  							"	End Property");
  					}
  				}
  				cParts.push("End Class");
  				cParts.push(
  					"Function "+gtname+"()",
  					"	Dim tmp",
  					"	Set tmp = New "+tname,
  					"	Set "+gtname+" = tmp",
  					"End Function");
  				dojox.lang.lettableWin.vbEval(cParts.join("\n"));
  					
  				// Put the new class in the cache
  				cache[signature] = clazz = function(){
  					return dojox.lang.lettableWin.construct(gtname); // the class can't be accessed, only called, so we have to wrap it with a function
  				};
  			}
  			console.log("starting5");
  			var newObj = clazz();
  			newObj.data__ = wrapped;
  			console.log("starting6");
  			try {
  				wrapped.__observable = newObj;
  			} catch(e){ // some objects are not expando
  			}
  			for(i = 0,  l = props.length; i < l; i++){
  				prop = props[i];
  				try {
  				var val = wrapped[prop];
  				}
  				catch(e){
  					console.log("error ",prop,e);
  				}
  				if(typeof val == 'function' || hiddenFunctions[prop]){ // we can make a delegate function here
  					newObj[prop] = makeInvoker(newObj,wrapped,prop);
  				}
  			}
  			return newObj;
  		};
  	}else{
  		return function(wrapped){ // do it with getters and setters
  			if(wrapped.__observable){ // if it already has an observable, use that
  				return wrapped.__observable;
  			}
  			var newObj = wrapped instanceof Array ? [] : {};
  			newObj.data__ = wrapped;
  			for(var i in wrapped){
  				if(i.charAt(0) != '_'){
  					if(typeof wrapped[i] == 'function'){
  						newObj[i] = makeInvoker(newObj,wrapped,i); // TODO: setup getters and setters so we can detect when this changes
  					}else if(typeof wrapped[i] != 'object'){
  						(function(i){
  							newObj.__defineGetter__(i,function(){
  								return onRead(wrapped,i);
  							});
  							newObj.__defineSetter__(i,function(value){
  								return onWrite(wrapped,i,value);
  							});
  						})(i);
  					}
  				}
  			}
  			for(i in hiddenFunctions){
  				newObj[i] = makeInvoker(newObj,wrapped,i);
  			}
  			wrapped.__observable = newObj;
  			return newObj;
  		};
  	}
  };
  if(!{}.__defineGetter__){
  	if(dojo.isIE){
  		// to setup the crazy lettable hack we need to
  		// introduce vb script eval
  		// the only way that seems to work for adding a VBScript to the page is with a document.write
  		// document.write is not always available, so we use an iframe to do the document.write
  		// the iframe also provides a good hiding place for all the global variables that we must
  		// create in order for JScript and VBScript to interact.
  		var frame;
  		if(document.body){ // if the DOM is ready we can add it
  			frame = document.createElement("iframe");
  			document.body.appendChild(frame);
  		}else{ // other we have to write it out
  			document.write("<iframe id='dj_vb_eval_frame'></iframe>");
  			frame = document.getElementById("dj_vb_eval_frame");
  		}
  		frame.style.display="none";
  		var doc = frame.contentWindow.document;
  		dojox.lang.lettableWin = frame.contentWindow;
  		doc.write('<html><head><script language="VBScript" type="text/VBScript">' + 
  			'Function vb_global_eval(code)' +
  				'ExecuteGlobal(code)' +
  			'End Function' +
  			'</script>' +
  			'<script type="text/javascript">' + 
  			'function vbEval(code){ \n' + // this has to be here to call it from another frame
  				'return vb_global_eval(code);' +
  			'}' +
  			'function construct(name){ \n' + // and this too 
  				'return window[name]();' +
  			'}' +
  			'</script>' +
  			'</head><body>vb-eval</body></html>');
  		doc.close();
  	}else{
  		throw new Error("This browser does not support getters and setters");
  	}
  }
  
  dojox.lang.ReadOnlyProxy =
  // summary: 
  // 		Provides a read only proxy to another object, this can be 
  // 		very useful in object-capability systems
  // example:
  // 	|	var obj = {foo:"bar"};
  // 	|	var readonlyObj = dojox.lang.ReadOnlyProxy(obj);
  // 	|	readonlyObj.foo = "test" // throws an error
  // 	|	obj.foo = "new bar";
  // 	|	readonlyObj.foo -> returns "new bar", always reflects the current value of the original (it is not just a copy) 
  dojox.lang.makeObservable(function(obj,i){
  		return obj[i];
  	},function(obj,i,value){
  		// just ignore, exceptions don't seem to propagate through the VB stack.
  });
  