<commit_before>/**
 * @fileOverview Loader module for restartless addons
 * @author       YUKI "Piro" Hiroshi
 * @contributor  Infocatcher
 * @version      16
 *
 * @license
 *   The MIT License, Copyright (c) 2010-2015 YUKI "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

function toPropertyDescriptors(aProperties) {
	var descriptors = {};
	Object.keys(aProperties).forEach(function(aProperty) {
		var description = Object.getOwnPropertyDescriptor(aProperties, aProperty);
		descriptors[aProperty] = description;
	});
	return descriptors;
}

function inherit(aParent, aExtraProperties) {
	var global;
	if (Components.utils.getGlobalForObject)
		global = Components.utils.getGlobalForObject(aParent);
	else
		global = aParent.valueOf.call();
	global = global || this;

	var ObjectClass = global.Object || Object;
	if (aExtraProperties)
		return ObjectClass.create(aParent, toPropertyDescriptors(aExtraProperties));
	else
		return ObjectClass.create(aParent);
}

// import base64 utilities from the js code module namespace
try {
	var { atob, btoa } = Components.utils.import('resource://gre/modules/Services.jsm', {});
} catch(e) {
	Components.utils.reportError(new Error('failed to load Services.jsm'));
}
try {
	var { console } = Components.utils.import('resource://gre/modules/devtools/Console.jsm', {});
} catch(e) {
	Components.utils.reportError(new Error('failed to load Console.jsm'));
}
var _namespacePrototype = {
		Cc : Components.classes,
		Ci : Components.interfaces,
		Cu : Components.utils,
		Cr : Components.results,
		console : this.console,
		btoa    : function(aInput) {
			return btoa(aInput);
		},
		atob    : function(aInput) {
			return atob(aInput);
		},
		inherit : function(aParent, aExtraProperties) {
			return inherit(aParent, aExtraProperties);
		},
	};
var _namespaces;

/**
 * This functiom loads specified script into a unique namespace for the URL.
 * Namespaces for loaded scripts have a wrapped version of this function.
 * Both this and wrapped work like as Components.utils.import().
 * Due to the reserved symbol "import", we have to use another name "load"
 * instead it.
 *
 * @param {String} aScriptURL
 *   URL of a script. Wrapped version of load() can handle related path.
 *   Related path will be resolved based on the location of the caller script.
 * @param {Object=} aExportTargetForImport
 *   EXPORTED_SYMBOLS in the loaded script will be exported to the object.
 *   If no object is specified, symbols will be exported to the global object
 *   of the caller.
 * @param {Object=} aExportTargetForRequire
 *   Properties of "exports" in the loaded script will be exported to the object.
 *
 * @returns {Object}
 *   The global object for the loaded script.
 */
function load(aURISpec, aExportTargetForImport, aExportTargetForRequire, aRoot)
{
	if (!_namespaces)
		_namespaces = {};
	var ns;
	if (aURISpec in _namespaces) {
		ns = _namespaces[aURISpec];
		_exportForImport(ns, aExportTargetForImport);
		_exportForRequire(ns, aExportTargetForRequire);
		return ns;
	}
	ns = _createNamespace(aURISpec, aRoot || aURISpec);
	try {
		Components.classes['@mozilla.org/moz/jssubscript-loader;1']
			.getService(Components.interfaces.mozIJSSubScriptLoader)
			.loadSubScript(aURISpec, ns);
	}
	catch(e) {
		let message = 'Loader::load('+aURISpec+') failed!\n'+e+'\n';
		dump(message);
		Components.utils.reportError(message + e.stack);
		throw e;
	}
	_exportForImport(ns, aExportTargetForImport);
	_exportForRequire(ns, aExportTargetForRequire);
	return _namespaces[aURISpec] = ns;
}

// JavaScript code module style
function _exportForImport(aSource, aTarget)
{
	if (
		!aTarget ||
		!('EXPORTED_SYMBOLS' in aSource) ||
		!aSource.EXPORTED_SYMBOLS ||
		!aSource.EXPORTED_SYMBOLS.forEach
		)
		return;
	for each (var symbol in aSource.EXPORTED_SYMBOLS)
	{
		aTarget[symbol] = aSource[symbol];
	}
}

// CommonJS style
function _exportForRequire(aSource, aTarget)
{
	if (
		!aTarget ||
		!('exports' in aSource) ||
		!aSource.exports ||
		typeof aSource.exports != 'object'
		)
		return;
	for (var symbol in aSource.exports)
	{
		aTarget[symbol] = aSource.exports[symbol];
	}
}

var IOService = Components.classes['@mozilla.org/network/io-service;1']
					.getService(Components.interfaces.nsIIOService);
var FileHandler = IOService.getProtocolHandler('file')
					.QueryInterface(Components.interfaces.nsIFileProtocolHandler);

/**
 * Checks existence of the file specified by the given relative path and the base URI.
 *
 * @param {String} aPath
 *   A relative path to a file or directory, from the aBaseURI.
 * @param {String} aBaseURI
 *   An absolute URI (with scheme) for relative paths.
 *
 * @returns {String}
 *   If the file (or directory) exists, returns the absolute URI. Otherwise null.
 */
function exists(aPath, aBaseURI)
{
	if (/^\w+:/.test(aPath)) {
		let leafName = aPath.match(/([^\/]+)$/);
		leafName = leafName ? leafName[1] : '' ;
		aBaseURI = aPath.replace(/(?:[^\/]+)$/, '');
		aPath = leafName;
	}
	var baseURI = aBaseURI.indexOf('file:') == 0 ?
					IOService.newFileURI(FileHandler.getFileFromURLSpec(aBaseURI)) :
					IOService.newURI(aBaseURI, null, null);
	if (aBaseURI.indexOf('jar:') == 0) {
		baseURI = baseURI.QueryInterface(Components.interfaces.nsIJARURI);
		var reader = Components.classes['@mozilla.org/libjar/zip-reader;1']
						.createInstance(Components.interfaces.nsIZipReader);
		reader.open(baseURI.JARFile.QueryInterface(Components.interfaces.nsIFileURL).file);
		try {
			let baseEntry = baseURI.JAREntry.replace(/[^\/]+$/, '');
			let entries = reader.findEntries(baseEntry + aPath + '$');
			let found = entries.hasMore();
			return found ? baseURI.resolve(aPath) : null ;
		}
		finally {
			reader.close();
		}
	}
	else {
		let resolved = baseURI.resolve(aPath);
		return FileHandler.getFileFromURLSpec(resolved).exists() ? resolved : null ;
	}
}

function _readFrom(aURISpec, aEncoding)
{
	const Cc = Components.classes;
	const Ci = Components.interfaces;

	var uri = aURISpec.indexOf('file:') == 0 ?
			IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
			IOService.newURI(aURISpec, null, null) ;
	var channel = IOService.newChannelFromURI(uri.QueryInterface(Ci.nsIURI));
	var stream = channel.open();

	var fileContents = null;
	try {
		if (aEncoding) {
			var converterStream = Cc['@mozilla.org/intl/converter-input-stream;1']
					.createInstance(Ci.nsIConverterInputStream);
			var buffer = stream.available();
			converterStream.init(stream, aEncoding, buffer,
				converterStream.DEFAULT_REPLACEMENT_CHARACTER);
			var out = { value : null };
			converterStream.readString(stream.available(), out);
			converterStream.close();
			fileContents = out.value;
		}
		else {
			var scriptableStream = Cc['@mozilla.org/scriptableinputstream;1']
					.createInstance(Ci.nsIScriptableInputStream);
			scriptableStream.init(stream);
			fileContents = scriptableStream.read(scriptableStream.available());
			scriptableStream.close();
		}
	}
	finally {
		stream.close();
	}
	return fileContents;
}

function _createNamespace(aURISpec, aRoot)
{
	var baseURI = aURISpec.indexOf('file:') == 0 ?
					IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
					IOService.newURI(aURISpec, null, null);
	var rootURI = typeof aRoot == 'string' ?
					(aRoot.indexOf('file:') == 0 ?
						IOService.newFileURI(FileHandler.getFileFromURLSpec(aRoot)) :
						IOService.newURI(aRoot, null, null)
					) :
					aRoot ;
	var ns = inherit(_namespacePrototype, {
			location : _createFakeLocation(baseURI),
			exists : function(aPath, aBase) {
				return exists(aPath, aBase || baseURI.spec);
			},
			exist : function(aPath, aBase) { // alias
				return exists(aPath, aBase || baseURI.spec);
			},
			/** JavaScript code module style */
			load : function(aURISpec, aExportTarget) {
				if (!/\.jsm?$/.test(aURISpec)) {
					if (exists(aURISpec+'.js', baseURI.spec))
						aURISpec += '.js'
					else if (exists(aURISpec+'.jsm', baseURI.spec))
						aURISpec += '.jsm'
				}
				var resolved = baseURI.resolve(aURISpec);
				if (resolved == aURISpec)
					throw new Error('Recursive load!');
				return load(resolved, aExportTarget || ns, aExportTarget, rootURI);
			},
			'import' : function() { // alias
				return this.load.apply(this, arguments);
			},
			/**
			 * CommonJS style
			 * @url http://www.commonjs.org/specs/
			 */
			require : function(aURISpec) {
				if (!/\.jsm?$/.test(aURISpec)) {
					if (exists(aURISpec+'.js', baseURI.spec))
						aURISpec += '.js'
					else if (exists(aURISpec+'.jsm', baseURI.spec))
						aURISpec += '.jsm'
				}
				var resolved = (aURISpec.charAt(0) == '.' ? rootURI : baseURI ).resolve(aURISpec);
				if (resolved == aURISpec)
					throw new Error('Recursive load!');
				var exported = {};
				load(resolved, exported, exported, rootURI);
				return exported;
			},
			/* utility to resolve relative path from the file */
			resolve : function(aURISpec, aBaseURI) {
				var base = !aBaseURI ?
								baseURI :
							aBaseURI.indexOf('file:') == 0 ?
								IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
								IOService.newURI(aURISpec, null, null) ;
				return base.resolve(aURISpec);
			},
			/* utility to read contents of a text file */
			read : function(aURISpec, aEncoding, aBaseURI) {
				return _readFrom(this.resolve(aURISpec, aBaseURI), aEncoding);
			},
			exports : {}
		});
	return ns;
}

function _createFakeLocation(aURI)
{
	aURI = aURI.QueryInterface(Components.interfaces.nsIURL)
					.QueryInterface(Components.interfaces.nsIURI);
	return {
		href     : aURI.spec,
		search   : aURI.query ? '?'+aURI.query : '' ,
		hash     : aURI.ref ? '#'+aURI.ref : '' ,
		host     : aURI.scheme == 'jar' ? '' : aURI.hostPort,
		hostname : aURI.scheme == 'jar' ? '' : aURI.host,
		port     : aURI.scheme == 'jar' ? -1 : aURI.port,
		pathname : aURI.path,
		protocol : aURI.scheme+':',
		reload   : function() {},
		replace  : function() {},
		toString : function() {
			return this.href;
		}
	};
}

function _callHandler(aHandler, aReason)
{
	var handlers = [];
	for (var i in _namespaces)
	{
		if (_namespaces[i][aHandler] &&
			typeof _namespaces[i][aHandler] == 'function')
			handlers.push({
				key       : i,
				namespace : _namespaces[i],
				handler   : _namespaces[i][aHandler]
			});
	}

	var { Promise } = Components.utils.import('resource://gre/modules/Promise.jsm', {});
	return new Promise(function(aResolve, aReject) {
		var processHandler = function() {
			var handler = handlers.shift();
			if (!handler)
				return aResolve();

			try {
				var result = handler.handler.call(handler.namespace, aReason);
			}
			catch(e) {
				let message = i+'('+aHandler+', '+aReason+')\n'+e+'\n';
				dump(message);
				Components.utils.reportError(message + e.stack);
			}

			if (result && typeof result.then == 'function') {
				result.then(processHandler);
			}
			else {
				processHandler();
			}
		};
		processHandler();
	});
}

