whole_func_string: function create_chain() {
  			var chainedAPI,
  				chain_opts = merge_objs(global_defaults,{}),
  				chain = [],
  				exec_cursor = 0,
  				scripts_currently_loading = false,
  				chain_is_corked = false,
  				group
  			;
  
  			// called when a script has finished preloading
  			function chain_script_ready(script_obj,exec_trigger) {
  				if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);
  				script_obj.ready = true;
  				script_obj.exec_trigger = function() {
  					if (chain_opts[_Debug]) log_msg("script execute start: "+script_obj.real_src);
  					exec_trigger();
  				}
  				advance_exec_cursor(); // will only check for 'ready' scripts to be executed
  			}
  
  			// called when a script has finished executing
  			function chain_script_executed(script_obj,chain_group) {
  				if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);
  				script_obj.ready = script_obj.finished = true;
  				script_obj.exec_trigger = null;
  				// check if chain group is all finished
  				for (var i=0; i<chain_group.scripts.length; i++) {
  					if (!chain_group.scripts[i].finished) return;
  				}
  				// chain_group is all finished if we get this far
  				chain_group.finished = true;
  				advance_exec_cursor();
  			}
  
  			// main driver for executing each part of the chain
  			function advance_exec_cursor() {
  				if (chain_is_corked) return;
  				while (exec_cursor < chain.length) {
  					if (is_func(chain[exec_cursor])) {
  						if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);
  						try { chain[exec_cursor++](); } catch (err) {
  							if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);
  						}
  						continue;
  					}
  					else if (!chain[exec_cursor].finished) {
  						if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
  						break;
  					}
  					exec_cursor++;
  				}
  				// we've reached the end of the chain (so far)
  				if (exec_cursor == chain.length) {
  					scripts_currently_loading = false;
  					group = false;
  				}
  			}
  
  			// setup next chain script group
  			function init_script_chain_group() {
  				if (!group || !group.scripts) {
  					chain.push(group = {scripts:[],finished:true});
  				}
  			}
  
  			// API for $LAB chains
  			chainedAPI = {
  				// start loading one or more scripts
  				script:function(){
  					for (var i=0; i<arguments.length; i++) {
  						(function(script_obj,script_list){
  							var splice_args;
  
  							if (!is_array(script_obj)) {
  								script_list = [script_obj];
  							}
  							for (var j=0; j<script_list.length; j++) {
  								init_script_chain_group();
  								script_obj = script_list[j];
  
  								if (is_func(script_obj)) script_obj = script_obj();
  								if (!script_obj) continue;
  								if (is_array(script_obj)) {
  									// set up an array of arguments to pass to splice()
  									splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
  									splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
  									[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
  									j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
  									continue;
  								}
  								if (typeof script_obj == "string") script_obj = {src:script_obj};
  								script_obj = merge_objs(script_obj,{
  									ready:false,
  									ready_cb:chain_script_ready,
  									finished:false,
  									finished_cb:chain_script_executed
  								});
  								group.finished = false;
  								group.scripts.push(script_obj);
  								do_script(chain_opts,script_obj,group,(
  									(can_use_preloading && scripts_currently_loading) || chain_is_corked
  								));
  								scripts_currently_loading = true;
  
  								if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
  							}
  						})(arguments[i],arguments[i]);
  					}
  					return chainedAPI;
  				},
  				// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
  				wait:function(){
  					if (arguments.length > 0) {
  						for (var i=0; i<arguments.length; i++) {
  							chain.push(arguments[i]);
  						}
  						group = chain[chain.length-1];
  					}
  					else group = false;
  
  					advance_exec_cursor();
  
  					return chainedAPI;
  				},
  				cork:function(){
  					if (chain_opts[_Debug]) log_msg("$LAB.cork()");
  					chain_is_corked = true;
  					return chainedAPI;
  				},
  				uncork:function(){
  					if (chain_opts[_Debug]) log_msg("$LAB.uncork()");
  					if (chain_is_corked) {
  						chain_is_corked = false;
  						advance_exec_cursor();
  					}
  					return chainedAPI;
  				}
  			};
  
  			// the first chain link API (includes `setOptions` only this first time)
  			return {
  				script:chainedAPI.script,
  				wait:chainedAPI.wait,
  				cork:chainedAPI.cork,
  				uncork:chainedAPI.uncork,
  				setOptions:function(opts){
  					merge_objs(opts,chain_opts);
  					return chainedAPI;
  				}
  			};
  		}
