<html>
<head>
<script>
function test() { clear(); try { var n = new nest(); n.runAsync(app, "main"); } catch(e) { show(e.message || e.description); } }
function clear() { document.getElementById("leftinput").value = ""; document.getElementById("rightinput").value = ""; }
function show(s) { var out = document.getElementById("rightinput"); //alert(s); out.value += "\r\n--------------------\r\n" + s + "\r\n"; }
function showLeft(s) { var out = document.getElementById("leftinput"); //alert(s); out.value += "\r\n--------------------\r\n" + s + "\r\n"; }
function showObject(m) { var out = document.getElementById("testoutput"); var s = ""; for (var k in m) { if (!m.hasOwnProperty(k)) continue; s += k + " : " + m[k] + "\r\n"; } show(s); }
/********************************************* ********************************************* * NEST * * A crazy JavaScript module system * * Version 0.2 * * Copyright Julian Turner 2009 * ********************************************* *********************************************/ function nest( moduleSource /*: (Function,Object,String)*/ /* OPTIONAL*/ ) /*: Object*/ { copyright : "Julian Turner 2009"; version : "0.2"; namespace : "nest";
nest (
[moduleSource : Function|Object|String]
[async : Boolean]
) [: Any]
The principal function container for the nest module system.
It is activated by direct calling new nest()
. Alternatively just calling nest()
will return a new nest()
created by the function for you.
moduleSource : Function|Object|String [OPTIONAL]
You can supply an initial module which nest will immediately start loading.
async : Boolean [OPTIONAL]
Whether to load moduleSource
on an asynchronous basis. You should do this if the moduleSource
is specified as a file name, or if any of its dependencies still need to be downloaded.
Object
Returns a copy of the new nest()
instance created to contain your modules.
Nothing.
None
None
var NEST_GLOBAL /*: (Window,Any)*/ = (function(){return this;})(); var NEST_FUNCTION /*: Function*/ = arguments.callee || NEST_GLOBAL.nest; var NEST_IS_IE /*: Boolean*/ = false /*@cc_on || true @*/;
Internal Variables - global
GLOBAL
A reference to the Window
or other global object hosting the ECMAScript instance.
NEST_FUNCTION
A reference to the nest
Function. This is because the name nest
is overwritten internally to refer to the instance of nest created by calling new nest()
, which is the root of the nest namespace.
// Option 1 var nest /*: Object*/ = (this instanceof NEST_FUNCTION) ? this : new NEST_FUNCTION(); // Option 2 // NEST_GLOBAL.nest /*: Object*/ = (this instanceof nest) ? this : new nest(); // for (var k /*: String*/ in NEST_FUNCTION) { nest[k] = NEST_FUNCTION[k]; }
Instantiation
To function, nest
needs to be activated.
Option 1
Creates a new nest()
instantiation as an internal variable, and returns this object. This option lets you re-use the nest
function for multiple instantiations.
Option 2
Overwrites the global nest
function with the new nest()
instance object, so that you have only one nest instantiation in your application.
var NEST_FATAL_ERROR /*: Boolean*/ = false; var NEST_LAST_CLOSURE /*: Function*/; var NEST_LOADING_MODULE_INSTANCE /*: Object*/ = nest;
Private Variables - module loading
NEST_FATAL_ERROR : Boolean
Used to record fatal errors, particularly for module loading, to cancel timeouts.
NEST_LOADING_MODULE_INSTANCE : Object
This represents the current module object that is being instantiated. Each module overwrites this variable when it is loading. In effect it always stores the last instantiated module object.
NEST_LAST_CLOSURE : Function
Each module has its own nested closure function inside which the next module is instantiated. This represents effectively the closure function of the last instantiated module.
function closure (jsSource /*: String*/) /*: Any*/ { var returnValue; eval(jsSource); return returnValue; } NEST_LAST_CLOSURE = closure;
closure (
jsSource : String
) : Any
nest
and each module has one of these. Each module is loaded by eval'ing new module_identifier()
in the closure
function of the previous module.
E.g. a closure stack of nest [nest_util [nest_dom [nest_gui [app]]]]
app
then has internal scope chain access to the other modules and can access them with or without a namespace prefix if you wish.
jsSource : String
Module source.
It can also be used for inspecting the internal variables and function declarations of modules.
Any
The eval'd code can set an external variable returnValue
which is then returned by the function.
Nothing
None
None
function loadModule( moduleSource /*: (Function, String, Object)*/ ) /*: Module*/ { NEST_FATAL_ERROR = false; var module /*: Module*/ = new Module(moduleSource); module.loadRequires(); // synchronous module.load(); return module; } exports(loadModule);
loadModule (
module : Function|Object|String
) : Module
This performs a basic synchronous load of the supplied module and all its dependencies.
It assumes that the module's source (and that of all its dependencies) are fully loaded at the point it is called.
Use loadModuleAsync
for all other situations.
moduleSource : Function|Object|String
The module can either be supplied as a function (in which case toString
is called), or the function already in toString
form, or an Object which has the module source as one of its properties. See the separate entry on module format.
Module
An internal object created to process information about a Module as part of the module loading process.
nest.Module
nest.Module.loadRequires
nest.Module.load
None
None
function loadModuleAsync( moduleSource /*: (Function, String, Object)*/ ) /*: Object*/ { NEST_FATAL_ERROR = false; var module /*: Module*/ = new Module(moduleSource); module.loadAsync(); // requires are loaded through this function return module; } exports(loadModuleAsync);
loadModuleAsync (
module : Function|Object|String
) : Object
This is the entry function for asynchronous loading. If any dependency needs to be asynchronously loaded, then the whole dependency chain must be asynchronously loaded.
module : Function|Object|String
A module Function.
The source code of a module Function
A module specification Object
A file name pointing to one of the above. The file name must end in ".js".
Module
An internal object created to process information about a Module as part of the module loading process.
nest.exports
nest.Module
nest.Module.loadAsync
None
None
function run( moduleSource /*: (Function,Object,String)*/, mainFunction /*: String*/ ) /*: Module*/ { mainFunction = (typeof mainFunction == "string") ? mainFunction : "main"; var module /*: Module*/ = loadModule(moduleSource); module.instance[mainFunction](); return module; } exports(run);
run (
moduleSource : Function|Object|String
[mainFunction : String]
) : Any
An alternative means of running your application. It is effectively the same as loadModule
, but (a) assumes that you are referring to the final application module (so that all dependencies are loaded implicitly), and (b) calls a method of your application module called main
or whatever mainFunction
refers to.
Synchronous only.
moduleSource : Function|Object|String
Your final application module source.
mainFunction : String [OPTIONAL] [DEFAULT "main()"]
A module exported method to call when it has finished loadined.
Module
The Module object of the application module.
nest.exports
nest.loadModule
None
None
function runAsync( moduleSource /*: (Function,Object,String)*/, mainFunction /*: String*/ ) /*: Any*/ { mainFunction = (typeof mainFunction == "string") ? mainFunction : "main"; var module /*: Module*/ = loadModuleAsync(moduleSource); call("show", "Application '" + (module.filePath || module.identifier) + "' started loading on " + new Date()); NEST_GLOBAL.setTimeout(deferred, 1); function deferred() { if (NEST_FATAL_ERROR) { return; } if (module.isLoaded) { call("show", "Application '" + (module.filePath || module.identifier) + "' finished loading on " + new Date()); module.instance[mainFunction](); } else { NEST_GLOBAL.setTimeout(deferred, 1); } } return module; } exports(runAsync);
runAsync (
moduleSource : Function|Object|String
mainFunction : String
) : Any
An alternative means of running your application. It is effectively the same as loadModuleAsync
, but (a) assumes that you are referring to the final application module (so that all dependencies are loaded implicitly), and (b) calls a method of your application module called main
or whatever mainFunction
refers to.
moduleSource : Function|Object|String
A module Function.
The source code of a module Function
A module specification Object
A file name pointing to one of the above. The file name must end in ".js".
mainFunction : String [OPTIONAL] [DEFAULT "main()"]
A module exported method to call when it has finished loadined.
Module
nest.exports
nest.loadModuleAsync
None
None
function inspect(findName /*: String*/) /*: Any*/ { var source = "returnValue = " + findName; return NEST_LAST_CLOSURE(source); } exports(inspect); // if you want to share the innards to the world
inspect (
findName : String
) : Any
Allows you to retrieve any internally declared variable or function declaration.
findName : String
Identifier for the property.
Any
Nothing
None
None
function exports( exportItem /*: Any*/, alias /*: String*/ ) /*: void*/ { if (alias) { NEST_LOADING_MODULE_INSTANCE[alias] = exportItem; } if (exportItem instanceof Function) { var identifier /*: String*/ = Function_GetIdentifier(exportItem); NEST_LOADING_MODULE_INSTANCE[identifier] = exportItem; exportItem.ownerModule = NEST_LOADING_MODULE_INSTANCE; // for some reflection } }
exports (
exportItem : Any
alias : String
) : void
Manages the exporting of items from a module.
Used to provide some meta-data
The items are added as properties to an internal object called NEST_LOADING_MODULE_INSTANCE
which is set to the this
value of the currently loading module.
exportItem : Any
Function or variable to export.
alias : String
Property name to give it.
void
nest.Function_GetIdentifier
None
None
function Function_GetIdentifier( f /*: (Function,String)*/ ) /*: String*/ { if (f instanceof Function) { f = f.toString(); } var funcPattern /*: RegExp*/ = /^\s*function\s+([A-Za-z0-9_$]+)\s*\(/; var execResult /*: Array.<String>*/ = funcPattern.exec(f); if (!execResult) { return ""; } var functionIdentifier /*: String*/ = execResult[1]; if (functionIdentifier == "anonymous") { return ""; } return functionIdentifier; } exports(Function_GetIdentifier)
Function_GetIdentifierFromString (
functionSource : String
) : String
Extracts the function identifier from a supplied Functionm.
f : Function|String
If a Function, then toString
is called.
If a String, then the result of calling toString
on the function.
String
The identifier, or anonymous
Nothing
None
None
function LoadScript( src /*: String*/, callBack /*: Function*/, loadIdentifier /*: String*/, waitForMS /*: Number*/, timeout /*: Function*/ ) /*: void*/ { var head /*: HTMLHeadElement*/ = NEST_GLOBAL.document.getElementsByTagName('head')[0]; var scr /*: HTMLScriptElement*/ = NEST_GLOBAL.document.createElement('script'); var loaded /*: Boolean*/ = false; scr.type = "text/javascript"; if (callBack) { scr.onreadystatechange = function () { call("show", "Ready State for '" + src + "' is '" + scr.readyState + "'"); if (!loaded && (scr.readyState == 'complete' || (NEST_IS_IE ? scr.readyState == 'loaded' : false))) { loaded = true; callBack(); } } scr.onload = function () { call("show", "Onload for '" + src + "' just fired."); if (!loaded) { loaded = true; callBack(); } } } scr.src = src; head.appendChild(scr); if (loadIdentifier) { if (!waitForMS) { waitForMS = 30000; // thirty seconds } var started /*: Date*/ = new Date(); var loadCheck /*: Function*/ = function () { call("show", "Load check for '" + src + "' identifier '" + loadIdentifier + "' on " + new Date()); if (loaded == true) { return; } if (NEST_GLOBAL[loadIdentifier]) { call("show", "Source code for file '" + src + "' identifier '" + loadIdentifier + "' available on " + new Date()); loaded = true; callBack(); return; } var now /*: Date*/ = new Date(); if (now - started > waitForMS) { loaded = true; timeout(); } NEST_GLOBAL.setTimeout(loadCheck, 1); }; NEST_GLOBAL.setTimeout(loadCheck, 1); } } exports(LoadScript);
LoadScript (
src : String
[callBack : Function]
[loadIdentifier : String
waitForMS : Number
timeout : Function]
) : void
Inserts a script
element in into the head
of the document and loads the resource pointed to be the src
attribute.
src : String
The URL (absolute or relative) for a resource that returns a JavaScript file.
callBack : Function
Optional callback function.
loadIdentifier : String
waitForMS : Numbermiliseconds
timeout : Function
Optional name of a global identifier that the script will create if it loads and runs correctly. Supplying this will trigger a setTimeout
which will keep looking for the identifier for the waitFor
miliseconds and call timeout
on failure.
void
nest.GLOBAL
None
None
var Module /*: Function*/ = (function(){
Module
A simple object used to manage the module you are loading.
function Module( moduleSource /*: (Function,String,Object)*/ ) /*: void*/ { // PUBLIC this.isNestModule /*: Boolean*/ = true; this.author /*: String*/ = ""; this.version /*: String*/ = ""; this.identifier /*: String*/ = ""; this.filePath /*: String*/ = ""; this.fileName /*: String*/ = ""; this.namespace /*: String*/ = ""; this.requires /*: Array.<String>*/ = []; this.source /*: (Function,String)*/ = ""; // PRIVATE this.isDownloaded /*: Boolean*/ = false; this.isPreProcessed /*: Boolean*/ = false; this.requiresInitiatied /*: Boolean*/ = false; this.isLoaded /*: Boolean*/ = false; this.instance /*: Object*/ = null; // created on load this.namespaceChain /*: Array.<String>*/ = []; this.requiresFileNames /*: Array.<String>*/ = []; this.requiresModuleIdentifiers /*: Array.<String>*/ = []; if (moduleSource) { this.initialise(moduleSource); } } var constr /*: Function*/ = Module; var proto /*: Object*/ = Module.prototype;
Module (
[moduleSource : Function|String|Object]
) : void
The constructor function.
moduleSource : Function|String|Object [OPTIONAL]
A function, string or object containing the module source, or a file path.
Alternatively you can call initialise(moduleSource)
yourself at any time.
void
nest.Module.initialise
None
None
function initialise( moduleSource /*: (Function,String,Object)*/ ) /*: String*/ { // Pointing to variable or function identifier containing the module source if (typeof moduleSource == "string" && NEST_LOADING_REQUIRE_REGEXP.test(moduleSource)) { var execResult /*: RegExp*/ = NEST_LOADING_REQUIRE_REGEXP.exec(moduleSource); this.filePath = execResult[0]; this.fileName = execResult[6]; if (/\.js$/.test(this.fileName)) { this.identifier = this.fileName.substring(0, this.fileName.length - 3); } else { this.identifier = this.fileName; this.fileName = this.fileName + ".js"; } this.identifier = this.identifier.split(".").join("_"); return; } if (moduleSource instanceof Function) { this.source /*: String*/ = moduleSource.toString(); } else if (typeof moduleSource == "string") // function source code { this.source /*: String*/ = moduleSource; } else if (moduleSource instanceof Module || (moduleSource instanceof Object && moduleSource.isNestModule)) { for (var k /*: String*/ in moduleSource) { this[k] = moduleSource[k]; } } else { NEST_FATAL_ERROR = false; throw new Error("Error > nest > Module > initialise() > Supplied argument does not appear to be a valid moduleSource. Argument supplied was: " + moduleSource); } this.preProcess(moduleSource); } proto.initialise = initialise;
initialise (
moduleSource : Function|String|Object
) : void
Carries out some basic initialisation. Will call preProcess
if the full module source code is supplied. Otherwise it will just parse the file name for use in dynamic script loading.
moduleSource : Function|String|Object
A module function or object, or a file name.
void
nest.Module.preProcess
None
None
var NEST_LOADING_MODULE_TIMEOUT /*: int*/ = 30000; var NEST_LOADING_STACK /*: Array.<Object>*/ = []; //var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3})?(([^\\\/\? ]*[\\\\/])*)([^\\\/\? ]+)(\?[^\? ]+)?)\s*$/; // paren 6 //var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3})?(([^\\\/\? ]*[\\\\/])*)([A-Za-z0-9\.]+)(\?[^\? ]+)?)\s*$/; // paren 6 var NEST_LOADING_REQUIRE_REGEXP /*: RegExp*/ = /^\s*(((http|https|file):[\/\\]{2,3}|[\/\\]{1,2})?(([^\\\/\? ]*[\\\\/])*)([A-Za-z0-9\.]+)(\?[^\? ]+)?)\s*$/; // paren 6 var NEST_LOADED_MODULES /*: Object.<Object>*/ = {"nest" : nest};
Stattic - Private - Variables - MODULE_LOADING
NEST_LOADING_MODULE_TIMEOUT : Number [DEFAULT 30000 MS]
How long to wait to load a module before a fatal error.
NEST_LOADING_STACK : Array.<Object>
Each module and its require modules are put on the stack. A module is not loaded until its requires have been successfully loaded. The process is recursive, as any requires of requires are added to the stack, etc. Requires always put at the top of the stack.
NEST_LOADING_REQUIRE_REGEXP : RegExp
Simply regular expression to process http
, https
, file
and normal file paths.
NEST_LOADED_MODULES : Object.<Object>
Stores each instance of a module, under both its namespace, and its function constructor identifier.
function preProcess() /*: void*/ { this.isPreProcessed = true; // major crash without this this.preProcessIdentifier(); this.preProcessClosure(); this.preProcessInstanceReference(); this.preProcessNamespace(); this.preProcessRequires(); this.isDownloaded = true; if (NEST_LOADED_MODULES[this.namespace] || NEST_LOADED_MODULES[this.identifier]) { this.isLoaded = true; } } proto.preProcess = preProcess;
preProcess (
) : void
Carries out some pre-processing of the source code of a module, prior to evaluation.
void
nest.Module.preProcessClosure
nest.Module.preProcessIdentifier
nest.Module.preProcessInstanceReference
nest.Module.preProcessNamespace
nest.Module.preProcessRequires
None
None
function load() /*: void*/ { if (this.isLoaded) { return; } if (NEST_LOADED_MODULES[this.namespace] || NEST_LOADED_MODULES[this.identifier]) { this.isLoaded = true; return; } call("show", "Loaded module '" + this.identifier + "' with namespace '" + this.namespace + "'."); var evalSource /*: String*/ = this.source + "; returnValue = new " + this.identifier + "();" + this.identifier + " = null;"; var returnValue /*: Any*/; try { returnValue = NEST_LAST_CLOSURE(evalSource); if (!returnValue) { throw new Error("Module '" + this.identifier + "' does not refer to valid module function."); } } catch(e) { NEST_FATAL_ERROR = true; throw new Error("nest > Module > load > Module name '" + this.identifier + "' threw an error when loaded. Error was '" + (e.message || e.description) + "'."); } NEST_LOADED_MODULES[this.namespace] = NEST_LOADING_MODULE_INSTANCE; NEST_LOADED_MODULES[this.identifier] = NEST_LOADING_MODULE_INSTANCE; this.createNamespaceObjects(); this.isLoaded = true; this.instance = NEST_LOADING_MODULE_INSTANCE; } proto.load = load;
load (
) : void
This is the final step in the loading chain. When the source code for a module and its dependency chain has been downloaded and processed, this function instantiates the module.
None
void
nest.NEST_LAST_CLOSURE
nest.Module.createNamespaceObjects
None
None
function loadAsync() /*: void*/ { var me /*: Module*/ = this; var timeout /*: int*/ = NEST_LOADING_MODULE_TIMEOUT; NEST_LOADING_STACK.push(this); if (!this.isDownloaded && this.filePath) { this.loadAsyncFile(); } call("show", "Async observer started for module '" + me.identifier + "' on " + new Date()); NEST_GLOBAL.setTimeout(observe, 1); function observe() { if (NEST_FATAL_ERROR) { return; } if (me.isDownloaded && !me.isPreProcessed) { me.preProcess(); me.loadRequires(true); } if (me.isDownloaded && me.isPreProcessed && !me.requiresInitiated) { me.loadRequires(true); } if (me.isPreProcessed && NEST_LOADING_STACK[NEST_LOADING_STACK.length - 1] === me) { call("show", "Async observer completed for module '" + me.identifier + "' on " + new Date()); NEST_LOADING_STACK.pop(); me.load(); return; } if (timeout - 1 < 0) { NEST_FATAL_ERROR = true; throw new Error("Error > nest > Module > loadAsync() > Failed to load '" + me.identifier + "'. Timed out."); return; } NEST_GLOBAL.setTimeout(observe, 1); } } proto.loadAsync = loadAsync;
loadAsync (
) : void
Starts an asynchronous loading process for a module, so that a watcher is started to watch for when the module source has been downloaded. A separate watcher is started for each dependency. The load
for a module is only called when it is at the top of the stack (i.e. any dependencies have been loaded.
void
nest.Module.load
nest.Module.loadAsyncFile
nest.Module.loadRequires
nest.Module.preProcess
None
None
function loadRequires( async /*: Boolean*/ ) /*: void*/ { this.requiresInitiated = true; if (!this.requires.length) { return; } var extension /*: RegExp*/ = /\.js$/; var moduleFilePath /*: String*/ = ""; var moduleFileName /*: String*/ = ""; var moduleIdentifier /*: String*/ = ""; var moduleSource /*: (Function,String,Object)*/; var module /*: Module*/; for (var i /*: int*/ = 0; i < this.requires.length; i++) { moduleIdentifier = this.requiresModuleIdentifiers[i]; call("show", "Loading require for module '" + this.identifier + "' : '" + moduleIdentifier + "'"); if (NEST_LOADED_MODULES[moduleIdentifier]) { call("show", "Already loaded."); continue; } moduleSource = NEST_GLOBAL[moduleIdentifier] || NEST_FUNCTION[moduleIdentifier]; if (moduleSource) { call("show", "Dependency '" + moduleIdentifier + "' for module '" + this.identifier + "' : source available."); module = new Module(moduleSource); if (async) { module = new Module(moduleSource); module.loadAsync(); } else { module = new Module(moduleSource); module.loadRequires(); module.load(); } continue; } moduleFilePath = this.requires[i]; moduleFileName = this.requiresFileNames[i]; call("show", "Loadling require file '" + moduleFilePath + "' for module '" + this.identifier + "'."); if (!async || !extension.test(moduleFileName)) { NEST_FATAL_ERROR = true; throw new Error("nest > Module > loadRequires > Module '" + this.requires[i] + "' is either not a valid file name, or it does not refer to an already loaded module, or it is a file name and you are not loading in asynchronous mode."); } module = new Module(moduleFilePath); module.loadAsync(); } } proto.loadRequires = loadRequires;
loadRequires (
async : Boolean
) : void
Initiates separate loading of each require in a module. This will be on an async basis if async
is true
. When loading requires, nest will first check to see if (a) the module has already been fully loaded, or (b) if the module source is at least available.
async : Boolean
All requires loaded on an asynchronous basis.
void
nest.Module.load
nest.Module.loadAsync
None
None
function preProcessIdentifier() /*: void*/ { if (this.identifier) { return; } this.identifier = Function_GetIdentifier(this.source); if (!this.identifier || this.identifier == "anonymous") { NEST_FATAL_ERROR = true; throw new Error("nest > Module > preProcessIdentifier > Module does not have a valid identifier for the module function. Module source : " + this.source); } // optional to recover memory? //if (NEST_GLOBAL[this.identifier]) //{ // NEST_GLOBAL[this.identifier] = null; //} //if (NEST_FUNCTION[this.identifier]) //{ // NEST_FUNCTION[this.identifier] = null; //} } proto.preProcessIdentifier = preProcessIdentifier;
preProcessIdentifier (
) : void
Extract the function identifier from the module source.
void
nest.Function_GetIdentifier
None
None
function preProcessClosure() /*: void*/ { var start /*: int*/ = 0; start = this.source.indexOf("{"); if (start == -1) { NEST_FATAL_ERROR = true; throw new Error("nest > Module > preProcessInstanceReference > Module source may not be a function. Source : " + this.source.substring(0, 40) + "..."); } this.source = this.source.substring(0, start + 1) + "function closure (jsSource \/*: String*\/) \/*: Any*\/ { var returnValue \/*: Any*\/; eval(jsSource); return returnValue; }NEST_LAST_CLOSURE = closure;" + this.source.substring(start + 1, this.source.length); } proto.preProcessClosure = preProcessClosure;
preProcessClosure (
) : void
Inject a function into the module source which is the modules sub-closure used by nest.
None
void
None
None
function preProcessInstanceReference() /*: void*/ { var ref /*: RegExp*/ = /NEST_LOADING_MODULE_INSTANCE/; var start /*: int*/ = 0; if (ref.test(this.source)) { return; } start = this.source.indexOf("{"); if (start == -1) { NEST_FATAL_ERROR = true; throw new Error("nest > Module > preProcessInstanceReference > Module source may not be a function. Source : " + this.source.substring(0, 40) + "..."); } this.source = this.source.substring(0, start + 1) + "NEST_LOADING_MODULE_INSTANCE = this;" + this.source.substring(start + 1, this.source.length); } proto.preProcessInstanceReference = preProcessInstanceReference;
preProcessInstanceReference (
) : void
Inject into the module source a reference to NEST_LOADING_MODULE_INSTANCE = this
.
None
void
None
None
function preProcessNamespace() /*: void*/ { var declaration /*: RegExp*/ = /(\{|\}|;|\r|\n)\s*namespace\s*:\s*"\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*"\s*;/; var namespace /*: RegExp*/ = /\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*$/; if (this.namespace && namespace.test(this.namespace)) { this.namespaceChain = this.namespace.split("."); if (!/^nest\./.test(this.namespace)) { this.namespace = "nest." + this.namespace; this.namespaceChain.unshift("nest"); } return; } if (this.source && declaration.test(this.source)) { this.namespace = declaration.exec(this.source)[2]; this.namespaceChain = this.namespace.split("."); if (!/^nest\./.test(this.namespace)) { this.namespace = "nest." + this.namespace; this.namespaceChain.unshift("nest"); } return; } NEST_FATAL_ERROR = true; throw new Error("Module '" + this.identifier + "' does not declare a namespace or the namespace is invalid. Namespace = '" + this.namespace + "'."); } proto.preProcessNamespace = preProcessNamespace;
preProcessNamespace (
) : void
Look for "namespace my.namespace";
in the module source and capture its value.
None.
void
None
None
var declaration /*: RegExp*/ = /"\s*namespace\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*";/; var namespace /*: RegExp*/ = /\s*(([A-Za-z0-9_]+)(\.([A-Za-z0-9_]+))*)\s*$/;
function preProcessRequires() /*: void*/ { var requires /*: Array.<String>*/ = []; var requiresFileNames /*: Array.<String>*/ = []; var requiresModuleIdentifiers /*: Array.<String>*/ = []; var requirePattern /*: RegExp*/ = /(\{|\}|;|\r|\n)\s*requires?\s*:\s*"\s*([^\s]+)\s*"\s*;/g; var execResult /*: Array.<String>*/; var require /*: String*/ = ""; if (this.requires && this.requires.length > 0) { requires = this.requires; for (var i /*: int*/ = 0; i < requires.length; i++) { require = requires[i]; execResult = NEST_LOADING_REQUIRE_REGEXP.exec(require); if (!execResult) { NEST_FATAL_ERROR = true; throw new Error("Error > nest > Module > preProcessRequires() > Require string is invalid for module '" + this.identifier + "'. Require was '" + requires[i] + "'. The actual file name can only have the characters A-Z a-z 0-9 and DOT, and should be a valid ECMAScript identifier."); } require = execResult[6]; requiresFileNames[i] = require; if (/\.js$/.test(require)) { require = require.substring(0, require.length - 3); } require = require.split(".").join("_"); requiresModuleIdentifiers[i] = require; } } else { requirePattern.lastIndex = 0; requires = this.source.match(requirePattern) || []; if (!requires || !requires.length) { return; } for (var i /*: int*/ = 0; i < requires.length; i++) { requirePattern.lastIndex = 0; require = requirePattern.exec(requires[i])[2]; if (!NEST_LOADING_REQUIRE_REGEXP.test(require)) { NEST_FATAL_ERROR = true; throw new Error("Error > nest > Module > preProcessRequires() > Require string is invalid for module '" + this.identifier + "'. Require was '" + requires[i] + "'"); } requires[i] = require; require = NEST_LOADING_REQUIRE_REGEXP.exec(require)[6]; requiresFileNames[i] = require; if (/\.js$/.test(require)) { require = require.substring(0, require.length - 3); } require = require.split(".").join("_"); requiresModuleIdentifiers[i] = require; } } this.requires = requires; this.requiresFileNames = requiresFileNames; this.requiresModuleIdentifiers = requiresModuleIdentifiers; } proto.preProcessRequires = preProcessRequires;
preProcessRequires (
) : void
Look for "require my.require.js";
in the module source and capture its value.
void
None
None
var requirePattern /*: RegExp*/ = /"\s*requires?\s*([^\s]+)\s*";/g;
function loadAsyncFile() /*: void*/ { var me /*: Module*/ = this; function callBack() { if (!NEST_GLOBAL[me.identifier] && !NEST_FUNCTION[me.identifier]) { NEST_FATAL_ERROR = true; throw new Error("Error > nest > Module > loadAsyncFile() > Failed to load '" + me.filePath + "'. Could not find module called '" + me.identifier + "'."); } me.initialise(NEST_GLOBAL[me.identifier] || NEST_FUNCTION[me.identifier]); } function timeout() { NEST_FATAL_ERROR = true; throw new Error("Error > nest > Module > loadAsyncFile() > Failed to load '" + me.filePath + "'. Timed out."); } LoadScript(me.filePath, callBack, me.identifier, NEST_LOADING_MODULE_TIMEOUT, timeout); } proto.loadAsyncFile = loadAsyncFile;
loadAsyncFile (
) : void
If you are using loadAsync
and a file name is encountered, this function handles the actual asynchronous loaading of that module file.
None
void
nest.LoadScript
nest.Module.initialise
None
None
function createNamespaceObjects() /*: void*/ { var chain /*: Array.<String>*/ = this.namespaceChain; var link /*: String*/; var namespace /*: Object*/ = nest; var start /*: int*/ = 0; var existing /*: Boolean*/ = false; if (!chain.length || (chain.length == 1 && chain[0] == "nest")) { existing = true; } else { if (chain[0] == "nest") { start = 1; } for (var i = start; i < chain.length - 1; i++) { link = chain[i]; namespace[link] = namespace[link] || {}; namespace = namespace[link]; } link = chain[chain.length - 1]; if (namespace[link]) { namespace = namespace[link]; existing = true; } else { namespace[link] = namespace = NEST_LOADING_MODULE_INSTANCE; } } if (existing) { for (var k /*: String*/ in NEST_LOADING_MODULE_INSTANCE) { namespace[k] = NEST_LOADING_MODULE_INSTANCE[k]; } } } proto.createNamespaceObjects = createNamespaceObjects;
createNamespaceObjects (
) : void
This is used to create each object in the namespace chain you specify. If you load a module which uses a parent namespace, e.g. nest.util
and nest.util.String
then the util
object will be a merged object.
None
void
None
None
None
return constr; })();
function call( functionName /*: String*/ ) /*: Any*/ { var f /*: Function*/ = NEST_GLOBAL[functionName]; if (!f) { return; } switch(arguments.length) { default: /* Fall through*/ case 1: return f.call(null); break; case 2: return f.call(null, arguments[1]); break; case 3: return f.call(null, arguments[1], arguments[2]); break; } }
This is for temporary debugging use only. Anything called using this will be stripped from the final code.
return moduleSource ? async ? nest.runAsync(moduleSource) : nest.run(moduleSource) : nest;
}
function nest_util() { namespace : "nest.util"; function ExportedFunctionFromUTIL() { show("Hello from util"); } exports(ExportedFunctionFromUTIL); }
var nest_dom = { isNestModule : true, author : "Julian Turner", version : "1", identifier : "nest_dom", namespace : "nest.dom", requires : ["nest.util.js"], source : "function nest_dom(){function ExportedFunctionFromDOM(){show(\"Hello from dom\");ExportedFunctionFromUTIL()}exports(ExportedFunctionFromDOM);}" };
nest["nest_gui"] = { isNestModule : true, author : "Julian Turner", version : "1", identifier : "nest_gui", namespace : "nest.gui", requires : ["nest.dom.js"], source : "function nest_gui(){function ExportedFunctionFromGUI(){show(\"Hello from gui\");ExportedFunctionFromDOM()}exports(ExportedFunctionFromGUI);function PrivateFunctionToInspect(){show(\"You found me\")}};" };
function app() { namespace : "apps.test"; requires : "nest.lib.js"; function main() { show("Hello from app"); ExportedFunctionFromLIB(); inspect("PrivateFunctionToInspect")(); show(nest.util.ExportedFunctionFromUTIL); show(nest.apps.test.main); } exports(main); }
<p style="color:blue; text-decoration:underline; font-bold" onclick="test()" style="cursor:pointer">Test</p> <div style="float:left;"> <h4>Input</h4> <textarea id=leftinput style="width:470px; height:250px;"></textarea> </div> <div style="float:right;"> <h4>Output</h4> <textarea id=rightinput style="width:470px; height:250px;"></textarea> </div>
<v:shape style='width:200;height:200' strokecolor="blue" strokeweight="1px"
coordorigin="0 0" coordsize="200 200">
<v:path id=testPath v="m 0,0 l 0,10, 20,20 e"/>
</v:shape>
<v:curve
from="0px,0px" to="200px,0px"
control1="0px,200px" control2="100px,0px">
</v:curve>
function nest_lib() { namespace : "nest.lib"; requires : "nest.gui"; function ExportedFunctionFromLIB() { show("Hello from lib"); ExportedFunctionFromGUI(); } exports(ExportedFunctionFromLIB); }