function registerResource(aName, aRoot)
{
	IOService.getProtocolHandler('resource')
		.QueryInterface(Components.interfaces.nsIResProtocolHandler)
		.setSubstitution(aName, aRoot);
}

function unregisterResource(aName)
{
	IOService.getProtocolHandler('resource')
		.QueryInterface(Components.interfaces.nsIResProtocolHandler)
		.setSubstitution(aName, null);
}

/** Handler for "install" of the bootstrap.js */
function install(aReason)
{
	_callHandler('install', aReason);
}

/** Handler for "uninstall" of the bootstrap.js */
function uninstall(aReason)
{
	_callHandler('uninstall', aReason);
}

/** Handler for "shutdown" of the bootstrap.js */
function shutdown(aReason)
{
	_callHandler('shutdown', aReason)
		.then(function() {
			for each (let ns in _namespaces)
			{
				for (let i in ns.exports)
				{
					if (ns.exports.hasOwnProperty(i))
						delete ns.exports[i];
				}
			}
			_namespaces = void(0);
			_namespacePrototype = void(0);

			IOService = void(0);
			FileHandler = void(0);

			load = void(0);
			_exportSymbols = void(0);
			exists = void(0);
			_createNamespace = void(0);
			_callHandler = void(0);
			registerResource = void(0);
			unregisterResource = void(0);
			install = void(0);
			uninstall = void(0);
			shutdown = void(0);
		});
}
<commit_msg>Add "Promise" as a default utility<commit_after>/**
 * @fileOverview Loader module for restartless addons
 * @author       YUKI "Piro" Hiroshi
 * @contributor  Infocatcher
 * @version      16
 *
 * @license
 *   The MIT License, Copyright (c) 2010-2015 YUKI "Piro" Hiroshi.
 *   https://github.com/piroor/restartless/blob/master/license.txt
 * @url http://github.com/piroor/restartless
 */

function toPropertyDescriptors(aProperties) {
	var descriptors = {};
	Object.keys(aProperties).forEach(function(aProperty) {
		var description = Object.getOwnPropertyDescriptor(aProperties, aProperty);
		descriptors[aProperty] = description;
	});
	return descriptors;
}

function inherit(aParent, aExtraProperties) {
	var global;
	if (Components.utils.getGlobalForObject)
		global = Components.utils.getGlobalForObject(aParent);
	else
		global = aParent.valueOf.call();
	global = global || this;

	var ObjectClass = global.Object || Object;
	if (aExtraProperties)
		return ObjectClass.create(aParent, toPropertyDescriptors(aExtraProperties));
	else
		return ObjectClass.create(aParent);
}

// import base64 utilities from the js code module namespace
try {
	var { atob, btoa } = Components.utils.import('resource://gre/modules/Services.jsm', {});
} catch(e) {
	Components.utils.reportError(new Error('failed to load Services.jsm'));
}
try {
	var { console } = Components.utils.import('resource://gre/modules/devtools/Console.jsm', {});
} catch(e) {
	Components.utils.reportError(new Error('failed to load Console.jsm'));
}

var { Promise } = Components.utils.import('resource://gre/modules/Promise.jsm', {});

var _namespacePrototype = {
		Cc : Components.classes,
		Ci : Components.interfaces,
		Cu : Components.utils,
		Cr : Components.results,
		console : this.console,
		btoa    : function(aInput) {
			return btoa(aInput);
		},
		atob    : function(aInput) {
			return atob(aInput);
		},
		inherit : function(aParent, aExtraProperties) {
			return inherit(aParent, aExtraProperties);
		},
		Promise : Promise,
	};
var _namespaces;

/**
 * This functiom loads specified script into a unique namespace for the URL.
 * Namespaces for loaded scripts have a wrapped version of this function.
 * Both this and wrapped work like as Components.utils.import().
 * Due to the reserved symbol "import", we have to use another name "load"
 * instead it.
 *
 * @param {String} aScriptURL
 *   URL of a script. Wrapped version of load() can handle related path.
 *   Related path will be resolved based on the location of the caller script.
 * @param {Object=} aExportTargetForImport
 *   EXPORTED_SYMBOLS in the loaded script will be exported to the object.
 *   If no object is specified, symbols will be exported to the global object
 *   of the caller.
 * @param {Object=} aExportTargetForRequire
 *   Properties of "exports" in the loaded script will be exported to the object.
 *
 * @returns {Object}
 *   The global object for the loaded script.
 */
function load(aURISpec, aExportTargetForImport, aExportTargetForRequire, aRoot)
{
	if (!_namespaces)
		_namespaces = {};
	var ns;
	if (aURISpec in _namespaces) {
		ns = _namespaces[aURISpec];
		_exportForImport(ns, aExportTargetForImport);
		_exportForRequire(ns, aExportTargetForRequire);
		return ns;
	}
	ns = _createNamespace(aURISpec, aRoot || aURISpec);
	try {
		Components.classes['@mozilla.org/moz/jssubscript-loader;1']
			.getService(Components.interfaces.mozIJSSubScriptLoader)
			.loadSubScript(aURISpec, ns);
	}
	catch(e) {
		let message = 'Loader::load('+aURISpec+') failed!\n'+e+'\n';
		dump(message);
		Components.utils.reportError(message + e.stack);
		throw e;
	}
	_exportForImport(ns, aExportTargetForImport);
	_exportForRequire(ns, aExportTargetForRequire);
	return _namespaces[aURISpec] = ns;
}

// JavaScript code module style
function _exportForImport(aSource, aTarget)
{
	if (
		!aTarget ||
		!('EXPORTED_SYMBOLS' in aSource) ||
		!aSource.EXPORTED_SYMBOLS ||
		!aSource.EXPORTED_SYMBOLS.forEach
		)
		return;
	for each (var symbol in aSource.EXPORTED_SYMBOLS)
	{
		aTarget[symbol] = aSource[symbol];
	}
}

// CommonJS style
function _exportForRequire(aSource, aTarget)
{
	if (
		!aTarget ||
		!('exports' in aSource) ||
		!aSource.exports ||
		typeof aSource.exports != 'object'
		)
		return;
	for (var symbol in aSource.exports)
	{
		aTarget[symbol] = aSource.exports[symbol];
	}
}

var IOService = Components.classes['@mozilla.org/network/io-service;1']
					.getService(Components.interfaces.nsIIOService);
var FileHandler = IOService.getProtocolHandler('file')
					.QueryInterface(Components.interfaces.nsIFileProtocolHandler);

/**
 * Checks existence of the file specified by the given relative path and the base URI.
 *
 * @param {String} aPath
 *   A relative path to a file or directory, from the aBaseURI.
 * @param {String} aBaseURI
 *   An absolute URI (with scheme) for relative paths.
 *
 * @returns {String}
 *   If the file (or directory) exists, returns the absolute URI. Otherwise null.
 */
function exists(aPath, aBaseURI)
{
	if (/^\w+:/.test(aPath)) {
		let leafName = aPath.match(/([^\/]+)$/);
		leafName = leafName ? leafName[1] : '' ;
		aBaseURI = aPath.replace(/(?:[^\/]+)$/, '');
		aPath = leafName;
	}
	var baseURI = aBaseURI.indexOf('file:') == 0 ?
					IOService.newFileURI(FileHandler.getFileFromURLSpec(aBaseURI)) :
					IOService.newURI(aBaseURI, null, null);
	if (aBaseURI.indexOf('jar:') == 0) {
		baseURI = baseURI.QueryInterface(Components.interfaces.nsIJARURI);
		var reader = Components.classes['@mozilla.org/libjar/zip-reader;1']
						.createInstance(Components.interfaces.nsIZipReader);
		reader.open(baseURI.JARFile.QueryInterface(Components.interfaces.nsIFileURL).file);
		try {
			let baseEntry = baseURI.JAREntry.replace(/[^\/]+$/, '');
			let entries = reader.findEntries(baseEntry + aPath + '$');
			let found = entries.hasMore();
			return found ? baseURI.resolve(aPath) : null ;
		}
		finally {
			reader.close();
		}
	}
	else {
		let resolved = baseURI.resolve(aPath);
		return FileHandler.getFileFromURLSpec(resolved).exists() ? resolved : null ;
	}
}

function _readFrom(aURISpec, aEncoding)
{
	const Cc = Components.classes;
	const Ci = Components.interfaces;

	var uri = aURISpec.indexOf('file:') == 0 ?
			IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
			IOService.newURI(aURISpec, null, null) ;
	var channel = IOService.newChannelFromURI(uri.QueryInterface(Ci.nsIURI));
	var stream = channel.open();

	var fileContents = null;
	try {
		if (aEncoding) {
			var converterStream = Cc['@mozilla.org/intl/converter-input-stream;1']
					.createInstance(Ci.nsIConverterInputStream);
			var buffer = stream.available();
			converterStream.init(stream, aEncoding, buffer,
				converterStream.DEFAULT_REPLACEMENT_CHARACTER);
			var out = { value : null };
			converterStream.readString(stream.available(), out);
			converterStream.close();
			fileContents = out.value;
		}
		else {
			var scriptableStream = Cc['@mozilla.org/scriptableinputstream;1']
					.createInstance(Ci.nsIScriptableInputStream);
			scriptableStream.init(stream);
			fileContents = scriptableStream.read(scriptableStream.available());
			scriptableStream.close();
		}
	}
	finally {
		stream.close();
	}
	return fileContents;
}

function _createNamespace(aURISpec, aRoot)
{
	var baseURI = aURISpec.indexOf('file:') == 0 ?
					IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
					IOService.newURI(aURISpec, null, null);
	var rootURI = typeof aRoot == 'string' ?
					(aRoot.indexOf('file:') == 0 ?
						IOService.newFileURI(FileHandler.getFileFromURLSpec(aRoot)) :
						IOService.newURI(aRoot, null, null)
					) :
					aRoot ;
	var ns = inherit(_namespacePrototype, {
			location : _createFakeLocation(baseURI),
			exists : function(aPath, aBase) {
				return exists(aPath, aBase || baseURI.spec);
			},
			exist : function(aPath, aBase) { // alias
				return exists(aPath, aBase || baseURI.spec);
			},
			/** JavaScript code module style */
			load : function(aURISpec, aExportTarget) {
				if (!/\.jsm?$/.test(aURISpec)) {
					if (exists(aURISpec+'.js', baseURI.spec))
						aURISpec += '.js'
					else if (exists(aURISpec+'.jsm', baseURI.spec))
						aURISpec += '.jsm'
				}
				var resolved = baseURI.resolve(aURISpec);
				if (resolved == aURISpec)
					throw new Error('Recursive load!');
				return load(resolved, aExportTarget || ns, aExportTarget, rootURI);
			},
			'import' : function() { // alias
				return this.load.apply(this, arguments);
			},
			/**
			 * CommonJS style
			 * @url http://www.commonjs.org/specs/
			 */
			require : function(aURISpec) {
				if (!/\.jsm?$/.test(aURISpec)) {
					if (exists(aURISpec+'.js', baseURI.spec))
						aURISpec += '.js'
					else if (exists(aURISpec+'.jsm', baseURI.spec))
						aURISpec += '.jsm'
				}
				var resolved = (aURISpec.charAt(0) == '.' ? rootURI : baseURI ).resolve(aURISpec);
				if (resolved == aURISpec)
					throw new Error('Recursive load!');
				var exported = {};
				load(resolved, exported, exported, rootURI);
				return exported;
			},
			/* utility to resolve relative path from the file */
			resolve : function(aURISpec, aBaseURI) {
				var base = !aBaseURI ?
								baseURI :
							aBaseURI.indexOf('file:') == 0 ?
								IOService.newFileURI(FileHandler.getFileFromURLSpec(aURISpec)) :
								IOService.newURI(aURISpec, null, null) ;
				return base.resolve(aURISpec);
			},
			/* utility to read contents of a text file */
			read : function(aURISpec, aEncoding, aBaseURI) {
				return _readFrom(this.resolve(aURISpec, aBaseURI), aEncoding);
			},
			exports : {}
		});
	return ns;
}

