text: define([
  	'module',
  	'./watch',
  	'./util',
  	'../_base/kernel',
  	'../_base/array',
  	'../_base/lang',
  	'../on',
  	'../dom',
  	'../dom-construct',
  	'../has',
  	'../_base/window'/*=====,
  	'../request',
  	'../_base/declare' =====*/
  ], function(module, watch, util, kernel, array, lang, on, dom, domConstruct, has, win/*=====, request, declare =====*/){
  	has.add('script-readystatechange', function(global, document){
  		var script = document.createElement('script');
  		return typeof script['onreadystatechange'] !== 'undefined' &&
  			(typeof global['opera'] === 'undefined' || global['opera'].toString() !== '[object Opera]');
  	});
  
  	var mid = module.id.replace(/[\/\.\-]/g, '_'),
  		counter = 0,
  		loadEvent = has('script-readystatechange') ? 'readystatechange' : 'load',
  		readyRegExp = /complete|loaded/,
  		callbacks = kernel.global[mid + '_callbacks'] = {},
  		deadScripts = [];
  
  	function attach(id, url, frameDoc){
  		var doc = (frameDoc || win.doc),
  			element = doc.createElement('script');
  
  		element.type = 'text/javascript';
  		element.src = url;
  		element.id = id;
  		element.async = true;
  		element.charset = 'utf-8';
  
  		return doc.getElementsByTagName('head')[0].appendChild(element);
  	}
  
  	function remove(id, frameDoc, cleanup){
  		domConstruct.destroy(dom.byId(id, frameDoc));
  
  		if(callbacks[id]){
  			if(cleanup){
  				// set callback to a function that deletes itself so requests that
  				// are in-flight don't error out when returning and also
  				// clean up after themselves
  				callbacks[id] = function(){
  					delete callbacks[id];
  				};
  			}else{
  				delete callbacks[id];
  			}
  		}
  	}
  
  	function _addDeadScript(dfd){
  		// Be sure to check ioArgs because it can dynamically change in the dojox/io plugins.
  		// See http://bugs.dojotoolkit.org/ticket/15890.
  		var options = dfd.response.options,
  			frameDoc = options.ioArgs ? options.ioArgs.frameDoc : options.frameDoc;
  
  		deadScripts.push({ id: dfd.id, frameDoc: frameDoc });
  
  		if(options.ioArgs){
  			options.ioArgs.frameDoc = null;
  		}
  		options.frameDoc = null;
  	}
  
  	function canceler(dfd, response){
  		if(dfd.canDelete){
  			//For timeouts and cancels, remove the script element immediately to
  			//avoid a response from it coming back later and causing trouble.
  			script._remove(dfd.id, response.options.frameDoc, true);
  		}
  	}
  	function isValid(response){
  		//Do script cleanup here. We wait for one inflight pass
  		//to make sure we don't get any weird things by trying to remove a script
  		//tag that is part of the call chain (IE 6 has been known to
  		//crash in that case).
  		if(deadScripts && deadScripts.length){
  			array.forEach(deadScripts, function(_script){
  				script._remove(_script.id, _script.frameDoc);
  				_script.frameDoc = null;
  			});
  			deadScripts = [];
  		}
  
  		return response.options.jsonp ? !response.data : true;
  	}
  	function isReadyScript(response){
  		return !!this.scriptLoaded;
  	}
  	function isReadyCheckString(response){
  		var checkString = response.options.checkString;
  
  		return checkString && eval('typeof(' + checkString + ') !== "undefined"');
  	}
  	function handleResponse(response, error){
  		if(this.canDelete){
  			_addDeadScript(this);
  		}
  		if(error){
  			this.reject(error);
  		}else{
  			this.resolve(response);
  		}
  	}
  
  	function script(url, options, returnDeferred){
  		var response = util.parseArgs(url, util.deepCopy({}, options));
  		url = response.url;
  		options = response.options;
  
  		var dfd = util.deferred(
  			response,
  			canceler,
  			isValid,
  			options.jsonp ? null : (options.checkString ? isReadyCheckString : isReadyScript),
  			handleResponse
  		);
  
  		lang.mixin(dfd, {
  			id: mid + (counter++),
  			canDelete: false
  		});
  
  		if(options.jsonp){
  			var queryParameter = new RegExp('[?&]' + options.jsonp + '=');
  			if(!queryParameter.test(url)){
  				url += (~url.indexOf('?') ? '&' : '?') +
  					options.jsonp + '=' +
  					(options.frameDoc ? 'parent.' : '') +
  					mid + '_callbacks.' + dfd.id;
  			}
  
  			dfd.canDelete = true;
  			callbacks[dfd.id] = function(json){
  				response.data = json;
  				dfd.handleResponse(response);
  			};
  		}
  
  		if(util.notify){
  			util.notify.emit('send', response, dfd.promise.cancel);
  		}
  
  		if(!options.canAttach || options.canAttach(dfd)){
  			var node = script._attach(dfd.id, url, options.frameDoc);
  
  			if(!options.jsonp && !options.checkString){
  				var handle = on(node, loadEvent, function(evt){
  					if(evt.type === 'load' || readyRegExp.test(node.readyState)){
  						handle.remove();
  						dfd.scriptLoaded = evt;
  					}
  				});
  			}
  		}
  
  		on.once(node, 'error', function (error) {
  			dfd.reject(error);
  			script._remove(dfd.id, options.frameDoc, true);
  		});
  
  		watch(dfd);
  
  		return returnDeferred ? dfd : dfd.promise;
  	}
  	script.get = script;
  	/*=====
  	script = function(url, options){
  		// summary:
  		//		Sends a request using a script element with the given URL and options.
  		// url: String
  		//		URL to request
  		// options: dojo/request/script.__Options?
  		//		Options for the request.
  		// returns: dojo/request.__Promise
  	};
  	script.__BaseOptions = declare(request.__BaseOptions, {
  		// jsonp: String?
  		//		The URL parameter name that indicates the JSONP callback string.
  		//		For instance, when using Yahoo JSONP calls it is normally,
  		//		jsonp: "callback". For AOL JSONP calls it is normally
  		//		jsonp: "c".
  		// checkString: String?
  		//		A string of JavaScript that when evaluated like so:
  		//		"typeof(" + checkString + ") != 'undefined'"
  		//		being true means that the script fetched has been loaded.
  		//		Do not use this if doing a JSONP type of call (use `jsonp` instead).
  		// frameDoc: Document?
  		//		The Document object of a child iframe. If this is passed in, the script
  		//		will be attached to that document. This can be helpful in some comet long-polling
  		//		scenarios with Firefox and Opera.
  	});
  	script.__MethodOptions = declare(null, {
  		// method: String?
  		//		This option is ignored. All requests using this transport are
  		//		GET requests.
  	});
  	script.__Options = declare([script.__BaseOptions, script.__MethodOptions]);
  
  	script.get = function(url, options){
  		// summary:
  		//		Send an HTTP GET request using a script element with the given URL and options.
  		// url: String
  		//		URL to request
  		// options: dojo/request/script.__BaseOptions?
  		//		Options for the request.
  		// returns: dojo/request.__Promise
  	};
  	=====*/
  
  	// TODO: Remove in 2.0
  	script._attach = attach;
  	script._remove = remove;
  	script._callbacksProperty = mid + '_callbacks';
  
  	return script;
  });
  