Commits

Mathias Panzenböck  committed 565bbf6

require.js: added require.Module and include

  • Participants
  • Parent commits e6fe0c6

Comments (0)

Files changed (1)

-const module = {
-	id: null,
-	uri: window.location.protocol + '://' + location.host + location.pathname,
-	path: location.pathname
-};
 const require = (function (_eval) {
+	var location = window.location;
 	var loading = {};
 	var loaded  = {};
 	var paths   = [];
+
+	function notSetable (name) {
+		return function () {
+			throw new Error('field '+name+' is not settable');
+		};
+	}
+
+	function property (obj, name, getter, setter) {
+		obj.__defineGetter__(name, getter);
+		obj.__defineSetter__(name, setter || notSetable(name));
+	}
+
+	function Module() {
+	}
+
+	function ModuleInfo(id, uri, path, parent) {
+		property(this, 'uri', function () {
+			return uri;
+		});
+		
+		property(this, 'path', function () {
+			return path;
+		});
+
+		property(this, 'id', function () {
+			return id;
+		});
+
+		property(this, 'parent', function () {
+			return parent;
+		});
+	}
+
+	var main = new ModuleInfo(
+		location.pathname,
+		location.protocol + '//' + location.host + location.pathname,
+		location.pathname);
 	
 	function normpath (path) {
 		var newpath = [];
 			return __require(moduleName, opts, parent);
 		}
 		
-		_require.__proto__ = new Function();
-		_require.__proto__.__defineGetter__('paths', function () {
+		property(_require, 'Module', function () {
+			return Module;
+		});
+		property(_require, 'main', function () {
+			return main;
+		});
+		property(_require, 'paths', function () {
 			return paths;
 		});
-		_require.__proto__.__defineGetter__('isLoaded', function () {
+		property(_require, 'isLoaded', function () {
 			return function (uri) {
 				return uri in loaded; // || uri in loading; ?
 			};
 
 		if (getters) {
 			for (name in getters) {
-				_require.__proto__.__defineGetter__(name, getters[name]);
+				property(_require, name, getters[name]);
 			}
 		}
 
 	}
 
 	function __require (moduleName, opts, parent) {
-		var location = window.location;
 		var search = false;
 		var pathIndex = 0;
-		var prefix =  location.protocol + '://' + location.host;
+		var prefix =  location.protocol + '//' + location.host;
 		var id;
 		var reluri;
 		var uri;
 		}
 	
 		if (moduleObj === undefined) {
-			loading[uri] = moduleObj = {};
+			loading[uri] = moduleObj = new Module();
 	
-			var newModule = {id: id, uri: uri, path: reluri, parent: parent};
-			var argnames = ['exports', 'require', 'module'];
-			var args = [moduleObj, make_require(newModule), newModule];
+			var newModule = new ModuleInfo(id, uri, reluri, parent);
+			var globals = {
+				exports: moduleObj,
+				include: include,
+				require: make_require(newModule),
+				module:  newModule,
+			};
 	
 			if (opts.globals) {
 				for (argname in opts.globals) {
-					if (!/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(argname)
-							|| argname == 'exports'
-							|| argname == 'require'
-							|| argname == 'module') {
+					if (!/^[_a-zA-Z][_a-zA-Z0-9]*$/.test(argname) || argname in globals) {
 						throw new Error('Illegal global name: '+argname);
 					}
-					argnames.push(argname);
-					args.push(opts.globals[argname]);
+					globals[argname] = opts.globals[argname];
 				}
 			}
 	
 	
 			function transferError () {
 				if (search && xhr.status == 404 && (pathIndex+1) < paths.length) {
-					newModule.path = reluri = '/' + normpath(paths[++pathIndex] + '/' + id + '.js');
-					newModule.uri = prefix + reluri;
+					reluri = '/' + normpath(paths[++pathIndex] + '/' + id + '.js');
+					uri = prefix + reluri;
+					globals.module = newModule = new ModuleInfo(id, uri, reluri, parent);
+					globals.require = make_require(newModule);
 					xhr.open('GET', reluri, opts.async);
 					xhr.send(null);
 					return;
 	
 				try {
 					_eval(
-						'(function ('+argnames.join(',')+') { ' +
-						xhr.responseText+' })').apply(null, args);
+						'(function (globals) { with (globals) { ' +
+						xhr.responseText+' }})')(globals);
 							
 					delete loading[uri];
 					loaded[uri] = moduleObj;
 		return moduleObj;
 	}
 	
-	return make_require(module, {
+	return make_require(main, {
 		clear: function () {
 			return function () {
 				loading = {};
 			};
 		}
 	});
-	// be careful so that nothing is bound to the closure made by eval:
+	// be careful so that as few as possible is bound to the closure made by eval:
 })(function (code) { return eval(code); });
+const module  = require.main;
+const include = function (moduleName, opts) {
+	if (opts) {
+		opts.async = false;
+	}
+	var module = require(moduleName, opts);
+	
+	for (name in module) {
+		this[name] = module[name];
+	}
+	return module;
+};