function _createFakeLocation(aURI)
{
	aURI = aURI.QueryInterface(Components.interfaces.nsIURL)
					.QueryInterface(Components.interfaces.nsIURI);
	return {
		href     : aURI.spec,
		search   : aURI.query ? '?'+aURI.query : '' ,
		hash     : aURI.ref ? '#'+aURI.ref : '' ,
		host     : aURI.scheme == 'jar' ? '' : aURI.hostPort,
		hostname : aURI.scheme == 'jar' ? '' : aURI.host,
		port     : aURI.scheme == 'jar' ? -1 : aURI.port,
		pathname : aURI.path,
		protocol : aURI.scheme+':',
		reload   : function() {},
		replace  : function() {},
		toString : function() {
			return this.href;
		}
	};
}

function _callHandler(aHandler, aReason)
{
	var handlers = [];
	for (var i in _namespaces)
	{
		if (_namespaces[i][aHandler] &&
			typeof _namespaces[i][aHandler] == 'function')
			handlers.push({
				key       : i,
				namespace : _namespaces[i],
				handler   : _namespaces[i][aHandler]
			});
	}

	return new Promise(function(aResolve, aReject) {
		var processHandler = function() {
			var handler = handlers.shift();
			if (!handler)
				return aResolve();

			try {
				var result = handler.handler.call(handler.namespace, aReason);
			}
			catch(e) {
				let message = i+'('+aHandler+', '+aReason+')\n'+e+'\n';
				dump(message);
				Components.utils.reportError(message + e.stack);
			}

			if (result && typeof result.then == 'function') {
				result.then(processHandler);
			}
			else {
				processHandler();
			}
		};
		processHandler();
	});
}

function registerResource(aName, aRoot)
{
	IOService.getProtocolHandler('resource')
		.QueryInterface(Components.interfaces.nsIResProtocolHandler)
		.setSubstitution(aName, aRoot);
}

function unregisterResource(aName)
{
	IOService.getProtocolHandler('resource')
		.QueryInterface(Components.interfaces.nsIResProtocolHandler)
		.setSubstitution(aName, null);
}

/** Handler for "install" of the bootstrap.js */
function install(aReason)
{
	_callHandler('install', aReason);
}

/** Handler for "uninstall" of the bootstrap.js */
function uninstall(aReason)
{
	_callHandler('uninstall', aReason);
}

/** Handler for "shutdown" of the bootstrap.js */
function shutdown(aReason)
{
	_callHandler('shutdown', aReason)
		.then(function() {
			for each (let ns in _namespaces)
			{
				for (let i in ns.exports)
				{
					if (ns.exports.hasOwnProperty(i))
						delete ns.exports[i];
				}
			}
			_namespaces = void(0);
			_namespacePrototype = void(0);

			IOService = void(0);
			FileHandler = void(0);
			Promise = void(0);

			load = void(0);
			_exportSymbols = void(0);
			exists = void(0);
			_createNamespace = void(0);
			_callHandler = void(0);
			registerResource = void(0);
			unregisterResource = void(0);
			install = void(0);
			uninstall = void(0);
			shutdown = void(0);
		});
}
<|endoftext|>


<commit_before>// Code goes here
var
  theContainer, cubeCamera, mirrorSphereCamera, controls, mirrorSphereCameras = [], theColor = 0xFC6A45, renderer, theSphere, theLight, theScene, theCamera, theGeometry, theMaterial, IS_WIRE_FRAME, ANIMATE;

function onStart() {
  'use strict';

  // boilerplate
  theContainer = document.getElementById("theContainer");
  renderer = new THREE.WebGLRenderer();
  renderer.setClearColor(0xaabbff);
  renderer.setSize(640, 480);
  theScene = new THREE.Scene();
  theCamera = new THREE.PerspectiveCamera(50, 640 / 480, 0.1, 4000);
  theCamera.position.set(0, 0, 40);
  theContainer.appendChild(renderer.domElement);

  var mousePositionText = document.getElementById('mousePosition');
  var canvasPositionText = document.getElementById('canvasPosition');
  var selectionName = document.getElementById('currentSelection');
  var mouseVector = new THREE.Vector3();
  var rayCaster = new THREE.Raycaster();

  var loader = new THREE.ColladaLoader();

  loader.options.convertUpAxis = true;

  loader.load('models/wood_man.dae', function (dae) {
    var scene = dae.scene;
    scene.scale.set(10, 10, 10);

    scene.traverse(function (child) {
      if (child instanceof THREE.Mesh) {
        //console.log(child.id+' -> ', child.material.name);
        intersectables.push(child);
      }
    });

    theScene.add(scene);

  });

  controls = new THREE.OrbitControls(theCamera, renderer.domElement);

  var hightlightMaterial = new THREE.MeshPhongMaterial({
    name       : 'highlighted',
    color      : 0x00ff00,
    opacity    : 0.6,
    transparent: true
  });

  var selectedMaterial = new THREE.MeshPhongMaterial({
    name     : 'selected',
    color    : 0x0000ff,
    wireframe: true
  });

  var theMaterials = {};

  function normalizeCoordinates(event) {
    var offset = $(theContainer).offset();

    // canvas element local
    var localX = event.pageX - offset.left;
    var localY = event.pageY - offset.top;

    // webgl context
    var canvasX = (localX / renderer.domElement.width) * 2 - 1;
    var canvasY = (1 - (localY / renderer.domElement.height)) * 2 - 1;

    return {
      canvas: {
        x: canvasX,
        y: canvasY
      },
      local : {
        x: localX,
        y: localY
      }
    }
  }

  var lastMouseDown = new THREE.Vector2();
  var isMouseDown = false;
  var lastIntersected;
  var intersectables = [];
  var currentIntersection;

  function onMouseDown(event) {
    event.preventDefault();

    isMouseDown = true;

    var normalized = normalizeCoordinates(event);
    lastMouseDown.set(normalized.canvas.x, normalized.canvas.y);
  }

  function onMouseUp(event) {
    event.preventDefault();

    isMouseDown = false;

    var normalized = normalizeCoordinates(event);

    console.log(Math.abs(lastMouseDown.x - normalized.canvas.x) + ' > 0.2 || ' + Math.abs(lastMouseDown.y - normalized.canvas.y) + '> 0.2');
    if (Math.abs(lastMouseDown.x - normalized.canvas.x) > 0.2 || Math.abs(lastMouseDown.y - normalized.canvas.y) > 0.2)
      return;

    if (currentIntersection !== undefined) {
      if (currentIntersection.material.name === selectedMaterial.name) {
        currentIntersection.material = theMaterial;
      } else {
        currentIntersection.material = selectedMaterial;
      }
    }

  }

  function onMouseMove(event) {
    event.preventDefault();

    var normalized = normalizeCoordinates(event);

    $(mousePositionText).text(normalized.local.x + ', ' + normalized.local.y);
    $(canvasPositionText).text((Math.round(normalized.canvas.x * 100) / 100) + ',' + (Math.round(normalized.canvas.y * 100) / 100));

    if (isMouseDown)
      return;

    mouseVector.set(normalized.canvas.x, normalized.canvas.y, 1);

    rayCaster.setFromCamera(mouseVector, theCamera);

    var intersections = rayCaster.intersectObjects(intersectables);

    if (intersections.length > 0) {
      currentIntersection = intersections[0].object;
      console.log(currentIntersection.id + ' -> ', currentIntersection.material.name);
      if (currentIntersection.material.name !== selectedMaterial.name && currentIntersection.material.name !== hightlightMaterial.name) {
        theMaterials[currentIntersection.id] = currentIntersection.material.clone();
        currentIntersection.material = hightlightMaterial;
        console.log(theMaterials[currentIntersection.id].name);
      }
      $(selectionName).text(currentIntersection.id);
    } else {
      $(selectionName).text('none');
      currentIntersection = undefined;
    }

    if (lastIntersected !== undefined && lastIntersected !== currentIntersection) {
      console.log(lastIntersected.id + ' -> ' + lastIntersected.material.name + ' vs '+selectedMaterial.name+' last id '+theMaterials[lastIntersected.id].name);
      if (lastIntersected.material.name !== selectedMaterial.name) {
        lastIntersected.material = theMaterials[lastIntersected.id].clone();
      }
    }

    lastIntersected = currentIntersection;

  }

  // two lights
  var theLight1 = new THREE.DirectionalLight(0xffdddd, 1);
  theLight1.position.set(10, 10, 20);
  theScene.add(theLight1);

  var theLight2 = new THREE.DirectionalLight(0xddddff, 0.7);
  theLight2.position.set(10, 10, -20);
  theScene.add(theLight2);

  $(renderer.domElement).on('touchmove', onMouseMove);
  $(renderer.domElement).on('mousemove', onMouseMove);
  $(renderer.domElement).on('mouseup', onMouseUp);
  $(renderer.domElement).on('mousedown', onMouseDown);

  requestAnimationFrame(animate);

  function animate() {
    renderer.render(theScene, theCamera);
    requestAnimationFrame(animate);
  }
}<commit_msg>bugifix on mouse up<commit_after>// Code goes here
var
    theContainer, cubeCamera, mirrorSphereCamera, controls, mirrorSphereCameras = [], theColor = 0xFC6A45, renderer, theSphere, theLight, theScene, theCamera, theGeometry, theMaterial, IS_WIRE_FRAME, ANIMATE;

var theMaterials = {};
var uniqueMaterials = {};

