mirror of
				https://github.com/Jermolene/TiddlyWiki5
				synced 2025-10-30 23:23:02 +00:00 
			
		
		
		
	Refactor boot.js module execution code
The aim is to expose the underlying cross-platform evalGlobal and evalSandboxed. Also adding the capability for a tiddlywiki.files file to specify a prefix to be added to the text of a file.
This commit is contained in:
		
							
								
								
									
										170
									
								
								boot/boot.js
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								boot/boot.js
									
									
									
									
									
								
							| @@ -67,7 +67,11 @@ Display an error and exit | ||||
| */ | ||||
| $tw.utils.error = function(err) { | ||||
| 	console.error(err); | ||||
| 	if($tw.browser) { | ||||
| 		return null; | ||||
| 	} else { | ||||
| 		process.exit(1); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @@ -270,6 +274,44 @@ $tw.utils.registerFileType = function(type,encoding,extension) { | ||||
| 	$tw.config.contentTypeInfo[type] = {encoding: encoding, extension: extension}; | ||||
| } | ||||
|  | ||||
| /* | ||||
| Run code globally with specified context variables in scope | ||||
| */ | ||||
| $tw.utils.evalGlobal = function(code,context,filename) { | ||||
| 	var contextCopy = $tw.utils.extend({},context,{ | ||||
| 		exports: {} | ||||
| 	}); | ||||
| 	// Get the context variables as a pair of arrays of names and values | ||||
| 	var contextNames = [], contextValues = []; | ||||
| 	$tw.utils.each(contextCopy,function(value,name) { | ||||
| 		contextNames.push(name); | ||||
| 		contextValues.push(value); | ||||
| 	}); | ||||
| 	// Add the code prologue and epilogue | ||||
| 	code = "(function(" + contextNames.join(",") + ") {(function(){\n" + code + ";})();\nreturn exports;\n})\n"; | ||||
| 	// Compile the code into a function | ||||
| 	var fn; | ||||
| 	if($tw.browser) { | ||||
| 		fn = window["eval"](code); | ||||
| 	} else { | ||||
| 		fn = vm.runInThisContext(code,filename);		 | ||||
| 	} | ||||
| 	// Call the function and return the exports | ||||
| 	return fn.apply(null,contextValues); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Run code in a sandbox with only the specified context variables in scope | ||||
| */ | ||||
| $tw.utils.evalSandboxed = $tw.browser ? $tw.utils.evalGlobal : function(code,context,filename) { | ||||
| 	var sandbox = $tw.utils.extend({},context); | ||||
| 	$tw.utils.extend(sandbox,{ | ||||
| 		exports: {}		 | ||||
| 	}); | ||||
| 	vm.runInNewContext(code,sandbox,filename); | ||||
| 	return sandbox.exports; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Creates a PasswordPrompt object | ||||
| */ | ||||
| @@ -399,6 +441,57 @@ $tw.utils.Crypto = function() { | ||||
|  | ||||
| /////////////////////////// Module mechanism | ||||
|  | ||||
| /* | ||||
| Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot' | ||||
| */ | ||||
| $tw.modules.execute = function(moduleName,moduleRoot) { | ||||
| 	var name = moduleRoot ? $tw.utils.resolvePath(moduleName,moduleRoot) : moduleName, | ||||
| 		moduleInfo = $tw.modules.titles[name], | ||||
| 		tiddler = $tw.wiki.getTiddler(name), | ||||
| 		sandbox = { | ||||
| 			module: moduleInfo, | ||||
| 			exports: {}, | ||||
| 			console: console, | ||||
| 			setInterval: setInterval, | ||||
| 			clearInterval: clearInterval, | ||||
| 			setTimeout: setTimeout, | ||||
| 			clearTimeout: clearTimeout, | ||||
| 			$tw: $tw, | ||||
| 			require: function(title) { | ||||
| 				return $tw.modules.execute(title,name); | ||||
| 			} | ||||
| 		}; | ||||
| 	if(!$tw.browser) { | ||||
| 		$tw.utils.extend(sandbox,{ | ||||
| 			process: process | ||||
| 		}); | ||||
| 	} | ||||
| 	if(!moduleInfo) { | ||||
| 		if($tw.browser) { | ||||
| 			return $tw.utils.error("Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name); | ||||
|  | ||||
| 		} else { | ||||
| 			// If we don't have a module with that name, let node.js try to find it | ||||
| 			return require(moduleName); | ||||
| 		} | ||||
| 	} | ||||
| 	// Execute the module if we haven't already done so | ||||
| 	if(!moduleInfo.exports) { | ||||
| 		try { | ||||
| 			// Check the type of the definition | ||||
| 			if(typeof moduleInfo.definition === "string") { // String | ||||
| 				moduleInfo.exports = $tw.utils.evalSandboxed(moduleInfo.definition,sandbox,tiddler.fields.title); | ||||
| 			} else { // Object | ||||
| 				moduleInfo.exports = moduleInfo.definition; | ||||
| 			} | ||||
| 		} catch(e) { | ||||
| 			$tw.utils.error("Error executing boot module " + name + ":\n" + e); | ||||
| 		} | ||||
| 	} | ||||
| 	// Return the exports of the module | ||||
| 	return moduleInfo.exports; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Apply a callback to each module of a particular type | ||||
| 	moduleType: type of modules to enumerate | ||||
| @@ -756,35 +849,6 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) { | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot' | ||||
| */ | ||||
| $tw.modules.execute = function(moduleName,moduleRoot) { | ||||
| 	/*jslint evil: true */ | ||||
| 	var name = moduleRoot ? $tw.utils.resolvePath(moduleName,moduleRoot) : moduleName, | ||||
| 		require = function(modRequire) { | ||||
| 			return $tw.modules.execute(modRequire,name); | ||||
| 		}, | ||||
| 		exports = {}, | ||||
| 		moduleInfo = $tw.modules.titles[name]; | ||||
| 	if(!moduleInfo) { | ||||
| 		$tw.utils.error("Cannot find module named '" + moduleName + "' required by module '" + moduleRoot + "', resolved to " + name); | ||||
| 	} | ||||
| 	if(!moduleInfo.exports) { | ||||
| 		if(typeof moduleInfo.definition === "string") { // String | ||||
| 			moduleInfo.definition = window["eval"]("(function(module,exports,require) {" + moduleInfo.definition + "})"); | ||||
| 			moduleInfo.exports = {}; | ||||
| 			moduleInfo.definition(moduleInfo,moduleInfo.exports,require); | ||||
| 		} else if(typeof moduleInfo.definition === "function") { // Function | ||||
| 			moduleInfo.exports = {}; | ||||
| 			moduleInfo.definition(moduleInfo,moduleInfo.exports,require); | ||||
| 		} else { // Object | ||||
| 			moduleInfo.exports = moduleInfo.definition; | ||||
| 		} | ||||
| 	} | ||||
| 	return moduleInfo.exports; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Register a deserializer that can extract tiddlers from the DOM | ||||
| */ | ||||
| @@ -879,51 +943,6 @@ $tw.boot.decryptEncryptedTiddlers = function(callback) { | ||||
| 	callback(); | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Execute the module named 'moduleName'. The name can optionally be relative to the module named 'moduleRoot' | ||||
| */ | ||||
| $tw.modules.execute = function(moduleName,moduleRoot) { | ||||
| 	var name = moduleRoot ? $tw.utils.resolvePath(moduleName,moduleRoot) : moduleName, | ||||
| 		moduleInfo = $tw.modules.titles[name], | ||||
| 		tiddler = $tw.wiki.getTiddler(name), | ||||
| 		sandbox = { | ||||
| 			module: moduleInfo, | ||||
| 			exports: {}, | ||||
| 			console: console, | ||||
| 			process: process, | ||||
| 			setInterval: setInterval, | ||||
| 			clearInterval: clearInterval, | ||||
| 			setTimeout: setTimeout, | ||||
| 			clearTimeout: clearTimeout, | ||||
| 			$tw: $tw, | ||||
| 			require: function(title) { | ||||
| 				return $tw.modules.execute(title,name); | ||||
| 			} | ||||
| 		}; | ||||
| 	if(!moduleInfo) { | ||||
| 		// If we don't have a module with that name, let node.js try to find it | ||||
| 		return require(moduleName); | ||||
| 	} | ||||
| 	// Execute the module if we haven't already done so | ||||
| 	if(!moduleInfo.exports) { | ||||
| 		try { | ||||
| 			// Check the type of the definition | ||||
| 			if(typeof moduleInfo.definition === "string") { // String | ||||
| 				vm.runInNewContext(moduleInfo.definition,sandbox,tiddler.fields.title); | ||||
| 				moduleInfo.exports = sandbox.exports; | ||||
| 			} else if(typeof moduleInfo.definition === "function") { // Function | ||||
| 				moduleInfo.exports = moduleInfo.definition(moduleInfo,sandbox.require,moduleInfo.exports); | ||||
| 			} else { // Object | ||||
| 				moduleInfo.exports = moduleInfo.definition; | ||||
| 			} | ||||
| 		} catch(e) { | ||||
| 			$tw.utils.error("Error executing boot module " + name + ":\n" + e); | ||||
| 		} | ||||
| 	} | ||||
| 	// Return the exports of the module | ||||
| 	return moduleInfo.exports; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| Load the tiddlers contained in a particular file (and optionally extract fields from the accompanying .meta file) returned as {filepath:,type:,tiddlers:[],hasMetaFile:} | ||||
| */ | ||||
| @@ -963,6 +982,9 @@ $tw.loadTiddlersFromPath = function(filepath,excludeRegExp) { | ||||
| 					var typeInfo = $tw.config.contentTypeInfo[tidInfo.fields.type || "text/plain"], | ||||
| 						pathname = path.resolve(filepath,tidInfo.file), | ||||
| 						text = fs.readFileSync(pathname,typeInfo ? typeInfo.encoding : "utf8"); | ||||
| 					if(tidInfo.prefix) { | ||||
| 						text = tidInfo.prefix + text; | ||||
| 					} | ||||
| 					tidInfo.fields.text = text; | ||||
| 					tiddlers.push({tiddlers: [tidInfo.fields]}); | ||||
| 				}); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jeremy Ruston
					Jeremy Ruston