func_code_string: function create_chain() {
  			var chainedAPI,
  				chain_opts = merge_objs(global_defaults,{}),
  				chain = [],
  				exec_cursor = 0,
  				scripts_currently_loading = false,
  				chain_is_corked = false,
  				group
  			;
  
  			// called when a script has finished preloading
  			function chain_script_ready(script_obj,exec_trigger) {
  				if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);
  				script_obj.ready = true;
  				script_obj.exec_trigger = function() {
  					if (chain_opts[_Debug]) log_msg("script execute start: "+script_obj.real_src);
  					exec_trigger();
  				}
  				advance_exec_cursor(); // will only check for 'ready' scripts to be executed
  			}
  
  			// called when a script has finished executing
  			function chain_script_executed(script_obj,chain_group) {
  				if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);
  				script_obj.ready = script_obj.finished = true;
  				script_obj.exec_trigger = null;
  				// check if chain group is all finished
  				for (var i=0; i<chain_group.scripts.length; i++) {
  					if (!chain_group.scripts[i].finished) return;
  				}
  				// chain_group is all finished if we get this far
  				chain_group.finished = true;
  				advance_exec_cursor();
  			}
  
  			// main driver for executing each part of the chain
  			function advance_exec_cursor() {
  				if (chain_is_corked) return;
  				while (exec_cursor < chain.length) {
  					if (is_func(chain[exec_cursor])) {
  						if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);
  						try { chain[exec_cursor++](); } catch (err) {
  							if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);
  						}
  						continue;
  					}
  					else if (!chain[exec_cursor].finished) {
  						if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
  						break;
  					}
  					exec_cursor++;
  				}
  				// we've reached the end of the chain (so far)
  				if (exec_cursor == chain.length) {
  					scripts_currently_loading = false;
  					group = false;
  				}
  			}
  
  			// setup next chain script group
  			function init_script_chain_group() {
  				if (!group || !group.scripts) {
  					chain.push(group = {scripts:[],finished:true});
  				}
  			}
  
  			// API for $LAB chains
  			chainedAPI = {
  				// start loading one or more scripts
  				script:function(){
  					for (var i=0; i<arguments.length; i++) {
  						(function(script_obj,script_list){
  							var splice_args;
  
  							if (!is_array(script_obj)) {
  								script_list = [script_obj];
  							}
  							for (var j=0; j<script_list.length; j++) {
  								init_script_chain_group();
  								script_obj = script_list[j];
  
  								if (is_func(script_obj)) script_obj = script_obj();
  								if (!script_obj) continue;
  								if (is_array(script_obj)) {
  									// set up an array of arguments to pass to splice()
  									splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
  									splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
  									[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
  									j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
  									continue;
  								}
  								if (typeof script_obj == "string") script_obj = {src:script_obj};
  								script_obj = merge_objs(script_obj,{
  									ready:false,
  									ready_cb:chain_script_ready,
  									finished:false,
  									finished_cb:chain_script_executed
  								});
  								group.finished = false;
  								group.scripts.push(script_obj);
  								do_script(chain_opts,script_obj,group,(
  									(can_use_preloading && scripts_currently_loading) || chain_is_corked
  								));
  								scripts_currently_loading = true;
  
  								if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
  							}
  						})(arguments[i],arguments[i]);
  					}
  					return chainedAPI;
  				},
  				// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
  				wait:function(){
  					if (arguments.length > 0) {
  						for (var i=0; i<arguments.length; i++) {
  							chain.push(arguments[i]);
  						}
  						group = chain[chain.length-1];
  					}
  					else group = false;
  
  					advance_exec_cursor();
  
  					return chainedAPI;
  				},
  				cork:function(){
  					if (chain_opts[_Debug]) log_msg("$LAB.cork()");
  					chain_is_corked = true;
  					return chainedAPI;
  				},
  				uncork:function(){
  					if (chain_opts[_Debug]) log_msg("$LAB.uncork()");
  					if (chain_is_corked) {
  						chain_is_corked = false;
  						advance_exec_cursor();
  					}
  					return chainedAPI;
  				}
  			};
  
  			// the first chain link API (includes `setOptions` only this first time)
  			return {
  				script:chainedAPI.script,
  				wait:chainedAPI.wait,
  				cork:chainedAPI.cork,
  				uncork:chainedAPI.uncork,
  				setOptions:function(opts){
  					merge_objs(opts,chain_opts);
  					return chainedAPI;
  				}
  			};
  		}
func_documentation_string: creates a closure for each separate chain spawned from this $LAB instance, to keep state cleanly separated between chains