function onStart() {
    'use strict';

    // boilerplate
    theContainer = document.getElementById("theContainer");
    renderer = new THREE.WebGLRenderer();
    renderer.setClearColor(0xaabbff);
    renderer.setSize(640, 480);
    theScene = new THREE.Scene();
    theCamera = new THREE.PerspectiveCamera(50, 640 / 480, 0.1, 4000);
    theCamera.position.set(0, 0, 40);
    theContainer.appendChild(renderer.domElement);

    var mousePositionText = document.getElementById('mousePosition');
    var canvasPositionText = document.getElementById('canvasPosition');
    var selectionName = document.getElementById('currentSelection');
    var mouseVector = new THREE.Vector3();
    var rayCaster = new THREE.Raycaster();

    var loader = new THREE.ColladaLoader();

    loader.options.convertUpAxis = true;

    loader.load('models/wood_man.dae', function (dae) {
        var scene = dae.scene;
        scene.scale.set(10, 10, 10);

        scene.traverse(function (child) {
            if (child instanceof THREE.Mesh) {
                //console.log(child.id+' -> ', child.material.name);
                theMaterials[child.id] = child.material;
                uniqueMaterials[child.material.id] = child.material;
                intersectables.push(child);
            }
        });

        $.map(uniqueMaterials, function (mat) {
            var diffuse;

            switch (mat.name) {
                case 'acciaio' :
                    console.log('acciaio');
                    mat.setValues({});
                    break;
                case 'legno' :
                    console.log('legno ok');
                    diffuse = THREE.ImageUtils.loadTexture('./models/wood_diffuse.jpg');
                    mat.setValues({
                        color: 0xff9999,
                        map: diffuse
                    });
                    break;
                default:
                    console.error('missing implementation '+mat.name);
            }
        });

        theScene.add(scene);

    });

    controls = new THREE.OrbitControls(theCamera, renderer.domElement);

    var hightlightMaterial = new THREE.MeshPhongMaterial({
        name: 'highlighted',
        color: 0x00ff00,
        opacity: 0.6,
        transparent: true
    });

    var selectedMaterial = new THREE.MeshPhongMaterial({
        name: 'selected',
        color: 0x0000ff,
        wireframe: true
    });

    function normalizeCoordinates(event) {
        var offset = $(theContainer).offset();

        // canvas element local
        var localX = event.pageX - offset.left;
        var localY = event.pageY - offset.top;

        // webgl context
        var canvasX = (localX / renderer.domElement.width) * 2 - 1;
        var canvasY = (1 - (localY / renderer.domElement.height)) * 2 - 1;

        return {
            canvas: {
                x: canvasX,
                y: canvasY
            },
            local: {
                x: localX,
                y: localY
            }
        }
    }

    var lastMouseDown = new THREE.Vector2();
    var isMouseDown = false;
    var lastIntersected;
    var intersectables = [];
    var currentIntersection;

    function onMouseDown(event) {
        event.preventDefault();

        isMouseDown = true;

        var normalized = normalizeCoordinates(event);
        lastMouseDown.set(normalized.canvas.x, normalized.canvas.y);
    }

    function onMouseUp(event) {
        event.preventDefault();

        isMouseDown = false;

        var normalized = normalizeCoordinates(event);

        //console.log(Math.abs(lastMouseDown.x - normalized.canvas.x) + ' > 0.2 || ' + Math.abs(lastMouseDown.y - normalized.canvas.y) + '> 0.2');
        if (Math.abs(lastMouseDown.x - normalized.canvas.x) > 0.2 || Math.abs(lastMouseDown.y - normalized.canvas.y) > 0.2)
            return;

        if (currentIntersection !== undefined) {
            if (currentIntersection.material.name === selectedMaterial.name) {
                currentIntersection.material = theMaterials[lastIntersected.id];
            } else {
                currentIntersection.material = selectedMaterial;
            }
        }

    }

    function onMouseMove(event) {
        event.preventDefault();

        var normalized = normalizeCoordinates(event);

        $(mousePositionText).text(normalized.local.x + ', ' + normalized.local.y);
        $(canvasPositionText).text((Math.round(normalized.canvas.x * 100) / 100) + ',' + (Math.round(normalized.canvas.y * 100) / 100));

        if (isMouseDown)
            return;

        mouseVector.set(normalized.canvas.x, normalized.canvas.y, 1);

        rayCaster.setFromCamera(mouseVector, theCamera);

        var intersections = rayCaster.intersectObjects(intersectables);

        if (intersections.length > 0) {
            currentIntersection = intersections[0].object;
            console.log(currentIntersection.id + ' -> ', currentIntersection.material.name);
            if (currentIntersection.material.name !== selectedMaterial.name && currentIntersection.material.name !== hightlightMaterial.name) {
                //theMaterials[currentIntersection.id] = currentIntersection.material.clone();
                currentIntersection.material = hightlightMaterial;
                console.log(theMaterials[currentIntersection.id].name);
            }
            $(selectionName).text(currentIntersection.id);
        } else {
            $(selectionName).text('none');
            currentIntersection = undefined;
        }

        if (lastIntersected !== undefined && lastIntersected !== currentIntersection) {

            //console.log(lastIntersected.id + ' -> ' + lastIntersected.material.name + ' vs '+selectedMaterial.name+' last id '+theMaterials[lastIntersected.id].name);
            if (lastIntersected.material.name !== selectedMaterial.name) {
                lastIntersected.material = theMaterials[lastIntersected.id];
            }

        }

        lastIntersected = currentIntersection;

    }

    // two lights
    var theLight1 = new THREE.DirectionalLight(0xffdddd, 1);
    theLight1.position.set(10, 10, 20);
    theScene.add(theLight1);

    var theLight2 = new THREE.DirectionalLight(0xddddff, 0.7);
    theLight2.position.set(10, 10, -20);
    theScene.add(theLight2);

    $(renderer.domElement).on('touchmove', onMouseMove);
    $(renderer.domElement).on('mousemove', onMouseMove);
    $(renderer.domElement).on('mouseup', onMouseUp);
    $(renderer.domElement).on('mousedown', onMouseDown);

    requestAnimationFrame(animate);

    function animate() {
        renderer.render(theScene, theCamera);
        requestAnimationFrame(animate);
    }
}<|endoftext|>


<commit_before>/**
 * Loads a Wavefront .mtl file specifying materials
 *
 * @author angelxuanchang
 */

THREE.MTLLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

THREE.MTLLoader.prototype = {

	constructor: THREE.MTLLoader,

	/**
	 * Loads and parses a MTL asset from a URL.
	 *
	 * @param {String} url - URL to the MTL file.
	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
	 * @param {Function} [onProgress] - Callback for download progress.
	 * @param {Function} [onError] - Callback for download errors.
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to load.
	 */
	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		var loader = new THREE.FileLoader( this.manager );
		loader.setPath( this.path );
		loader.load( url, function ( text ) {

			onLoad( scope.parse( text ) );

		}, onProgress, onError );

	},

	/**
	 * Set base path for resolving references.
	 * If set this path will be prepended to each loaded and found reference.
	 *
	 * @see setTexturePath
	 * @param {String} path
	 * @return {THREE.MTLLoader}
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setPath: function ( path ) {

		this.path = path;
		return this;

	},

	/**
	 * Set base path for resolving texture references.
	 * If set this path will be prepended found texture reference.
	 * If not set and setPath is, it will be used as texture base path.
	 *
	 * @see setPath
	 * @param {String} path
	 * @return {THREE.MTLLoader}
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.setTexturePath( 'assets/textures/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setTexturePath: function ( path ) {

		this.texturePath = path;
		return this;

	},

	setBaseUrl: function ( path ) {

		console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );

		return this.setTexturePath( path );

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;
		return this;

	},

	setMaterialOptions: function ( value ) {

		this.materialOptions = value;
		return this;

	},

	/**
	 * Parses a MTL file.
	 *
	 * @param {String} text - Content of MTL file
	 * @return {THREE.MTLLoader.MaterialCreator}
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to parse.
	 */
	parse: function ( text ) {

		var lines = text.split( '\n' );
		var info = {};
		var delimiter_pattern = /\s+/;
		var materialsInfo = {};

		for ( var i = 0; i < lines.length; i ++ ) {

			var line = lines[ i ];
			line = line.trim();

			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {

				// Blank line or comment ignore
				continue;

			}

			var pos = line.indexOf( ' ' );

			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
			key = key.toLowerCase();

			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
			value = value.trim();

			if ( key === 'newmtl' ) {

				// New material

				info = { name: value };
				materialsInfo[ value ] = info;

			} else if ( info ) {

				if ( key === 'ka' || key === 'kd' || key === 'ks' ) {

					var ss = value.split( delimiter_pattern, 3 );
					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];

				} else {

					info[ key ] = value;

				}

			}

		}

		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
		materialCreator.setCrossOrigin( this.crossOrigin );
		materialCreator.setManager( this.manager );
		materialCreator.setMaterials( materialsInfo );
		return materialCreator;

	}

};

/**
 * Create a new THREE-MTLLoader.MaterialCreator
 * @param baseUrl - Url relative to which textures are loaded
 * @param options - Set of options on how to construct the materials
 *                  side: Which side to apply the material
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 *                  wrap: What type of wrapping to apply for textures
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 *                                Default: false, assumed to be already normalized
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 *                                  Default: false
 * @constructor
 */

THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {

	this.baseUrl = baseUrl || '';
	this.options = options;
	this.materialsInfo = {};
	this.materials = {};
	this.materialsArray = [];
	this.nameLookup = {};

	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;

};

THREE.MTLLoader.MaterialCreator.prototype = {

	constructor: THREE.MTLLoader.MaterialCreator,

	crossOrigin: 'anonymous',

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;
		return this;

	},

	setManager: function ( value ) {

		this.manager = value;

	},

	setMaterials: function ( materialsInfo ) {

		this.materialsInfo = this.convert( materialsInfo );
		this.materials = {};
		this.materialsArray = [];
		this.nameLookup = {};

	},

	convert: function ( materialsInfo ) {

		if ( ! this.options ) return materialsInfo;

		var converted = {};

		for ( var mn in materialsInfo ) {

			// Convert materials info into normalized form based on options

			var mat = materialsInfo[ mn ];

			var covmat = {};

			converted[ mn ] = covmat;

			for ( var prop in mat ) {

				var save = true;
				var value = mat[ prop ];
				var lprop = prop.toLowerCase();

				switch ( lprop ) {

					case 'kd':
					case 'ka':
					case 'ks':

						// Diffuse color (color under white light) using RGB values

						if ( this.options && this.options.normalizeRGB ) {

							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];

						}

						if ( this.options && this.options.ignoreZeroRGBs ) {

							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {

								// ignore

								save = false;

							}

						}

						break;

					default:

						break;

				}

				if ( save ) {

					covmat[ lprop ] = value;

				}

			}

		}

		return converted;

	},

	preload: function () {

		for ( var mn in this.materialsInfo ) {

			this.create( mn );

		}

	},

	getIndex: function ( materialName ) {

		return this.nameLookup[ materialName ];

	},

	getAsArray: function () {

		var index = 0;

		for ( var mn in this.materialsInfo ) {

			this.materialsArray[ index ] = this.create( mn );
			this.nameLookup[ mn ] = index;
			index ++;

		}

		return this.materialsArray;

	},

	create: function ( materialName ) {

		if ( this.materials[ materialName ] === undefined ) {

			this.createMaterial_( materialName );

		}

		return this.materials[ materialName ];

	},

	createMaterial_: function ( materialName ) {

		// Create material

		var scope = this;
		var mat = this.materialsInfo[ materialName ];
		var params = {

			name: materialName,
			side: this.side

		};

		function resolveURL( baseUrl, url ) {

			if ( typeof url !== 'string' || url === '' )
				return '';

			// Absolute URL
			if ( /^https?:\/\//i.test( url ) ) return url;

			return baseUrl + url;

		}

		function setMapForType( mapType, value ) {

			if ( params[ mapType ] ) return; // Keep the first encountered texture

			var texParams = scope.getTextureParams( value, params );
			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );

			map.repeat.copy( texParams.scale );
			map.offset.copy( texParams.offset );

			map.wrapS = scope.wrap;
			map.wrapT = scope.wrap;

			params[ mapType ] = map;

		}

		for ( var prop in mat ) {

			var value = mat[ prop ];
			var n;

			if ( value === '' ) continue;

			switch ( prop.toLowerCase() ) {

				// Ns is material specular exponent

				case 'kd':

					// Diffuse color (color under white light) using RGB values

					params.color = new THREE.Color().fromArray( value );

					break;

				case 'ks':

					// Specular color (color when light is reflected from shiny surface) using RGB values
					params.specular = new THREE.Color().fromArray( value );

					break;

				case 'map_kd':

					// Diffuse texture map

					setMapForType( "map", value );

					break;

				case 'map_ks':

					// Specular map

					setMapForType( "specularMap", value );

					break;

				case 'norm':

					setMapForType( "normalMap", value );

					break;

				case 'map_bump':
				case 'bump':

					// Bump texture map

					setMapForType( "bumpMap", value );

					break;

				case 'ns':

					// The specular exponent (defines the focus of the specular highlight)
					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.

					params.shininess = parseFloat( value );

					break;

				case 'd':
					n = parseFloat( value );

					if ( n < 1 ) {

						params.opacity = n;
						params.transparent = true;

					}

					break;

				case 'tr':
					n = parseFloat( value );

					if ( this.options && this.options.invertTrProperty ) n = 1 - n;

					if ( n > 0 ) {

						params.opacity = 1 - n;
						params.transparent = true;

					}

					break;

				default:
					break;

			}

		}

		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
		return this.materials[ materialName ];

	},

	getTextureParams: function ( value, matParams ) {

		var texParams = {

			scale: new THREE.Vector2( 1, 1 ),
			offset: new THREE.Vector2( 0, 0 )

		 };

		var items = value.split( /\s+/ );
		var pos;

		pos = items.indexOf( '-bm' );

		if ( pos >= 0 ) {

			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
			items.splice( pos, 2 );

		}

		pos = items.indexOf( '-s' );

		if ( pos >= 0 ) {

			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		pos = items.indexOf( '-o' );

		if ( pos >= 0 ) {

			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		texParams.url = items.join( ' ' ).trim();
		return texParams;

	},

	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {

		var texture;
		var loader = THREE.Loader.Handlers.get( url );
		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;

		if ( loader === null ) {

			loader = new THREE.TextureLoader( manager );

		}

		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
		texture = loader.load( url, onLoad, onProgress, onError );

		if ( mapping !== undefined ) texture.mapping = mapping;

		return texture;

	}

};
<commit_msg>Added support for alphaMap<commit_after>/**
 * Loads a Wavefront .mtl file specifying materials
 *
 * @author angelxuanchang
 */

THREE.MTLLoader = function ( manager ) {

	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;

};

THREE.MTLLoader.prototype = {

	constructor: THREE.MTLLoader,

	/**
	 * Loads and parses a MTL asset from a URL.
	 *
	 * @param {String} url - URL to the MTL file.
	 * @param {Function} [onLoad] - Callback invoked with the loaded object.
	 * @param {Function} [onProgress] - Callback for download progress.
	 * @param {Function} [onError] - Callback for download errors.
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to load.
	 */
	load: function ( url, onLoad, onProgress, onError ) {

		var scope = this;

		var loader = new THREE.FileLoader( this.manager );
		loader.setPath( this.path );
		loader.load( url, function ( text ) {

			onLoad( scope.parse( text ) );

		}, onProgress, onError );

	},

	/**
	 * Set base path for resolving references.
	 * If set this path will be prepended to each loaded and found reference.
	 *
	 * @see setTexturePath
	 * @param {String} path
	 * @return {THREE.MTLLoader}
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setPath: function ( path ) {

		this.path = path;
		return this;

	},

	/**
	 * Set base path for resolving texture references.
	 * If set this path will be prepended found texture reference.
	 * If not set and setPath is, it will be used as texture base path.
	 *
	 * @see setPath
	 * @param {String} path
	 * @return {THREE.MTLLoader}
	 *
	 * @example
	 *     mtlLoader.setPath( 'assets/obj/' );
	 *     mtlLoader.setTexturePath( 'assets/textures/' );
	 *     mtlLoader.load( 'my.mtl', ... );
	 */
	setTexturePath: function ( path ) {

		this.texturePath = path;
		return this;

	},

	setBaseUrl: function ( path ) {

		console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );

		return this.setTexturePath( path );

	},

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;
		return this;

	},

	setMaterialOptions: function ( value ) {

		this.materialOptions = value;
		return this;

	},

	/**
	 * Parses a MTL file.
	 *
	 * @param {String} text - Content of MTL file
	 * @return {THREE.MTLLoader.MaterialCreator}
	 *
	 * @see setPath setTexturePath
	 *
	 * @note In order for relative texture references to resolve correctly
	 * you must call setPath and/or setTexturePath explicitly prior to parse.
	 */
	parse: function ( text ) {

		var lines = text.split( '\n' );
		var info = {};
		var delimiter_pattern = /\s+/;
		var materialsInfo = {};

		for ( var i = 0; i < lines.length; i ++ ) {

			var line = lines[ i ];
			line = line.trim();

			if ( line.length === 0 || line.charAt( 0 ) === '#' ) {

				// Blank line or comment ignore
				continue;

			}

			var pos = line.indexOf( ' ' );

			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
			key = key.toLowerCase();

			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
			value = value.trim();

			if ( key === 'newmtl' ) {

				// New material

				info = { name: value };
				materialsInfo[ value ] = info;

			} else if ( info ) {

				if ( key === 'ka' || key === 'kd' || key === 'ks' ) {

					var ss = value.split( delimiter_pattern, 3 );
					info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];

				} else {

					info[ key ] = value;

				}

			}

		}

		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
		materialCreator.setCrossOrigin( this.crossOrigin );
		materialCreator.setManager( this.manager );
		materialCreator.setMaterials( materialsInfo );
		return materialCreator;

	}

};

/**
 * Create a new THREE-MTLLoader.MaterialCreator
 * @param baseUrl - Url relative to which textures are loaded
 * @param options - Set of options on how to construct the materials
 *                  side: Which side to apply the material
 *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
 *                  wrap: What type of wrapping to apply for textures
 *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
 *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
 *                                Default: false, assumed to be already normalized
 *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
 *                                  Default: false
 * @constructor
 */

THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {

	this.baseUrl = baseUrl || '';
	this.options = options;
	this.materialsInfo = {};
	this.materials = {};
	this.materialsArray = [];
	this.nameLookup = {};

	this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
	this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;

};

THREE.MTLLoader.MaterialCreator.prototype = {

	constructor: THREE.MTLLoader.MaterialCreator,

	crossOrigin: 'anonymous',

	setCrossOrigin: function ( value ) {

		this.crossOrigin = value;
		return this;

	},

	setManager: function ( value ) {

		this.manager = value;

	},

	setMaterials: function ( materialsInfo ) {

		this.materialsInfo = this.convert( materialsInfo );
		this.materials = {};
		this.materialsArray = [];
		this.nameLookup = {};

	},

	convert: function ( materialsInfo ) {

		if ( ! this.options ) return materialsInfo;

		var converted = {};

		for ( var mn in materialsInfo ) {

			// Convert materials info into normalized form based on options

			var mat = materialsInfo[ mn ];

			var covmat = {};

			converted[ mn ] = covmat;

			for ( var prop in mat ) {

				var save = true;
				var value = mat[ prop ];
				var lprop = prop.toLowerCase();

				switch ( lprop ) {

					case 'kd':
					case 'ka':
					case 'ks':

						// Diffuse color (color under white light) using RGB values

						if ( this.options && this.options.normalizeRGB ) {

							value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];

						}

						if ( this.options && this.options.ignoreZeroRGBs ) {

							if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {

								// ignore

								save = false;

							}

						}

						break;

					default:

						break;

				}

				if ( save ) {

					covmat[ lprop ] = value;

				}

			}

		}

		return converted;

	},

	preload: function () {

		for ( var mn in this.materialsInfo ) {

			this.create( mn );

		}

	},

	getIndex: function ( materialName ) {

		return this.nameLookup[ materialName ];

	},

	getAsArray: function () {

		var index = 0;

		for ( var mn in this.materialsInfo ) {

			this.materialsArray[ index ] = this.create( mn );
			this.nameLookup[ mn ] = index;
			index ++;

		}

		return this.materialsArray;

	},

	create: function ( materialName ) {

		if ( this.materials[ materialName ] === undefined ) {

			this.createMaterial_( materialName );

		}

		return this.materials[ materialName ];

	},

	createMaterial_: function ( materialName ) {

		// Create material

		var scope = this;
		var mat = this.materialsInfo[ materialName ];
		var params = {

			name: materialName,
			side: this.side

		};

		function resolveURL( baseUrl, url ) {

			if ( typeof url !== 'string' || url === '' )
				return '';

			// Absolute URL
			if ( /^https?:\/\//i.test( url ) ) return url;

			return baseUrl + url;

		}

		function setMapForType( mapType, value ) {

			if ( params[ mapType ] ) return; // Keep the first encountered texture

			var texParams = scope.getTextureParams( value, params );
			var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );

			map.repeat.copy( texParams.scale );
			map.offset.copy( texParams.offset );

			map.wrapS = scope.wrap;
			map.wrapT = scope.wrap;

			params[ mapType ] = map;

		}

		for ( var prop in mat ) {

			var value = mat[ prop ];
			var n;

			if ( value === '' ) continue;

			switch ( prop.toLowerCase() ) {

				// Ns is material specular exponent

				case 'kd':

					// Diffuse color (color under white light) using RGB values

					params.color = new THREE.Color().fromArray( value );

					break;

				case 'ks':

					// Specular color (color when light is reflected from shiny surface) using RGB values
					params.specular = new THREE.Color().fromArray( value );

					break;

				case 'map_kd':

					// Diffuse texture map

					setMapForType( "map", value );

					break;

				case 'map_ks':

					// Specular map

					setMapForType( "specularMap", value );

					break;

				case 'norm':

					setMapForType( "normalMap", value );

					break;

				case 'map_bump':
				case 'bump':

					// Bump texture map

					setMapForType( "bumpMap", value );

					break;

				case 'map_d':

					// Alpha map

					setMapForType( "alphaMap", value );
					params.transparent = true;

					break;

				case 'ns':

					// The specular exponent (defines the focus of the specular highlight)
					// A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.

					params.shininess = parseFloat( value );

					break;

				case 'd':
					n = parseFloat( value );

					if ( n < 1 ) {

						params.opacity = n;
						params.transparent = true;

					}

					break;

				case 'tr':
					n = parseFloat( value );

					if ( this.options && this.options.invertTrProperty ) n = 1 - n;

					if ( n > 0 ) {

						params.opacity = 1 - n;
						params.transparent = true;

					}

					break;

				default:
					break;

			}

		}

		this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
		return this.materials[ materialName ];

	},

	getTextureParams: function ( value, matParams ) {

		var texParams = {

			scale: new THREE.Vector2( 1, 1 ),
			offset: new THREE.Vector2( 0, 0 )

		 };

		var items = value.split( /\s+/ );
		var pos;

		pos = items.indexOf( '-bm' );

		if ( pos >= 0 ) {

			matParams.bumpScale = parseFloat( items[ pos + 1 ] );
			items.splice( pos, 2 );

		}

		pos = items.indexOf( '-s' );

		if ( pos >= 0 ) {

			texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		pos = items.indexOf( '-o' );

		if ( pos >= 0 ) {

			texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
			items.splice( pos, 4 ); // we expect 3 parameters here!

		}

		texParams.url = items.join( ' ' ).trim();
		return texParams;

	},

	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {

		var texture;
		var loader = THREE.Loader.Handlers.get( url );
		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;

		if ( loader === null ) {

			loader = new THREE.TextureLoader( manager );

		}

		if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
		texture = loader.load( url, onLoad, onProgress, onError );

		if ( mapping !== undefined ) texture.mapping = mapping;

		return texture;

	}

};
<|endoftext|>


<commit_before>import System;

class Foo {
	public var counter = 0;
	function Bar() { ++counter; }
}

class VirtualFoo {
	public var counter = 0;
	virtual function Bar() { ++counter; }
}

class VirtualFoo2 extends VirtualFoo {
	override function Bar() {}
}

function time(kind, block: function()) {
	var calls = 100000000;
	var start = DateTime.Now;
	for (var i=0; i<calls; ++i)
		block();
	var elapsed = DateTime.Now - start;
	print(calls + " "  + kind + " in " + elapsed.TotalMilliseconds + "ms.");
}

var foo = new Foo();
var virtualFoo = new VirtualFoo();

for (var i = 0; i < 3; ++i) {
	time("non virtual calls", function() { foo.Bar(); });
	time("virtual calls", function() { virtualFoo.Bar(); });
}

<commit_msg>update benchmark after virtual/final semantic changes (all functions are virtual by default now).<commit_after>import System;

class Foo {
	public var counter = 0;
	final function Bar() { ++counter; }
}

class VirtualFoo {
	public var counter = 0;
	function Bar() { ++counter; }
}

class VirtualFoo2 extends VirtualFoo {
	override function Bar() {}
}

function time(kind, block: function()) {
	var calls = 100000000;
	var start = DateTime.Now;
	for (var i=0; i<calls; ++i)
		block();
	var elapsed = DateTime.Now - start;
	print(calls + " "  + kind + " in " + elapsed.TotalMilliseconds + "ms.");
}

var foo = new Foo();
var virtualFoo = new VirtualFoo();

for (var i = 0; i < 3; ++i) {
	time("non virtual calls", function() { foo.Bar(); });
	time("virtual calls", function() { virtualFoo.Bar(); });
}

<|endoftext|>


<commit_before>var timer = foam.util.Timer.create();
timer.start();

var E = foam.__context__.E.bind(foam.__context__);

/*

foam.u2.DetailView.create({
  data: foam.util.Timer.create(),
  showActions: true
})..write();

foam.u2.DetailView.create({
  data: foam.util.Timer.create(),
  showActions: true,
  properties: [ foam.util.Timer.INTERVAL, foam.util.Timer.I ],
  actions: [ foam.util.Timer.STOP, foam.util.Timer.START ]
})..write();

*/
foam.CLASS({
  package: 'foam.util',
  name: 'TimerView',
  extends: 'foam.u2.DetailView',

  requires: [
    'foam.util.Timer'
  ],

  // css: foam.u2.DetailView.model_.css,

  methods: [
    function initE() {
      var self = this;
      this.startContext({data: this.data}).
        tag(this.DetailPropertyView, {prop: self.Timer.I}).
        tag(this.DetailPropertyView, {prop: self.Timer.INTERVAL}).
        add(self.Timer.STOP, self.Timer.START);
    },
    function layoutProperties(properties, self) {
      self.layoutProp(self.Timer.I, self);
      self.layoutProp(self.Timer.INTERVAL, self);
    },

  ]
});

E('br').write();
E('hr').write();
E('br').write();

foam.util.TimerView.create({data: timer, showActions: true}).write();
E('hr').write();
foam.u2.DetailView.create({data: timer, showActions: true}).write();
foam.u2.DetailView.create({of: 'foam.util.Timer', data: timer, showActions: true}).write();

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'GroupDetailView',
  extends: 'foam.u2.View',

  requires: [
    'foam.nanos.auth.Group',
    'foam.u2.DetailPropertyView'
  ],

  // css: foam.u2.DetailView.model_.css,

  css: `
    ^ {
      padding: 8px;
      display: inline-block;
      border-radius: 3px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
      margin: 8px;
    }
  `,

  methods: [
    function initE() {
      this.SUPER();
      var self = this;

      this.
        addClass(this.myClass()).
        start(Columns).
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.ID}).
            tag(this.DetailPropertyView, {prop: this.data.DESCRIPTION}).
          end().end().
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.PARENT}).
            tag(this.DetailPropertyView, {prop: this.data.DEFAULT_MENU}).
            tag(this.DetailPropertyView, {prop: this.data.ENABLED}).
          end().end().
        end().
        br().
        start(Tabs).
          start(Tab, {label: 'Permissions'}).
            start().style({'overflow-y': 'auto'}).
              startContext({data: this.data}).
                add(this.data.PERMISSIONS).
              endContext().
              startContext({data: this.data}).
                add(this.data.PERMISSIONS2).
              endContext().
            end().
          end().
          start(Tab, {label: 'Users'}).
          end().
          start(Tab, {label: 'Colours'}).
            start('table').
              tag(this.DetailPropertyView, {prop: this.data.PRIMARY_COLOR,     label: 'Primary'}).
              tag(this.DetailPropertyView, {prop: this.data.SECONDARY_COLOR,   label: 'Secondary'}).
              tag(this.DetailPropertyView, {prop: this.data.ACCENT_COLOR,      label: 'Accent'}).
              tag(this.DetailPropertyView, {prop: this.data.TABLE_COLOR,       label: 'Table'}).
              tag(this.DetailPropertyView, {prop: this.data.TABLE_HOVER_COLOR, label: 'Table Hover'}).
            end().
          end().
          start(Tab, {label: 'CSS'}).
            add(this.data.GROUP_CSS).
          end().
          start(Tab, {label: 'Views'}).
            start('table').
              tag(this.DetailPropertyView, {prop: this.data.TOP_NAVIGATION}).
              tag(this.DetailPropertyView, {prop: this.data.FOOTER_VIEW, label: 'Footer'}).
            end().
          end().
          start(Tab, {label: 'Logo'}).
            add(this.data.LOGO).
            br().
            start(foam.u2.view.ImageView, {data: this.data.logo$}).style({padding: '10px'}).end().
          end().
        end();
//        tag(this.DetailPropertyView, {prop: this.data.USERS});
    }
  ]
});

// Bug: Borders don't pass down Context properly

foam.u2.DetailView.create({of: foam.nanos.auth.Group, data: foam.nanos.auth.Group.create(), showActions: true}).write();

E('br').write();
E('hr').write();
E('br').write();

foam.CLASS({
  name: 'GroupDetailView2',
  extends: 'foam.u2.View',

  requires: [
    'foam.nanos.auth.Group',
    'foam.u2.DetailPropertyView'
  ],

  css: `
    ^ {
      padding: 8px;
      display: inline-block;
      border-radius: 3px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
      margin: 8px;
    }
  `,

  methods: [
    function initE() {
      this.SUPER();
      var self = this;

      this.
        addClass(this.myClass()).
        start(Columns).
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.ID}).
            tag(this.DetailPropertyView, {prop: this.data.DESCRIPTION}).
          end().end().
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.PARENT}).
            tag(this.DetailPropertyView, {prop: this.data.DEFAULT_MENU}).
            tag(this.DetailPropertyView, {prop: this.data.ENABLED}).
          end().end().
        end().
        br().
        start(Tabs).

          start(Tab, {label: 'Look & Feel'}).

            start(Columns).
              start(Column).

                start(LabelledSection, {title: 'CSS'}).
                  add(this.data.GROUP_CSS).
                end().br().

                start(LabelledSection, {title: 'Logo'}).
                  br().
                  add(this.data.LOGO).
                  br().
                  start(foam.u2.view.ImageView, {data: this.data.logo$}).style({padding: '10px'}).end().
                end().

              end().

              start(Column).

                start(LabelledSection, {title: 'Colours'}).
                  start('table').
                    tag(this.DetailPropertyView, {prop: this.data.PRIMARY_COLOR,     label: 'Primary'}).
                    tag(this.DetailPropertyView, {prop: this.data.SECONDARY_COLOR,   label: 'Secondary'}).
                    tag(this.DetailPropertyView, {prop: this.data.ACCENT_COLOR,      label: 'Accent'}).
                    tag(this.DetailPropertyView, {prop: this.data.TABLE_COLOR,       label: 'Table'}).
                    tag(this.DetailPropertyView, {prop: this.data.TABLE_HOVER_COLOR, label: 'Table Hover'}).
                  end().
                end().br().

                start(LabelledSection, {title: 'Views'}).
                  start('table').
                    tag(this.DetailPropertyView, {prop: this.data.TOP_NAVIGATION}).
                    tag(this.DetailPropertyView, {prop: this.data.FOOTER_VIEW, label: 'Footer'}).
                  end().
                end().

              end().
            end().
          end().

          start(Tab, {label: 'Permissions'}).
            start().style({'overflow-y': 'auto'}).
              add(this.data.PERMISSIONS).
            end().
          end().

          start(Tab, {label: 'Users'}).
          end().

        end();
//        tag(this.DetailPropertyView, {prop: this.data.USERS});
    }
  ]
});

GroupDetailView2.create({of: foam.nanos.auth.Group, data: foam.nanos.auth.Group.create(), showActions: true}).write();

E('br').write();
E('hr').write();
E('br').write();

/*
foam.nanos.auth.Group.getAxiomsByClass(foam.core.Property).forEach(function(p) { console.log("tag(this.DetailPropertyView, {prop: this.data." + foam.String.constantize(p.name) + "})..");}).;
*/
<commit_msg>Update DetailView demo.<commit_after>var timer = foam.util.Timer.create();
timer.start();

var E = foam.__context__.E.bind(foam.__context__);

/*

foam.u2.DetailView.create({
  data: foam.util.Timer.create(),
  showActions: true
})..write();

foam.u2.DetailView.create({
  data: foam.util.Timer.create(),
  showActions: true,
  properties: [ foam.util.Timer.INTERVAL, foam.util.Timer.I ],
  actions: [ foam.util.Timer.STOP, foam.util.Timer.START ]
})..write();

*/
foam.CLASS({
  package: 'foam.util',
  name: 'TimerDetailView',
  extends: 'foam.u2.DetailView',

  requires: [
    'foam.util.Timer'
  ],

  // css: foam.u2.DetailView.model_.css,

  methods: [
    function initE() {
      var self = this;
      this.startContext({data: this.data}).
        tag(this.DetailPropertyView, {prop: self.Timer.I}).
        tag(this.DetailPropertyView, {prop: self.Timer.INTERVAL}).
        add(self.Timer.STOP, self.Timer.START);
    },
    function layoutProperties(properties, self) {
      self.layoutProp(self.Timer.I, self);
      self.layoutProp(self.Timer.INTERVAL, self);
    },

  ]
});

E('br').write();
E('hr').write();
E('br').write();

E('h3').add('Custom DetailView').write();
foam.util.TimerDetailView.create({data: timer, showActions: true}).write();

E('h3').add('DetailView with data').write();
foam.u2.DetailView.create({data: timer, showActions: true}).write();

E('h3').add('DetailView with of and data').write();
foam.u2.DetailView.create({of: 'foam.util.Timer', data: timer, showActions: true}).write();

E('h3').add('DetailView with of').write();
foam.u2.DetailView.create({of: 'foam.util.Timer', showActions: true}).write();

E('br').write();
E('hr').write();
E('br').write();

foam.CLASS({
  package: 'foam.nanos.auth',
  name: 'GroupDetailView',
  extends: 'foam.u2.View',

  requires: [
    'foam.nanos.auth.Group',
    'foam.u2.DetailPropertyView'
  ],

  // css: foam.u2.DetailView.model_.css,

  css: `
    ^ {
      padding: 8px;
      display: inline-block;
      border-radius: 3px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
      margin: 8px;
    }
  `,

  methods: [
    function initE() {
      this.SUPER();
      var self = this;

      this.
        addClass(this.myClass()).
        start(Columns).
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.ID}).
            tag(this.DetailPropertyView, {prop: this.data.DESCRIPTION}).
          end().end().
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.PARENT}).
            tag(this.DetailPropertyView, {prop: this.data.DEFAULT_MENU}).
            tag(this.DetailPropertyView, {prop: this.data.ENABLED}).
          end().end().
        end().
        br().
        start(Tabs).
          start(Tab, {label: 'Permissions'}).
            start().style({'overflow-y': 'auto'}).
              startContext({data: this.data}).
                add(this.data.PERMISSIONS).
              endContext().
              startContext({data: this.data}).
                add(this.data.PERMISSIONS2).
              endContext().
            end().
          end().
          start(Tab, {label: 'Users'}).
          end().
          start(Tab, {label: 'Colours'}).
            start('table').
              tag(this.DetailPropertyView, {prop: this.data.PRIMARY_COLOR,     label: 'Primary'}).
              tag(this.DetailPropertyView, {prop: this.data.SECONDARY_COLOR,   label: 'Secondary'}).
              tag(this.DetailPropertyView, {prop: this.data.ACCENT_COLOR,      label: 'Accent'}).
              tag(this.DetailPropertyView, {prop: this.data.TABLE_COLOR,       label: 'Table'}).
              tag(this.DetailPropertyView, {prop: this.data.TABLE_HOVER_COLOR, label: 'Table Hover'}).
            end().
          end().
          start(Tab, {label: 'CSS'}).
            add(this.data.GROUP_CSS).
          end().
          start(Tab, {label: 'Views'}).
            start('table').
              tag(this.DetailPropertyView, {prop: this.data.TOP_NAVIGATION}).
              tag(this.DetailPropertyView, {prop: this.data.FOOTER_VIEW, label: 'Footer'}).
            end().
          end().
          start(Tab, {label: 'Logo'}).
            add(this.data.LOGO).
            br().
            start(foam.u2.view.ImageView, {data: this.data.logo$}).style({padding: '10px'}).end().
          end().
        end();
//        tag(this.DetailPropertyView, {prop: this.data.USERS});
    }
  ]
});

// Bug: Borders don't pass down Context properly

foam.u2.DetailView.create({of: foam.nanos.auth.Group, data: foam.nanos.auth.Group.create(), showActions: true}).write();

E('br').write();
E('hr').write();
E('br').write();

foam.CLASS({
  name: 'GroupDetailView2',
  extends: 'foam.u2.View',

  requires: [
    'foam.nanos.auth.Group',
    'foam.u2.DetailPropertyView'
  ],

  css: `
    ^ {
      padding: 8px;
      display: inline-block;
      border-radius: 3px;
      box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
      margin: 8px;
    }
  `,

  methods: [
    function initE() {
      this.SUPER();
      var self = this;

      this.
        addClass(this.myClass()).
        start(Columns).
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.ID}).
            tag(this.DetailPropertyView, {prop: this.data.DESCRIPTION}).
          end().end().
          start(Column).start('table').
            tag(this.DetailPropertyView, {prop: this.data.PARENT}).
            tag(this.DetailPropertyView, {prop: this.data.DEFAULT_MENU}).
            tag(this.DetailPropertyView, {prop: this.data.ENABLED}).
          end().end().
        end().
        br().
        start(Tabs).

          start(Tab, {label: 'Look & Feel'}).

            start(Columns).
              start(Column).

                start(LabelledSection, {title: 'CSS'}).
                  add(this.data.GROUP_CSS).
                end().br().

                start(LabelledSection, {title: 'Logo'}).
                  br().
                  add(this.data.LOGO).
                  br().
                  start(foam.u2.view.ImageView, {data: this.data.logo$}).style({padding: '10px'}).end().
                end().

              end().

              start(Column).

                start(LabelledSection, {title: 'Colours'}).
                  start('table').
                    tag(this.DetailPropertyView, {prop: this.data.PRIMARY_COLOR,     label: 'Primary'}).
                    tag(this.DetailPropertyView, {prop: this.data.SECONDARY_COLOR,   label: 'Secondary'}).
                    tag(this.DetailPropertyView, {prop: this.data.ACCENT_COLOR,      label: 'Accent'}).
                    tag(this.DetailPropertyView, {prop: this.data.TABLE_COLOR,       label: 'Table'}).
                    tag(this.DetailPropertyView, {prop: this.data.TABLE_HOVER_COLOR, label: 'Table Hover'}).
                  end().
                end().br().

                start(LabelledSection, {title: 'Views'}).
                  start('table').
                    tag(this.DetailPropertyView, {prop: this.data.TOP_NAVIGATION}).
                    tag(this.DetailPropertyView, {prop: this.data.FOOTER_VIEW, label: 'Footer'}).
                  end().
                end().

              end().
            end().
          end().

          start(Tab, {label: 'Permissions'}).
            start().style({'overflow-y': 'auto'}).
              add(this.data.PERMISSIONS).
            end().
          end().

          start(Tab, {label: 'Users'}).
          end().

        end();
//        tag(this.DetailPropertyView, {prop: this.data.USERS});
    }
  ]
});

GroupDetailView2.create({of: foam.nanos.auth.Group, data: foam.nanos.auth.Group.create(), showActions: true}).write();

E('br').write();
E('hr').write();
E('br').write();

/*
foam.nanos.auth.Group.getAxiomsByClass(foam.core.Property).forEach(function(p) { console.log("tag(this.DetailPropertyView, {prop: this.data." + foam.String.constantize(p.name) + "})..");}).;
*/
<|endoftext|>


<commit_before>module.exports = {
  extends: ["eslint:recommended", "plugin:prettier/recommended"],
  plugins: ["prettier"],
  rules: {
    "prettier/prettier": "error"
  },
  env: {
    node: true
  }
};
<commit_msg>Allow console.error<commit_after>module.exports = {
  extends: ["eslint:recommended", "plugin:prettier/recommended"],
  plugins: ["prettier"],
  rules: {
    "prettier/prettier": "error",
    "no-console": [
      "error",
      {
        allow: ["error"]
      }
    ]
  },
  env: {
    node: true
  }
};
<|endoftext|>


<commit_before>import { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import shortID from 'shortid';
import { createBlock, createUnblock } from './redux';

@connect(null, dispatch => ({
  block: createBlock(dispatch),
  unblock: createUnblock(dispatch),
}))
class Prompt extends Component {
  id = shortID.generate();

  static propTypes = {
    when: PropTypes.bool,
    message: PropTypes.oneOfType([PropTypes.func, PropTypes.string]).isRequired,
  };

  static defaultProps = {
    when: true,
  };

  componentWillMount() {
    if (this.props.when) {
      this.enable(this.props.message);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.when) {
      if (!this.props.when || this.props.message !== nextProps.message) {
        this.enable(nextProps.message);
      }
    } else {
      this.disable();
    }
  }

  componentWillUnmount() {
    this.disable();
  }

  enable(message) {
    this.props.block(this.id, message);
  }

  disable() {
    this.props.unblock(this.id);
  }

  render() {
    return null;
  }
}

export default Prompt;
<commit_msg>better rnd<commit_after>import { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { createBlock, createUnblock } from './redux';

@connect(null, dispatch => ({
  block: createBlock(dispatch),
  unblock: createUnblock(dispatch)
}))
class Prompt extends Component {
  id = Math.random()
    .toString(36)
    .substr(2, 10);

  static propTypes = {
    when: PropTypes.bool,
    message: PropTypes.oneOfType([PropTypes.func, PropTypes.string]).isRequired
  };

  static defaultProps = {
    when: true
  };

  componentWillMount() {
    if (this.props.when) {
      this.enable(this.props.message);
    }
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.when) {
      if (!this.props.when || this.props.message !== nextProps.message) {
        this.enable(nextProps.message);
      }
    } else {
      this.disable();
    }
  }

  componentWillUnmount() {
    this.disable();
  }

  enable(message) {
    this.props.block(this.id, message);
  }

  disable() {
    this.props.unblock(this.id);
  }

  render() {
    return null;
  }
}

export default Prompt;
<|endoftext|>


<commit_before>import macro                      from 'vtk.js/Sources/macro';
import vtkFullScreenRenderWindow  from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';

import vtkActor                   from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkCalculator              from 'vtk.js/Sources/Filters/General/Calculator';
import vtkLookupTable             from 'vtk.js/Sources/Common/Core/LookupTable';
import vtkMapper                  from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkPlaneSource             from 'vtk.js/Sources/Filters/Sources/PlaneSource';
import vtkPoints                  from 'vtk.js/Sources/Common/Core/Points';
import vtkPolyData                from 'vtk.js/Sources/Common/DataModel/PolyData';
import vtkWarpScalar              from 'vtk.js/Sources/Filters/General/WarpScalar';
import { ColorMode, ScalarMode }  from 'vtk.js/Sources/Rendering/Core/Mapper/Constants';
import { FieldDataTypes }         from 'vtk.js/Sources/Common/DataModel/DataSet/Constants';

import controlPanel from './controlPanel.html';

const { vtkErrorMacro } = macro;

let formulaIdx = 0;
const FORMULA = [
  '((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)) + 0.125',
  '0.25 * Math.sin(Math.sqrt(((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)))*50)',
];

// ----------------------------------------------------------------------------
// Standard rendering code setup
// ----------------------------------------------------------------------------

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background: [0.9, 0.9, 0.9] });
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------

const lookupTable = vtkLookupTable.newInstance({ hueRange: [0.666, 0] });

const planeSource = vtkPlaneSource.newInstance({ xResolution: 25, yResolution: 25 });
const planeMapper = vtkMapper.newInstance({
  interpolateScalarsBeforeMapping: true,
  colorMode: ColorMode.DEFAULT,
  scalarMode: ScalarMode.DEFAULT,
  useLookupTableScalarRange: true,
  lookupTable,
});
const planeActor = vtkActor.newInstance();
planeActor.getProperty().setEdgeVisibility(true);

const simpleFilter = vtkCalculator.newInstance();
simpleFilter.setFormulaSimple(
  FieldDataTypes.POINT, // Generate an output array defined over points.
  [],  // We don't request any point-data arrays because point coordinates are made available by default.
  'z', // Name the output array "z"
  x => ((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)) + 0.125,
); // Our formula for z

const warpScalar = vtkWarpScalar.newInstance();
const warpMapper = vtkMapper.newInstance({
  interpolateScalarsBeforeMapping: true,
  useLookupTableScalarRange: true,
  lookupTable,
});
const warpActor = vtkActor.newInstance();

// The generated 'z' array will become the default scalars, so the plane mapper will color by 'z':
simpleFilter.setInputConnection(planeSource.getOutputPort());

// We will also generate a surface whose points are displaced from the plane by 'z':
warpScalar.setInputConnection(simpleFilter.getOutputPort());
warpScalar.setInputArrayToProcess(0, 'z', 'PointData', 'Scalars');

planeMapper.setInputConnection(simpleFilter.getOutputPort());
planeActor.setMapper(planeMapper);

warpMapper.setInputConnection(warpScalar.getOutputPort());
warpActor.setMapper(warpMapper);

renderer.addActor(planeActor);
renderer.addActor(warpActor);

renderer.resetCamera();
renderWindow.render();

// ----------------------------------------------------------------------------
// UI control handling
// ----------------------------------------------------------------------------

fullScreenRenderer.addController(controlPanel);

function updateScalarRange() {
  const min = Number(document.querySelector('.min').value);
  const max = Number(document.querySelector('.max').value);
  if (!isNaN(min) && !isNaN(max)) {
    lookupTable.setMappingRange(min, max);
    renderWindow.render();
  }
}

function applyFormula() {
  const el = document.querySelector('.formula');
  let fn = null;
  try {
    /* eslint-disable no-new-func */
    fn = new Function('x,y', `return ${el.value}`);
    /* eslint-enable no-new-func */
  } catch (exc) {
    if (!('name' in exc && exc.name === 'SyntaxError')) {
      vtkErrorMacro(`Unexpected exception ${exc}`);
      el.style.background = '#fbb';
      return;
    }
  }
  if (fn) {
    el.style.background = '#fff';
    const formulaObj = simpleFilter.createSimpleFormulaObject(
      FieldDataTypes.POINT, [], 'z', fn);

    // See if the formula is actually valid by invoking "formulaObj" on
    // a dataset containing a single point.
    planeSource.update();
    const arraySpec = formulaObj.getArrays(planeSource.getOutputData());
    const testData = vtkPolyData.newInstance();
    const testPts = vtkPoints.newInstance({ name: 'coords', numberOfComponents: 3, size: 3, values: [0, 0, 0] });
    testData.setPoints(testPts);
    const testOut = vtkPolyData.newInstance();
    testOut.shallowCopy(testData);
    const testArrays = simpleFilter.prepareArrays(arraySpec, testData, testOut);
    try {
      formulaObj.evaluate(testArrays.arraysIn, testArrays.arraysOut);

      // We evaluated 1 point without exception... it's safe to update the
      // filter and re-render.
      simpleFilter.setFormula(formulaObj);

      simpleFilter.update();

      // Update UI with new range
      const [min, max] = simpleFilter.getOutputData().getPointData().getScalars().getRange();
      document.querySelector('.min').value = min;
      document.querySelector('.max').value = max;
      lookupTable.setMappingRange(min, max);

      renderWindow.render();
      return;
    } catch (exc) {
      vtkErrorMacro(`Unexpected exception ${exc}`);
    }
  }
  el.style.background = '#ffb';
}

['xResolution', 'yResolution'].forEach((propertyName) => {
  document.querySelector(`.${propertyName}`).addEventListener('input', (e) => {
    const value = Number(e.target.value);
    planeSource.set({ [propertyName]: value });
    renderWindow.render();
  });
});

['scaleFactor'].forEach((propertyName) => {
  document.querySelector(`.${propertyName}`).addEventListener('input', (e) => {
    const value = Number(e.target.value);
    warpScalar.set({ [propertyName]: value });
    renderWindow.render();
  });
});

// Checkbox
document.querySelector('.visibility').addEventListener('change', (e) => {
  planeActor.setVisibility(!!e.target.checked);
  renderWindow.render();
});

document.querySelector('.formula').addEventListener('input', applyFormula);

['min', 'max'].forEach((selector) => {
  document.querySelector(`.${selector}`).addEventListener('input', updateScalarRange);
});

document.querySelector('.next').addEventListener('click', (e) => {
  formulaIdx = (formulaIdx + 1) % FORMULA.length;
  document.querySelector('.formula').value = FORMULA[formulaIdx];
  applyFormula();
  renderWindow.render();
});

// Eecompute scalar range
applyFormula();

// -----------------------------------------------------------
// Make some variables global so that you can inspect and
// modify objects in your browser's developer console:
// -----------------------------------------------------------

global.setLoggerFunction = macro.setLoggerFunction;
global.planeSource = planeSource;
global.planeMapper = planeMapper;
global.planeActor = planeActor;
global.simpleFilter = simpleFilter;
global.warpMapper = warpMapper;
global.warpActor = warpActor;
global.renderer = renderer;
global.renderWindow = renderWindow;
global.lookupTable = lookupTable;
<commit_msg>doc(Calculator): Update example to reflect Constants usage<commit_after>import macro                      from 'vtk.js/Sources/macro';
import vtkFullScreenRenderWindow  from 'vtk.js/Sources/Rendering/Misc/FullScreenRenderWindow';

import vtkActor       from 'vtk.js/Sources/Rendering/Core/Actor';
import vtkCalculator  from 'vtk.js/Sources/Filters/General/Calculator';
import vtkDataSet     from 'vtk.js/Sources/Common/DataModel/DataSet';
import vtkLookupTable from 'vtk.js/Sources/Common/Core/LookupTable';
import vtkMapper      from 'vtk.js/Sources/Rendering/Core/Mapper';
import vtkPlaneSource from 'vtk.js/Sources/Filters/Sources/PlaneSource';
import vtkPoints      from 'vtk.js/Sources/Common/Core/Points';
import vtkPolyData    from 'vtk.js/Sources/Common/DataModel/PolyData';
import vtkWarpScalar  from 'vtk.js/Sources/Filters/General/WarpScalar';

import controlPanel from './controlPanel.html';

const { ColorMode, ScalarMode } = vtkMapper;
const { FieldDataTypes } = vtkDataSet;
const { vtkErrorMacro } = macro;

let formulaIdx = 0;
const FORMULA = [
  '((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)) + 0.125',
  '0.25 * Math.sin(Math.sqrt(((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)))*50)',
];

// ----------------------------------------------------------------------------
// Standard rendering code setup
// ----------------------------------------------------------------------------

const fullScreenRenderer = vtkFullScreenRenderWindow.newInstance({ background: [0.9, 0.9, 0.9] });
const renderer = fullScreenRenderer.getRenderer();
const renderWindow = fullScreenRenderer.getRenderWindow();

// ----------------------------------------------------------------------------
// Example code
// ----------------------------------------------------------------------------

const lookupTable = vtkLookupTable.newInstance({ hueRange: [0.666, 0] });

const planeSource = vtkPlaneSource.newInstance({ xResolution: 25, yResolution: 25 });
const planeMapper = vtkMapper.newInstance({
  interpolateScalarsBeforeMapping: true,
  colorMode: ColorMode.DEFAULT,
  scalarMode: ScalarMode.DEFAULT,
  useLookupTableScalarRange: true,
  lookupTable,
});
const planeActor = vtkActor.newInstance();
planeActor.getProperty().setEdgeVisibility(true);

const simpleFilter = vtkCalculator.newInstance();
simpleFilter.setFormulaSimple(
  FieldDataTypes.POINT, // Generate an output array defined over points.
  [],  // We don't request any point-data arrays because point coordinates are made available by default.
  'z', // Name the output array "z"
  x => ((x[0] - 0.5) * (x[0] - 0.5)) + ((x[1] - 0.5) * (x[1] - 0.5)) + 0.125,
); // Our formula for z

const warpScalar = vtkWarpScalar.newInstance();
const warpMapper = vtkMapper.newInstance({
  interpolateScalarsBeforeMapping: true,
  useLookupTableScalarRange: true,
  lookupTable,
});
const warpActor = vtkActor.newInstance();

// The generated 'z' array will become the default scalars, so the plane mapper will color by 'z':
simpleFilter.setInputConnection(planeSource.getOutputPort());

// We will also generate a surface whose points are displaced from the plane by 'z':
warpScalar.setInputConnection(simpleFilter.getOutputPort());
warpScalar.setInputArrayToProcess(0, 'z', 'PointData', 'Scalars');

planeMapper.setInputConnection(simpleFilter.getOutputPort());
planeActor.setMapper(planeMapper);

warpMapper.setInputConnection(warpScalar.getOutputPort());
warpActor.setMapper(warpMapper);

renderer.addActor(planeActor);
renderer.addActor(warpActor);

renderer.resetCamera();
renderWindow.render();

// ----------------------------------------------------------------------------
// UI control handling
// ----------------------------------------------------------------------------

fullScreenRenderer.addController(controlPanel);

function updateScalarRange() {
  const min = Number(document.querySelector('.min').value);
  const max = Number(document.querySelector('.max').value);
  if (!isNaN(min) && !isNaN(max)) {
    lookupTable.setMappingRange(min, max);
    renderWindow.render();
  }
}

function applyFormula() {
  const el = document.querySelector('.formula');
  let fn = null;
  try {
    /* eslint-disable no-new-func */
    fn = new Function('x,y', `return ${el.value}`);
    /* eslint-enable no-new-func */
  } catch (exc) {
    if (!('name' in exc && exc.name === 'SyntaxError')) {
      vtkErrorMacro(`Unexpected exception ${exc}`);
      el.style.background = '#fbb';
      return;
    }
  }
  if (fn) {
    el.style.background = '#fff';
    const formulaObj = simpleFilter.createSimpleFormulaObject(
      FieldDataTypes.POINT, [], 'z', fn);

    // See if the formula is actually valid by invoking "formulaObj" on
    // a dataset containing a single point.
    planeSource.update();
    const arraySpec = formulaObj.getArrays(planeSource.getOutputData());
    const testData = vtkPolyData.newInstance();
    const testPts = vtkPoints.newInstance({ name: 'coords', numberOfComponents: 3, size: 3, values: [0, 0, 0] });
    testData.setPoints(testPts);
    const testOut = vtkPolyData.newInstance();
    testOut.shallowCopy(testData);
    const testArrays = simpleFilter.prepareArrays(arraySpec, testData, testOut);
    try {
      formulaObj.evaluate(testArrays.arraysIn, testArrays.arraysOut);

      // We evaluated 1 point without exception... it's safe to update the
      // filter and re-render.
      simpleFilter.setFormula(formulaObj);

      simpleFilter.update();

      // Update UI with new range
      const [min, max] = simpleFilter.getOutputData().getPointData().getScalars().getRange();
      document.querySelector('.min').value = min;
      document.querySelector('.max').value = max;
      lookupTable.setMappingRange(min, max);

      renderWindow.render();
      return;
    } catch (exc) {
      vtkErrorMacro(`Unexpected exception ${exc}`);
    }
  }
  el.style.background = '#ffb';
}

['xResolution', 'yResolution'].forEach((propertyName) => {
  document.querySelector(`.${propertyName}`).addEventListener('input', (e) => {
    const value = Number(e.target.value);
    planeSource.set({ [propertyName]: value });
    renderWindow.render();
  });
});

['scaleFactor'].forEach((propertyName) => {
  document.querySelector(`.${propertyName}`).addEventListener('input', (e) => {
    const value = Number(e.target.value);
    warpScalar.set({ [propertyName]: value });
    renderWindow.render();
  });
});

// Checkbox
document.querySelector('.visibility').addEventListener('change', (e) => {
  planeActor.setVisibility(!!e.target.checked);
  renderWindow.render();
});

document.querySelector('.formula').addEventListener('input', applyFormula);

['min', 'max'].forEach((selector) => {
  document.querySelector(`.${selector}`).addEventListener('input', updateScalarRange);
});

document.querySelector('.next').addEventListener('click', (e) => {
  formulaIdx = (formulaIdx + 1) % FORMULA.length;
  document.querySelector('.formula').value = FORMULA[formulaIdx];
  applyFormula();
  renderWindow.render();
});

// Eecompute scalar range
applyFormula();

// -----------------------------------------------------------
// Make some variables global so that you can inspect and
// modify objects in your browser's developer console:
// -----------------------------------------------------------

global.setLoggerFunction = macro.setLoggerFunction;
global.planeSource = planeSource;
global.planeMapper = planeMapper;
global.planeActor = planeActor;
global.simpleFilter = simpleFilter;
global.warpMapper = warpMapper;
global.warpActor = warpActor;
global.renderer = renderer;
global.renderWindow = renderWindow;
global.lookupTable = lookupTable;
<|endoftext|>


<commit_before>'use strict';

var appRoot = require('app-root-path');

module.exports = {
  target: 'node',
  entry: appRoot.toString(),
  output: {
    path: appRoot.toString(),
    filename: 'bundle.js',
    libraryTarget: 'commonjs2',
    devtoolModuleFilenameTemplate: '[absolute-resource-path]',
    devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]'
  },
  context: appRoot.toString(),
  resolve: {
    mainFields: ['hopsServer', 'server', 'main'],
    extensions: ['.js', '.jsx']
  },
  externals: [require('webpack-node-externals')()],
  module: {
    rules: [
      require('./loaders/babel').default,
      require('./loaders/postcss').render,
      require('./loaders/json').default,
      require('./loaders/file').default,
      require('./loaders/url').default,
      require('./loaders/tpl').default
    ]
  },
  devtool: '#inline-source-map'
};
<commit_msg>prevent multiple chunks being produced for server side rendering<commit_after>'use strict';

var appRoot = require('app-root-path');

var webpack = require('webpack');

module.exports = {
  target: 'node',
  entry: appRoot.toString(),
  output: {
    path: appRoot.toString(),
    filename: 'bundle.js',
    libraryTarget: 'commonjs2',
    devtoolModuleFilenameTemplate: '[absolute-resource-path]',
    devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]'
  },
  context: appRoot.toString(),
  resolve: {
    mainFields: ['hopsServer', 'server', 'main'],
    extensions: ['.js', '.jsx']
  },
  externals: [require('webpack-node-externals')()],
  module: {
    rules: [
      require('./loaders/babel').default,
      require('./loaders/postcss').render,
      require('./loaders/json').default,
      require('./loaders/file').default,
      require('./loaders/url').default,
      require('./loaders/tpl').default
    ]
  },
  plugins: [
    new webpack.optimize.LimitChunkCountPlugin({
      maxChunks: 1
    })
  ],
  devtool: '#inline-source-map'
};
<|endoftext|>