Skip to content

Instantly share code, notes, and snippets.

@everplays
Created November 7, 2011 06:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save everplays/1344293 to your computer and use it in GitHub Desktop.
Save everplays/1344293 to your computer and use it in GitHub Desktop.
invalid utf-8 byte sequence - browser package manager
window={};
if (typeof BPM_PLUGIN === 'undefined') BPM_PLUGIN={};
// ==========================================================================
// Project: Spade - CommonJS Runtime
// Copyright: ©2010 Strobe Inc. All rights reserved.
// License: Licened under MIT license
// ==========================================================================
/*jslint evil:true */
/*globals spade ARGS ARGV ENV __module ActiveXObject */
(function() {
var K, Sandbox, Sp, Evaluator, Ep, Loader, Lp, Spade, Tp;
// ..........................................................
// HELPER FUNCTIONS
//
K = function() {}; // noop
// assume id is already normalized
function packageIdFor(normalizedId) {
return normalizedId.slice(0, normalizedId.indexOf('/'));
}
function remap(id, contextPkg) {
var mappings = contextPkg ? contextPkg.mappings : null;
if (!mappings) { return id; }
var packageId = packageIdFor(id);
if (mappings[packageId]) {
id = mappings[packageId] + id.slice(id.indexOf('/'));
}
return id;
}
// convert a relative or otherwise de-normalized module id into canoncial form
// normalize('./foo', 'bar/baz') -> 'bar/foo'
// normalize('foo', 'bar/baz') -> 'foo/main' (or foo/~package is asPackage)
// normalize('foo/bar', 'bar/baz') -> 'foo/bar'
function normalize(id, contextId, contextPkg, _asPackage) {
var idx, len;
// slice separator off the end since it is not used...
if (id[id.length-1]==='/') { id = id.slice(0,-1); }
// need to walk if there is a .
if (id.indexOf('.')>=0) {
var parts = contextId && (id.charAt(0) ==='.') ? contextId.split('/') : [],
part, next,
packageName = parts[0],
needsCleanup = false;
idx = 0;
len = id.length;
if (contextPkg && contextPkg.main && contextId === packageName+'/main') {
// If we're requiring from main we need to handle relative requires specially
needsCleanup = true;
parts = contextPkg.main.replace(/^\.?\//, '').split('/');
}
parts.pop(); // get rid of the last path element since it is a module.
while(idx<len) {
next = id.indexOf('/', idx);
if (next<0) { next = len; }
part = id.slice(idx, next);
if (part==='..') { parts.pop(); }
else if (part!=='.' && part!=='' && part!==null) { parts.push(part); }
// skip .., empty, and null.
idx = next+1;
}
id = parts.join('/');
if (needsCleanup) {
var libPaths = contextPkg.directories.lib;
for (idx=0,len=libPaths.length; idx<len; idx++){
id = id.replace(libPaths[idx].replace(/^\.?\//, '')+'/', '');
}
id = packageName+'/'+id;
}
// else, just slice off beginning '/' if needed
} else if (id[0]==='/') { id = id.slice(1); }
// if we end up with no separators, make this a pkg
if (id.indexOf('/')<0) { id = id+(_asPackage ? '/~package' : '/main'); }
// slice separators off begin and end
if (id[0]==='/') { id = id.slice(1); }
// Remove unnecessary ~lib references
id = id.replace('~lib/', '');
return remap(id, contextPkg);
}
// ..........................................................
// SANDBOX - you could make a secure version if you want
//
// runs a factory within context and returns exports...
function execFactory(id, factory, sandbox, spade) {
var require, mod, factoryData, fullId;
var filename = factory.filename,
ARGV = sandbox.ARGV,
ENV = sandbox.ENV;
require = sandbox.makeRequire(id, spade);
sandbox._modules[id] = mod = {
id: id,
exports: {},
sandbox: sandbox
};
factoryData = factory.data; // extract the raw module body
// evaluate if needed - use cache so we only do it once per sandbox
if ('string' === typeof factoryData) {
if (sandbox._factories[id]) {
factoryData = sandbox._factories[id];
} else {
sandbox._loading[id] = true;
// The __evalFunc keeps IE 9 happy since it doesn't like
// unassigned anonymous functions
factoryData = sandbox.evaluate('__evalFunc = '+factoryData+'\n//@ sourceURL='+filename+'\n', filename);
sandbox._factories[id] = factoryData;
sandbox._loading[id] = false;
}
}
if ('function' === typeof factoryData) {
var ret = factoryData(require, mod.exports, mod, ARGV, ENV, filename);
if (ret !== undefined) { mod.exports = ret; } // allow return exports
} else {
mod.exports = factoryData;
}
return mod.exports;
}
/**
@constructor
Sandbox provides an isolated context for loading and running modules.
You can create new sandboxes anytime you want. If you pass true for the
isolate flag, then the sandbox will be created in a separate context if
supported on the platform. Otherwise it will share globals with the
default sandbox context.
Note that isolated sandboxes are not the same as secure sandboxes. For
example in the browser, a isolated sandbox is created using an iframe
which still exposes access to the DOM and parent environment.
Isolated sandboxes are mostly useful for testing and sharing plugin code
that might want to use different versions of packages.
@param {Spade} spade
The spade instance
@param {String} name
(Optional) name of the sandbox for debugging purposes
@param {Boolean} isolate
Set to true if you want to isolate it
@returns {Sandbox} instance
*/
Sandbox = function(spade, name, isolate) {
// name parameter is optional
if (typeof name !== 'string') {
isolate = name;
name = null;
}
if (!name) { name = '(anonymous)'; }
this.spade = spade;
this.name = name;
this.isIsolated = !!isolate;
this._factories = {}; // evaluated factories
this._loading = {}; // list of loading modules
this._modules = {}; // cached export results
this._used = {}; // to detect circular references
};
// alias this to help minifier make the page a bit smaller.
Sp = Sandbox.prototype;
Sp.toString = function() {
return '[Sandbox '+this.name+']';
};
/**
Evaluate the passed string in the Sandbox context, returning the result.
This is the primitive used to evalute string-encoded factories into
modules that can execute within a specific context.
*/
Sp.evaluate = function(code, filename) {
if (this.isDestroyed) { throw new Error("Sandbox destroyed"); }
if (!this._evaluatorInited) {
this._evaluatorInited = true;
this.spade.evaluator.setup(this);
}
return this.spade.evaluator.evaluate(code, this, filename);
};
/**
NOTE: This is a primitive form of the require() method. Usually you should
use the require() method defined in your module.
Sandbox-specific require. This is the most primitive form of require. All
other requires() pass through here.
@param {String} id
The module id you want to require.
@param {String} callingId
(Optional) The id of the module requiring the module. This is needed if
you the id you pass in might be relative.
@returns {Object} exports of the required module
*/
Sp.require = function(id, callingId) {
var spade = this.spade,
pkg, ret, factory;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
ret = this._modules[id];
if (ret) { ret = ret.exports; }
if (ret) {
// save so we can detect circular references later
if (!this._used[id]) { this._used[id] = ret; }
return ret ;
} else {
factory = spade.loadFactory(spade.resolve(id, this));
if (!factory) { throw new Error('Module '+id+' not found'); }
if (!this.ENV) { this.ENV = spade.env(); } // get at the last minute
if (!this.ARGV) { this.ARGV = spade.argv(); }
ret = execFactory(id, factory, this, spade);
if (this._used[id] && (this._used[id] !== ret)) {
throw new Error("Circular require detected for module "+id);
}
}
return ret ;
};
/**
NOTE: This is a primitive form of the exists() method. Usually you should
use the require.exists() method defined on the require() function in your
module.
Sandbox-specific test to determine if the named module exists or not.
This property only reflects what is immediately available through the
sync-loader. Using the async loader may change the return value of this
call.
@param {String} id
The module id you want to test
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@returns {Object} exports of the required module
*/
Sp.exists = function(id, callingId) {
var spade = this.spade, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
if (this._modules[id]) { return true; }
return spade.factoryExists(spade.resolve(id, this));
};
/**
NOTE: This is a primitive form of the async() method. Usually you should
use the require.async() method defined on the require() function in your
module.
Asynchronously attempts to load a module, invoking a callback if and when
the module is loaded. If the module is already defined, the callback will
be invoked immediately. Otherwise, this will use the Loader plugin on the
main spade context to attempt to load the module. If the module cannot
be loaded, the callback will be invoked with an error object as its first
parameter to inform you that it failed.
Note that the default Loader that ships with spade is not actually capable
of asynchronously loading modules, which means this method will always fail
unless the module is already present. You can use the spade-loader package
to install an async loader that will work.
@param {String} id
The module id you want to load
@param {Function} callback
A callback to invoke when the module is loaded or if the load has failed.
The calback should expect an error object (or null) as the first
parameter.
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@returns {void}
*/
Sp.async = function(id, callback, callingId) {
var spade = this.spade, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = spade.resolve(normalize(id, callingId, pkg), this);
spade.loadFactory(id, callback);
};
/**
NOTE: This is a primitive form of the url() method. Usually you should
use the require.url() method defined on the require() function in your
module.
Returns the URL of the given resource based on the settings of the named
package. This method requires the package information to include a `root`
property that defines the root URL where resources can be found.
This method is useful for finding non-JavaScript resources such as images,
video, etc.
@param {String} id
A module id form of the reference you want to load.
@param {String} ext
(Optional) and extension to append to the returned URL.
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@param {String} the computed URL.
*/
Sp.url = function(id, ext, callingId) {
var spade = this.spade, ret, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
pkg = spade.package(id);
if (!pkg) {
var packageId = packageIdFor(id)+'/~package';
if (spade.exists(packageId)) { spade.require(packageId); }
pkg = spade.package(id);
}
if (!pkg) {
throw new Error("Can't get url for non-existent package "+id);
}
if (!pkg.root) {
throw new Error('Package for '+id+' does not support urls');
}
ret = pkg.root + id.slice(id.indexOf('/'));
if (ext) { ret = ret+'.'+ext; }
return ret ;
};
Sp.isDestroyed = false;
Sp.destroy = function() {
if (!this.isDestroyed) {
this.isDestroyed = true;
this.spade.evaluator.teardown(this);
}
return this;
};
/**
Return a new require function for the normalized module ID. Normally you
would not call this method yourself but you might override it if you want
to add new API to the require() methods passed into modules.
*/
Sp.makeRequire = function(id, spade) {
var pkg = spade.package(id),
sandbox = this,
require;
require = function(moduleId) {
return sandbox.require(moduleId, id, pkg);
};
// make the require 'object' have the same API as sandbox and spade.
require.require = require;
require.exists = function(moduleId) {
return sandbox.exists(normalize(moduleId, id, pkg));
};
require.normalize = function(moduleId) {
return normalize(moduleId, id, pkg);
};
require.async = function(moduleId, callback) {
return sandbox.async(normalize(moduleId, id, pkg), callback);
};
require.sandbox = function(name, isolate) {
return spade.sandbox(name, isolate);
};
require.url = function(moduleId, ext) {
return sandbox.url(normalize(moduleId, id, pkg), ext);
};
require.id = id; // so you can tell one require from another
return require;
};
// ..........................................................
// LOADER
//
/**
@constructor
The Loader object is used to asynchronously load modules from the server.
It also provides other low-level URL resolution and event handling
functions needed to integrate with the low-level environment. The default
implementation does not support any kind of async loading. See the
spade-loader package for a way to add support for this.
*/
Loader = function() {
this._loading = {};
};
Lp = Loader.prototype;
/**
Called by spade whenever a module is requested that has not already been
registered in memory. This function should attempt to load the module if
possible, registering any packages on the spade instance.
If a `done` is a function, then this method should run asynchronously -
invoking the callback when complete. If the load failed, this method should
pass an error as the first parameter. Otherwise it should not pass any
parameter.
If `done` is null, then this method should run synchronously and then simply
return when it is complete. If the named module cannot be loaded, you can
just return with no errors as the spade environment will detect this
condition and fail.
Note that loaders are not required to support both sync and async loading.
If you don't support one or the other, simply throw an error.
@method
@param {Spade} spade
The spade instance.
@param {String} id
The normalized module id to load.
@param {Function} done
(Optional) if passed, run this function async and invoke the done callback
when complete.
@returns {void}
*/
Lp.loadFactory = null;
/**
Called by spade whenever it wants to detect if a given module exists and the
id is not yet registered with the spade instance.
This method should do its best to determine if the module exists and return
the appropriate value. Note that if you only support async loading of
modules then you may not be able to detect when a module is defined outside
of what is already registered. In this case it is OK to simply return false.
@method
@param {Spade} spade
The spade instance.
@param {String} id
The normalized module id to load
@returns {Boolean} true if module exists
*/
Lp.exists = null;
// NOTE: On ready stuff mostly stolen from jQuery 1.4. Need to incl here
// because spade will often be used to load jQuery.
// Will only be invoked once. Just be prepared to call it
/**
Called once by spade on page load to schedule a ready callback, which should
be invoked once the documents 'ready' event (or an equivalent) is fired.
You should never call this method yourself but you might override it when
using spade outside of a proper browser.
@param {Function} callback
The callback to be invoked when the document is 'ready'.
@returns {void}
*/
Lp.scheduleReady = function(callback) {
// handle case where ready is invoked AFTER the document is already ready
if ( document.readyState === "complete" ) { return setTimeout(callback, 1); }
var handler, handled = false;
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if (handled) { return; }
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
handler();
}
// Mozilla, Opera and webkit nightlies currently support this event
if (document.addEventListener) {
handler = function() {
if (handled) { return; }
handled = true;
document.removeEventListener("DOMContentLoaded", handler, false);
window.removeEventListener('load', handler, false);
callback();
};
document.addEventListener( "DOMContentLoaded", handler, false);
// A fallback to window.onload, that will always work
window.addEventListener( "load", handler, false );
// If IE event model is used
} else if ( document.attachEvent ) {
handler = function() {
if (!handled && document.readyState === "complete") {
handled = true;
document.detachEvent( "onreadystatechange", handler );
window.detachEvent('onload', handler);
callback();
}
};
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", handler);
// A fallback to window.onload, that will always work
window.attachEvent( "onload", handler);
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement === null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); }
}
};
// ..........................................................
// Evaluator Class
//
/**
@constructor
An Evaluator instance is used to evaluate code inside of a sandbox. A
default instance is created on spade and used automatically by sandboxes.
You can extend this class and replace the default one on spade in order to
provide additional new features, such as sandbox isolation or secure eval.
The default Evaluator simply evals code in the current context using the
built-in eval() function. It does not support isolated sandboxes. To add
isolated sandbox support, add the `spade-isolate` package.
*/
Evaluator = function() {};
Ep = Evaluator.prototype;
/**
Called once on each new sandbox to allow the evaluator to setup any required
context for future calls. For isolated sandboxes, this is usually where
you would create the new compilation context and store it on the sandbox for
future use.
The default implementation does nothing, but will throw an exception if you
try to setup a new isolated sandbox. (Since the feature is not supported.).
If you override this method, you do not need to call the default function.
@param {Sandbox} sandbox
The sandbox to setup.
@returns {void}
*/
Ep.setup = function(sandbox) {
if (sandbox.isIsolated) {
throw new Error("Isolated sandboxes are not supported.");
}
};
/**
Evaluates the passed JavaScript within the context of a sandbox and returns
the resulting value (usually a function). The default version simply calls
the built-in eval().
@param {String} text
The code to evaluate.
@param {Sandbox} sandbox
The sandbox owning the code.
@param {String} filename
An optional filename to associate with the text (may be useful for debug
support)
@returns {Object} evaluated result.
*/
Ep.evaluate = function(text, sandbox, filename) {
return eval(text);
};
/**
Called once by the sandbox when it is destroyed to allow the evaluator to
cleanup any data it might have stashed on the sandbox. For isolated
sandboxes, this method might destroy the compilation context to allow its
memory to be reclaimed.
Since the default evaluator does not support isolated contexts, this method
is a no-op.
@param {Sandbox} sandbox
The sandbox about to be destroyed.
@returns {void}
*/
Ep.teardown = function(sandbox) {
// noop by default
};
// ..........................................................
// Spade Class - defined so we can recreate
//
/**
@constructor
The root object used to coordinate the entire spade environment. A global
instance of this class is created on page load called `spade`. Most of the
time you will only interact with this object directly to register new
modules and perhaps to load a new module outside of traditional module code.
Note that if you are using BPM and your app is actually published as modules
then you won't actually need reference this object at all as the details are
handled for you.
# Registering a Module
If you are manually constructing a JavaScript file to load from the server
and you want to register new modules, you will need to use the
`spade.register()` method:
spade.register('package_name/module_name', function() { ... });
This will make the module `package_name/module_name` available to all other
modules. The first time the module is required, your passed function will
be called.
You can also register metadata about a package by registering the
`package_name/~package` module:
spade.register('package_name/~package', {
"name": "package_name",
"version": "1.0.0",
...
});
Note that in addition to factory functions you can also pass in JSON hashes
(which will simply be returned directory) or a string of code - which will
be eval'd on demand.
The string format is particularly important because defining modules as
strings can dramatically improve load time on mobile devices while also
allowing you to easily support isolated sandbox contexts.
# Requiring a Module
Normally when you write module code that is managed by Spade you will have
a `require()` method defined within the module that you should use to load
modules.
If you happen to be writing code outside of a spade module and need to
require a module, however, you can use the `spade.require()` method instead:
var jQuery = spade.require('jquery');
This works just like the built-in require method except it will not support
relative modules (since there is no module to be relative too). This
method will require modules from the default sandbox, found at
`spade.defaultSandbox`.
# Plugins
Spade supports a number of plugins that you can use to enhance the way
spade discovers and loads modules. The two plugins currently supported are
a `loader` and `evaluator`.
The `loader` plugin is used to asynchronously discover and load modules. It
expects the object to be an instance of Spade.Loader. See `Loader`
documentation for more information.
The `evaluator` plugin is used to evaluate code within a sandbox context. It
can be enhanced to support isolated sandboxes as well as worker threads and
many other contexts. See the `Evaluator` documentation for more
information.
*/
Spade = function() {
this.loader = new this.Loader(this);
this.evaluator = new this.Evaluator(this);
this.defaultSandbox = this.sandbox();
this._factories = {};
this._packages = {};
};
Tp = Spade.prototype;
Tp.VERSION = "1.0.0";
// expose the classes. We do it this way so that you can create a new
// Spade instance and treat it like the spade module
Tp.Spade = Spade;
Tp.Sandbox = Sandbox;
Tp.Loader = Loader;
Tp.Evaluator = Evaluator;
/**
Computes and returns a normalized ENV hash. By default this will look for
a globally defined variable called `ENV` and use that. If not defined,
it will look for a locally defined `ENV` variable instead.
In either case, this method will also normalize the variable to include at
least the `LANG` and `SPADE_PLATFORM` properties.
@returns {Hash} the environment hash
*/
Tp.env = function() {
var env = this.ENV;
if (!env) { this.ENV = env = ('undefined' !== typeof ENV) ? ENV : {}; }
if (!env.SPADE_PLATFORM) { env.SPADE_PLATFORM = 'browser'; }
if (!env.LANG) {
env.LANG = ('undefined' !== typeof navigator) ? navigator.language : 'en-US';
}
return env;
};
/**
Computes and returns the ARGV array for the current spade environment. By
default this will look for a globally defined variable called `ARGV` and
use that.
ARGV is a useful way to pass in startup options to spade modules.
@returns {Array} the argv array
*/
Tp.argv = function() {
var argv = this.ARGV;
if (!argv) { argv= this.ARGV = ('undefined' !== typeof ARGV) ? ARGV : []; }
return argv;
};
/**
Restores original values after a call to `spade.globalize()`. If you call
this method more than once it will have no effect.
@returns {void}
*/
Tp.noConflict = function() {
var c = this._conflict;
if (c) {
delete this._conflict;
spade = this._conflict;
}
return this;
};
/**
Returns a new sandbox instance attached to the current spade instance.
If you pass true for the `isolate` parameter, the new sandbox will attempt
to load its code in an isolated compilation context (possibly using an
iframe in browsers). Note that isolated sandboxes are not supported by
default. Include the spade-isolate package instead.
@param {String} name
(Optional) name for the sandbox for debugging purposes.
@param {Boolean} isolate
true if you want the sandbox to be isolated. Throws exception if
platform cannot isolate.
@returns {Sandbox} sandbox instance
*/
Tp.sandbox = function(name, isolate) {
return new this.Sandbox(this, name, isolate);
};
/**
Register a module or package information. You can pass one of the
following:
'module/id', 'module body string'
'module/id', function() { module func }
'module/id', { exports: 'foo' }
'module/id' - just register module id and no body to indicate presence
Note also that if you pass just a packageId, it will be normalized to
packageId/~package. This is how you register a package.
@param {String} id
The module or package id
@param {String|Function|Hash} data
A module function, module body (as string), or hash of exports to use.
@param {String} opts
Additional metadata only if you are registering a module factory. Known
keys include 'filename' and 'format' (for compilation of DSLs).
@returns {void}
*/
Tp.register = function(id, data, opts) {
if (!data) { data = K ; }
var t = typeof data, isExtern, factory, isPkg;
id = normalize(id, null, null, true);
isPkg = id.slice(-9) === '/~package';
// register - note packages can only accept hashes
if (isPkg && 'object'!==typeof data) {
throw new Error('You can only register hashes for packages');
}
// Set some package defaults
if (isPkg) {
if (!data.directories) { data.directories = {}; }
if (!data.directories.lib) {
data.directories.lib = ['lib'];
} else if (typeof data.directories.lib === 'string') {
data.directories.lib = [data.directories.lib];
}
}
factory = { data: data };
factory.filename = opts && opts.filename ? opts.filename : id;
// Store with generic id if none, or if JS
this._factories[id] = factory;
return this;
};
/**
Efficient way to register external packages. Pass a hash of packageIds
and source URLs. If the package is already registered, the extern will
not replace it so this is safe to call multiple times.
@param {Hash} externs
A hash of package names and package settings.
@returns {void}
*/
Tp.externs = function(externs, extern) {
var tmp, packages = this._packages;
// normalize method call.
if ('string' === typeof externs) {
tmp = {};
tmp[externs] = extern;
externs = tmp;
extern = null;
}
for(var packageId in externs) {
if (!externs.hasOwnProperty(packageId)) { continue; }
if (packages[packageId] && !packages[packageId].extern) { continue; }
extern = externs[packageId];
if ('string' === typeof extern) { extern = {name: packageId, src: extern}; }
extern.extern = true;
this.register(packageId, extern);
}
};
/**
Require a module from the default sandbox.
@param {String} id
The module id.
@returns {Hash} module exports
*/
Tp.require = function(id) {
return this.defaultSandbox.require(id, this.defaultSandbox.callerId);
};
/**
Async load a module if it is not already a registered factory. Invoke
the passed callback with an optional error object when the module is
ready to load.
*/
Tp.async = function(id, callback) {
return this.defaultSandbox.async(id, callback);
};
/**
Returns true if the passed module exists in the default sandbox.
@param {String} id
The module id to check.
@returns {Boolean} true if module id exists
*/
Tp.exists = function(id) {
return this.defaultSandbox.exists(id);
};
/**
Returns the URL for a resource matching the passed module id and optional
extension.
@param {String} id
the module id to resolve
@param {String} ext
(Optional) extension to append to URL
@returns {String} url
*/
Tp.url = function(id, ext) {
return this.defaultSandbox.url(id, ext);
};
/**
Called by the sandbox to get a factory object for the named moduleId.
Normally you will not need to call this method directly or even override it.
@param {String} id
Fully normalized module id
@param {Function} callback
(Optional) callback to invoke once factory is loaded. If not passed, this
method will run sync. Otherwise it will run async.
@returns {Hash} factory hash.
*/
Tp.loadFactory = function(id, callback) {
var ret = this._factories[id],
loader = this.loader;
if (callback) {
if (!ret) {
if (loader && loader.loadFactory) {
loader.loadFactory(this, id, callback);
} else { callback(new Error('Module '+id+' not found')); }
} else { callback(); }
} else if (!ret && loader && loader.loadFactory) {
loader.loadFactory(this, id);
ret = this._factories[id];
}
return ret ;
};
/**
Called by the sandbox to determine if the named id exists on the system.
The id should already be normalized. If the id is not yet registered, the
loader will also be consulted.
Normally you will not need to call this method directly or override it.
@param {String} id
Fully normalized module id
@returns {Boolean} true if factory exists
*/
Tp.factoryExists = function(id) {
if (this._factories[id]) { return true; }
var loader = this.loader;
return loader && loader.exists && loader.exists(this, id);
};
/**
Returns the package info, if any, for the named module or packageId
@param {String} id
A package name or fully normalized module id.
@returns {Hash} package info or null if package is not registered
*/
Tp.package = function(id) {
id = packageIdFor(normalize(id))+'/~package';
var ret = this._factories[id];
return ret ? ret.data : null;
};
/**
Normalize a moduleId, expanding relative values if needed.
@param {String} id
The module id, possibly de-normalized.
@param {String} contextId
(Optional) The normalized module id of the calling module. Required if
your module id might be relative.
@returns {String} the normalized module id
*/
Tp.normalize = function(id, contextId) {
return normalize(id, contextId);
};
/**
Maps the passed module id to a potentially location specific module id.
This gives the loader a way to vary the factory function returns for a given
module id per sandbox. Useful when supporting multiple versions of the
same package.
@param {String} id
Normalized module id
@param {Sandbox} sandbox
The requesting sandbox
@returns {String} resolved module id
*/
Tp.resolve = function(id, sandbox) {
var loader = this.loader;
return sandbox && loader && loader.resolve ? loader.resolve(id, sandbox):id;
};
/**
Invokes the passed callback when the browser is ready. This will work
regardless of the environment you are in.
@param {Function} callback
Invoked when the browser is ready. If browser is alrady ready, invoked
immediately.
@returns {void}
*/
Tp.ready = function(callback) {
switch(this.readyState) {
case 'ready':
callback();
break;
case 'scheduled':
this._readyQueue.push(callback);
break;
default:
this._readyQueue = [callback];
this.readyState = 'scheduled';
if (this.loader.scheduleReady) {
var that = this;
this.loader.scheduleReady(function() {
var queue = that._readyQueue, len = queue ? queue.length : 0;
that._readyQueue = null;
that.readyState = 'ready';
for(var idx=0;idx<len;idx++) { queue[idx](); }
});
} else {
throw new Error('Loader does not support activate on ready state');
}
}
};
// instantiate spade and also attach class for testing
var newSpade = new Spade();
if ('undefined' !== typeof spade) newSpade._conflict = spade;
spade = newSpade;
// make this work when called as a module - both from within spade and from
// node.
if ('undefined' !== typeof require) {
if ('undefined' !== typeof __module) { __module.exports = spade; }
else if ('undefined' !== typeof module) { module.exports = spade; }
}
})();
spade.register("uglify-js/parse-js", "(function(require, exports, __module, ARGV, ENV, __filename){/***********************************************************************\n\n A JavaScript tokenizer / parser / beautifier / compressor.\n\n This version is suitable for Node.js. With minimal changes (the\n exports stuff) it should work on any JS platform.\n\n This file contains the tokenizer/parser. It is a port to JavaScript\n of parse-js [1], a JavaScript parser library written in Common Lisp\n by Marijn Haverbeke. Thank you Marijn!\n\n [1] http://marijn.haverbeke.nl/parse-js/\n\n Exported functions:\n\n - tokenizer(code) -- returns a function. Call the returned\n function to fetch the next token.\n\n - parse(code) -- returns an AST of the given JavaScript code.\n\n -------------------------------- (C) ---------------------------------\n\n Author: Mihai Bazon\n <mihai.bazon@gmail.com>\n http://mihai.bazon.net/blog\n\n Distributed under the BSD license:\n\n Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n Based on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n\n * Redistributions of source code must retain the above\n copyright notice, this list of conditions and the following\n disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials\n provided with the distribution.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER â\u0080\u009cAS ISâ\u0080\u009d AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n SUCH DAMAGE.\n\n ***********************************************************************/\n\n/* -----[ Tokenizer (constants) ]----- */\n\n\nvar KEYWORDS = array_to_hash([\n \"break\",\n \"case\",\n \"catch\",\n \"const\",\n \"continue\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"in\",\n \"instanceof\",\n \"new\",\n \"return\",\n \"switch\",\n \"throw\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\"\n]);\n\nvar RESERVED_WORDS = array_to_hash([\n \"abstract\",\n \"boolean\",\n \"byte\",\n \"char\",\n \"class\",\n \"debugger\",\n \"double\",\n \"enum\",\n \"export\",\n \"extends\",\n \"final\",\n \"float\",\n \"goto\",\n \"implements\",\n \"import\",\n \"int\",\n \"interface\",\n \"long\",\n \"native\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"short\",\n \"static\",\n \"super\",\n \"synchronized\",\n \"throws\",\n \"transient\",\n \"volatile\"\n]);\n\nvar KEYWORDS_BEFORE_EXPRESSION = array_to_hash([\n \"return\",\n \"new\",\n \"delete\",\n \"throw\",\n \"else\",\n \"case\"\n]);\n\nvar KEYWORDS_ATOM = array_to_hash([\n \"false\",\n \"null\",\n \"true\",\n \"undefined\"\n]);\n\nvar OPERATOR_CHARS = array_to_hash(characters(\"+-*&%=<>!?|~^\"));\n\nvar RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;\nvar RE_OCT_NUMBER = /^0[0-7]+$/;\nvar RE_DEC_NUMBER = /^\\d*\\.?\\d*(?:e[+-]?\\d*(?:\\d\\.?|\\.?\\d)\\d*)?$/i;\n\nvar OPERATORS = array_to_hash([\n \"in\",\n \"instanceof\",\n \"typeof\",\n \"new\",\n \"void\",\n \"delete\",\n \"++\",\n \"--\",\n \"+\",\n \"-\",\n \"!\",\n \"~\",\n \"&\",\n \"|\",\n \"^\",\n \"*\",\n \"/\",\n \"%\",\n \">>\",\n \"<<\",\n \">>>\",\n \"<\",\n \">\",\n \"<=\",\n \">=\",\n \"==\",\n \"===\",\n \"!=\",\n \"!==\",\n \"?\",\n \"=\",\n \"+=\",\n \"-=\",\n \"/=\",\n \"*=\",\n \"%=\",\n \">>=\",\n \"<<=\",\n \">>>=\",\n \"|=\",\n \"^=\",\n \"&=\",\n \"&&\",\n \"||\"\n]);\n\nvar WHITESPACE_CHARS = array_to_hash(characters(\" \\u00a0\\n\\r\\t\\f\\u000b\\u200b\"));\n\nvar PUNC_BEFORE_EXPRESSION = array_to_hash(characters(\"[{}(,.;:\"));\n\nvar PUNC_CHARS = array_to_hash(characters(\"[]{}(),;:\"));\n\nvar REGEXP_MODIFIERS = array_to_hash(characters(\"gmsiy\"));\n\n/* -----[ Tokenizer ]----- */\n\n// regexps adapted from http://xregexp.com/plugins/#unicode\nvar UNICODE = {\n letter: new RegExp(\"[\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02C1\\\\u02C6-\\\\u02D1\\\\u02E0-\\\\u02E4\\\\u02EC\\\\u02EE\\\\u0370-\\\\u0374\\\\u0376\\\\u0377\\\\u037A-\\\\u037D\\\\u0386\\\\u0388-\\\\u038A\\\\u038C\\\\u038E-\\\\u03A1\\\\u03A3-\\\\u03F5\\\\u03F7-\\\\u0481\\\\u048A-\\\\u0523\\\\u0531-\\\\u0556\\\\u0559\\\\u0561-\\\\u0587\\\\u05D0-\\\\u05EA\\\\u05F0-\\\\u05F2\\\\u0621-\\\\u064A\\\\u066E\\\\u066F\\\\u0671-\\\\u06D3\\\\u06D5\\\\u06E5\\\\u06E6\\\\u06EE\\\\u06EF\\\\u06FA-\\\\u06FC\\\\u06FF\\\\u0710\\\\u0712-\\\\u072F\\\\u074D-\\\\u07A5\\\\u07B1\\\\u07CA-\\\\u07EA\\\\u07F4\\\\u07F5\\\\u07FA\\\\u0904-\\\\u0939\\\\u093D\\\\u0950\\\\u0958-\\\\u0961\\\\u0971\\\\u0972\\\\u097B-\\\\u097F\\\\u0985-\\\\u098C\\\\u098F\\\\u0990\\\\u0993-\\\\u09A8\\\\u09AA-\\\\u09B0\\\\u09B2\\\\u09B6-\\\\u09B9\\\\u09BD\\\\u09CE\\\\u09DC\\\\u09DD\\\\u09DF-\\\\u09E1\\\\u09F0\\\\u09F1\\\\u0A05-\\\\u0A0A\\\\u0A0F\\\\u0A10\\\\u0A13-\\\\u0A28\\\\u0A2A-\\\\u0A30\\\\u0A32\\\\u0A33\\\\u0A35\\\\u0A36\\\\u0A38\\\\u0A39\\\\u0A59-\\\\u0A5C\\\\u0A5E\\\\u0A72-\\\\u0A74\\\\u0A85-\\\\u0A8D\\\\u0A8F-\\\\u0A91\\\\u0A93-\\\\u0AA8\\\\u0AAA-\\\\u0AB0\\\\u0AB2\\\\u0AB3\\\\u0AB5-\\\\u0AB9\\\\u0ABD\\\\u0AD0\\\\u0AE0\\\\u0AE1\\\\u0B05-\\\\u0B0C\\\\u0B0F\\\\u0B10\\\\u0B13-\\\\u0B28\\\\u0B2A-\\\\u0B30\\\\u0B32\\\\u0B33\\\\u0B35-\\\\u0B39\\\\u0B3D\\\\u0B5C\\\\u0B5D\\\\u0B5F-\\\\u0B61\\\\u0B71\\\\u0B83\\\\u0B85-\\\\u0B8A\\\\u0B8E-\\\\u0B90\\\\u0B92-\\\\u0B95\\\\u0B99\\\\u0B9A\\\\u0B9C\\\\u0B9E\\\\u0B9F\\\\u0BA3\\\\u0BA4\\\\u0BA8-\\\\u0BAA\\\\u0BAE-\\\\u0BB9\\\\u0BD0\\\\u0C05-\\\\u0C0C\\\\u0C0E-\\\\u0C10\\\\u0C12-\\\\u0C28\\\\u0C2A-\\\\u0C33\\\\u0C35-\\\\u0C39\\\\u0C3D\\\\u0C58\\\\u0C59\\\\u0C60\\\\u0C61\\\\u0C85-\\\\u0C8C\\\\u0C8E-\\\\u0C90\\\\u0C92-\\\\u0CA8\\\\u0CAA-\\\\u0CB3\\\\u0CB5-\\\\u0CB9\\\\u0CBD\\\\u0CDE\\\\u0CE0\\\\u0CE1\\\\u0D05-\\\\u0D0C\\\\u0D0E-\\\\u0D10\\\\u0D12-\\\\u0D28\\\\u0D2A-\\\\u0D39\\\\u0D3D\\\\u0D60\\\\u0D61\\\\u0D7A-\\\\u0D7F\\\\u0D85-\\\\u0D96\\\\u0D9A-\\\\u0DB1\\\\u0DB3-\\\\u0DBB\\\\u0DBD\\\\u0DC0-\\\\u0DC6\\\\u0E01-\\\\u0E30\\\\u0E32\\\\u0E33\\\\u0E40-\\\\u0E46\\\\u0E81\\\\u0E82\\\\u0E84\\\\u0E87\\\\u0E88\\\\u0E8A\\\\u0E8D\\\\u0E94-\\\\u0E97\\\\u0E99-\\\\u0E9F\\\\u0EA1-\\\\u0EA3\\\\u0EA5\\\\u0EA7\\\\u0EAA\\\\u0EAB\\\\u0EAD-\\\\u0EB0\\\\u0EB2\\\\u0EB3\\\\u0EBD\\\\u0EC0-\\\\u0EC4\\\\u0EC6\\\\u0EDC\\\\u0EDD\\\\u0F00\\\\u0F40-\\\\u0F47\\\\u0F49-\\\\u0F6C\\\\u0F88-\\\\u0F8B\\\\u1000-\\\\u102A\\\\u103F\\\\u1050-\\\\u1055\\\\u105A-\\\\u105D\\\\u1061\\\\u1065\\\\u1066\\\\u106E-\\\\u1070\\\\u1075-\\\\u1081\\\\u108E\\\\u10A0-\\\\u10C5\\\\u10D0-\\\\u10FA\\\\u10FC\\\\u1100-\\\\u1159\\\\u115F-\\\\u11A2\\\\u11A8-\\\\u11F9\\\\u1200-\\\\u1248\\\\u124A-\\\\u124D\\\\u1250-\\\\u1256\\\\u1258\\\\u125A-\\\\u125D\\\\u1260-\\\\u1288\\\\u128A-\\\\u128D\\\\u1290-\\\\u12B0\\\\u12B2-\\\\u12B5\\\\u12B8-\\\\u12BE\\\\u12C0\\\\u12C2-\\\\u12C5\\\\u12C8-\\\\u12D6\\\\u12D8-\\\\u1310\\\\u1312-\\\\u1315\\\\u1318-\\\\u135A\\\\u1380-\\\\u138F\\\\u13A0-\\\\u13F4\\\\u1401-\\\\u166C\\\\u166F-\\\\u1676\\\\u1681-\\\\u169A\\\\u16A0-\\\\u16EA\\\\u1700-\\\\u170C\\\\u170E-\\\\u1711\\\\u1720-\\\\u1731\\\\u1740-\\\\u1751\\\\u1760-\\\\u176C\\\\u176E-\\\\u1770\\\\u1780-\\\\u17B3\\\\u17D7\\\\u17DC\\\\u1820-\\\\u1877\\\\u1880-\\\\u18A8\\\\u18AA\\\\u1900-\\\\u191C\\\\u1950-\\\\u196D\\\\u1970-\\\\u1974\\\\u1980-\\\\u19A9\\\\u19C1-\\\\u19C7\\\\u1A00-\\\\u1A16\\\\u1B05-\\\\u1B33\\\\u1B45-\\\\u1B4B\\\\u1B83-\\\\u1BA0\\\\u1BAE\\\\u1BAF\\\\u1C00-\\\\u1C23\\\\u1C4D-\\\\u1C4F\\\\u1C5A-\\\\u1C7D\\\\u1D00-\\\\u1DBF\\\\u1E00-\\\\u1F15\\\\u1F18-\\\\u1F1D\\\\u1F20-\\\\u1F45\\\\u1F48-\\\\u1F4D\\\\u1F50-\\\\u1F57\\\\u1F59\\\\u1F5B\\\\u1F5D\\\\u1F5F-\\\\u1F7D\\\\u1F80-\\\\u1FB4\\\\u1FB6-\\\\u1FBC\\\\u1FBE\\\\u1FC2-\\\\u1FC4\\\\u1FC6-\\\\u1FCC\\\\u1FD0-\\\\u1FD3\\\\u1FD6-\\\\u1FDB\\\\u1FE0-\\\\u1FEC\\\\u1FF2-\\\\u1FF4\\\\u1FF6-\\\\u1FFC\\\\u2071\\\\u207F\\\\u2090-\\\\u2094\\\\u2102\\\\u2107\\\\u210A-\\\\u2113\\\\u2115\\\\u2119-\\\\u211D\\\\u2124\\\\u2126\\\\u2128\\\\u212A-\\\\u212D\\\\u212F-\\\\u2139\\\\u213C-\\\\u213F\\\\u2145-\\\\u2149\\\\u214E\\\\u2183\\\\u2184\\\\u2C00-\\\\u2C2E\\\\u2C30-\\\\u2C5E\\\\u2C60-\\\\u2C6F\\\\u2C71-\\\\u2C7D\\\\u2C80-\\\\u2CE4\\\\u2D00-\\\\u2D25\\\\u2D30-\\\\u2D65\\\\u2D6F\\\\u2D80-\\\\u2D96\\\\u2DA0-\\\\u2DA6\\\\u2DA8-\\\\u2DAE\\\\u2DB0-\\\\u2DB6\\\\u2DB8-\\\\u2DBE\\\\u2DC0-\\\\u2DC6\\\\u2DC8-\\\\u2DCE\\\\u2DD0-\\\\u2DD6\\\\u2DD8-\\\\u2DDE\\\\u2E2F\\\\u3005\\\\u3006\\\\u3031-\\\\u3035\\\\u303B\\\\u303C\\\\u3041-\\\\u3096\\\\u309D-\\\\u309F\\\\u30A1-\\\\u30FA\\\\u30FC-\\\\u30FF\\\\u3105-\\\\u312D\\\\u3131-\\\\u318E\\\\u31A0-\\\\u31B7\\\\u31F0-\\\\u31FF\\\\u3400\\\\u4DB5\\\\u4E00\\\\u9FC3\\\\uA000-\\\\uA48C\\\\uA500-\\\\uA60C\\\\uA610-\\\\uA61F\\\\uA62A\\\\uA62B\\\\uA640-\\\\uA65F\\\\uA662-\\\\uA66E\\\\uA67F-\\\\uA697\\\\uA717-\\\\uA71F\\\\uA722-\\\\uA788\\\\uA78B\\\\uA78C\\\\uA7FB-\\\\uA801\\\\uA803-\\\\uA805\\\\uA807-\\\\uA80A\\\\uA80C-\\\\uA822\\\\uA840-\\\\uA873\\\\uA882-\\\\uA8B3\\\\uA90A-\\\\uA925\\\\uA930-\\\\uA946\\\\uAA00-\\\\uAA28\\\\uAA40-\\\\uAA42\\\\uAA44-\\\\uAA4B\\\\uAC00\\\\uD7A3\\\\uF900-\\\\uFA2D\\\\uFA30-\\\\uFA6A\\\\uFA70-\\\\uFAD9\\\\uFB00-\\\\uFB06\\\\uFB13-\\\\uFB17\\\\uFB1D\\\\uFB1F-\\\\uFB28\\\\uFB2A-\\\\uFB36\\\\uFB38-\\\\uFB3C\\\\uFB3E\\\\uFB40\\\\uFB41\\\\uFB43\\\\uFB44\\\\uFB46-\\\\uFBB1\\\\uFBD3-\\\\uFD3D\\\\uFD50-\\\\uFD8F\\\\uFD92-\\\\uFDC7\\\\uFDF0-\\\\uFDFB\\\\uFE70-\\\\uFE74\\\\uFE76-\\\\uFEFC\\\\uFF21-\\\\uFF3A\\\\uFF41-\\\\uFF5A\\\\uFF66-\\\\uFFBE\\\\uFFC2-\\\\uFFC7\\\\uFFCA-\\\\uFFCF\\\\uFFD2-\\\\uFFD7\\\\uFFDA-\\\\uFFDC]\"),\n non_spacing_mark: new RegExp(\"[\\\\u0300-\\\\u036F\\\\u0483-\\\\u0487\\\\u0591-\\\\u05BD\\\\u05BF\\\\u05C1\\\\u05C2\\\\u05C4\\\\u05C5\\\\u05C7\\\\u0610-\\\\u061A\\\\u064B-\\\\u065E\\\\u0670\\\\u06D6-\\\\u06DC\\\\u06DF-\\\\u06E4\\\\u06E7\\\\u06E8\\\\u06EA-\\\\u06ED\\\\u0711\\\\u0730-\\\\u074A\\\\u07A6-\\\\u07B0\\\\u07EB-\\\\u07F3\\\\u0816-\\\\u0819\\\\u081B-\\\\u0823\\\\u0825-\\\\u0827\\\\u0829-\\\\u082D\\\\u0900-\\\\u0902\\\\u093C\\\\u0941-\\\\u0948\\\\u094D\\\\u0951-\\\\u0955\\\\u0962\\\\u0963\\\\u0981\\\\u09BC\\\\u09C1-\\\\u09C4\\\\u09CD\\\\u09E2\\\\u09E3\\\\u0A01\\\\u0A02\\\\u0A3C\\\\u0A41\\\\u0A42\\\\u0A47\\\\u0A48\\\\u0A4B-\\\\u0A4D\\\\u0A51\\\\u0A70\\\\u0A71\\\\u0A75\\\\u0A81\\\\u0A82\\\\u0ABC\\\\u0AC1-\\\\u0AC5\\\\u0AC7\\\\u0AC8\\\\u0ACD\\\\u0AE2\\\\u0AE3\\\\u0B01\\\\u0B3C\\\\u0B3F\\\\u0B41-\\\\u0B44\\\\u0B4D\\\\u0B56\\\\u0B62\\\\u0B63\\\\u0B82\\\\u0BC0\\\\u0BCD\\\\u0C3E-\\\\u0C40\\\\u0C46-\\\\u0C48\\\\u0C4A-\\\\u0C4D\\\\u0C55\\\\u0C56\\\\u0C62\\\\u0C63\\\\u0CBC\\\\u0CBF\\\\u0CC6\\\\u0CCC\\\\u0CCD\\\\u0CE2\\\\u0CE3\\\\u0D41-\\\\u0D44\\\\u0D4D\\\\u0D62\\\\u0D63\\\\u0DCA\\\\u0DD2-\\\\u0DD4\\\\u0DD6\\\\u0E31\\\\u0E34-\\\\u0E3A\\\\u0E47-\\\\u0E4E\\\\u0EB1\\\\u0EB4-\\\\u0EB9\\\\u0EBB\\\\u0EBC\\\\u0EC8-\\\\u0ECD\\\\u0F18\\\\u0F19\\\\u0F35\\\\u0F37\\\\u0F39\\\\u0F71-\\\\u0F7E\\\\u0F80-\\\\u0F84\\\\u0F86\\\\u0F87\\\\u0F90-\\\\u0F97\\\\u0F99-\\\\u0FBC\\\\u0FC6\\\\u102D-\\\\u1030\\\\u1032-\\\\u1037\\\\u1039\\\\u103A\\\\u103D\\\\u103E\\\\u1058\\\\u1059\\\\u105E-\\\\u1060\\\\u1071-\\\\u1074\\\\u1082\\\\u1085\\\\u1086\\\\u108D\\\\u109D\\\\u135F\\\\u1712-\\\\u1714\\\\u1732-\\\\u1734\\\\u1752\\\\u1753\\\\u1772\\\\u1773\\\\u17B7-\\\\u17BD\\\\u17C6\\\\u17C9-\\\\u17D3\\\\u17DD\\\\u180B-\\\\u180D\\\\u18A9\\\\u1920-\\\\u1922\\\\u1927\\\\u1928\\\\u1932\\\\u1939-\\\\u193B\\\\u1A17\\\\u1A18\\\\u1A56\\\\u1A58-\\\\u1A5E\\\\u1A60\\\\u1A62\\\\u1A65-\\\\u1A6C\\\\u1A73-\\\\u1A7C\\\\u1A7F\\\\u1B00-\\\\u1B03\\\\u1B34\\\\u1B36-\\\\u1B3A\\\\u1B3C\\\\u1B42\\\\u1B6B-\\\\u1B73\\\\u1B80\\\\u1B81\\\\u1BA2-\\\\u1BA5\\\\u1BA8\\\\u1BA9\\\\u1C2C-\\\\u1C33\\\\u1C36\\\\u1C37\\\\u1CD0-\\\\u1CD2\\\\u1CD4-\\\\u1CE0\\\\u1CE2-\\\\u1CE8\\\\u1CED\\\\u1DC0-\\\\u1DE6\\\\u1DFD-\\\\u1DFF\\\\u20D0-\\\\u20DC\\\\u20E1\\\\u20E5-\\\\u20F0\\\\u2CEF-\\\\u2CF1\\\\u2DE0-\\\\u2DFF\\\\u302A-\\\\u302F\\\\u3099\\\\u309A\\\\uA66F\\\\uA67C\\\\uA67D\\\\uA6F0\\\\uA6F1\\\\uA802\\\\uA806\\\\uA80B\\\\uA825\\\\uA826\\\\uA8C4\\\\uA8E0-\\\\uA8F1\\\\uA926-\\\\uA92D\\\\uA947-\\\\uA951\\\\uA980-\\\\uA982\\\\uA9B3\\\\uA9B6-\\\\uA9B9\\\\uA9BC\\\\uAA29-\\\\uAA2E\\\\uAA31\\\\uAA32\\\\uAA35\\\\uAA36\\\\uAA43\\\\uAA4C\\\\uAAB0\\\\uAAB2-\\\\uAAB4\\\\uAAB7\\\\uAAB8\\\\uAABE\\\\uAABF\\\\uAAC1\\\\uABE5\\\\uABE8\\\\uABED\\\\uFB1E\\\\uFE00-\\\\uFE0F\\\\uFE20-\\\\uFE26]\"),\n space_combining_mark: new RegExp(\"[\\\\u0903\\\\u093E-\\\\u0940\\\\u0949-\\\\u094C\\\\u094E\\\\u0982\\\\u0983\\\\u09BE-\\\\u09C0\\\\u09C7\\\\u09C8\\\\u09CB\\\\u09CC\\\\u09D7\\\\u0A03\\\\u0A3E-\\\\u0A40\\\\u0A83\\\\u0ABE-\\\\u0AC0\\\\u0AC9\\\\u0ACB\\\\u0ACC\\\\u0B02\\\\u0B03\\\\u0B3E\\\\u0B40\\\\u0B47\\\\u0B48\\\\u0B4B\\\\u0B4C\\\\u0B57\\\\u0BBE\\\\u0BBF\\\\u0BC1\\\\u0BC2\\\\u0BC6-\\\\u0BC8\\\\u0BCA-\\\\u0BCC\\\\u0BD7\\\\u0C01-\\\\u0C03\\\\u0C41-\\\\u0C44\\\\u0C82\\\\u0C83\\\\u0CBE\\\\u0CC0-\\\\u0CC4\\\\u0CC7\\\\u0CC8\\\\u0CCA\\\\u0CCB\\\\u0CD5\\\\u0CD6\\\\u0D02\\\\u0D03\\\\u0D3E-\\\\u0D40\\\\u0D46-\\\\u0D48\\\\u0D4A-\\\\u0D4C\\\\u0D57\\\\u0D82\\\\u0D83\\\\u0DCF-\\\\u0DD1\\\\u0DD8-\\\\u0DDF\\\\u0DF2\\\\u0DF3\\\\u0F3E\\\\u0F3F\\\\u0F7F\\\\u102B\\\\u102C\\\\u1031\\\\u1038\\\\u103B\\\\u103C\\\\u1056\\\\u1057\\\\u1062-\\\\u1064\\\\u1067-\\\\u106D\\\\u1083\\\\u1084\\\\u1087-\\\\u108C\\\\u108F\\\\u109A-\\\\u109C\\\\u17B6\\\\u17BE-\\\\u17C5\\\\u17C7\\\\u17C8\\\\u1923-\\\\u1926\\\\u1929-\\\\u192B\\\\u1930\\\\u1931\\\\u1933-\\\\u1938\\\\u19B0-\\\\u19C0\\\\u19C8\\\\u19C9\\\\u1A19-\\\\u1A1B\\\\u1A55\\\\u1A57\\\\u1A61\\\\u1A63\\\\u1A64\\\\u1A6D-\\\\u1A72\\\\u1B04\\\\u1B35\\\\u1B3B\\\\u1B3D-\\\\u1B41\\\\u1B43\\\\u1B44\\\\u1B82\\\\u1BA1\\\\u1BA6\\\\u1BA7\\\\u1BAA\\\\u1C24-\\\\u1C2B\\\\u1C34\\\\u1C35\\\\u1CE1\\\\u1CF2\\\\uA823\\\\uA824\\\\uA827\\\\uA880\\\\uA881\\\\uA8B4-\\\\uA8C3\\\\uA952\\\\uA953\\\\uA983\\\\uA9B4\\\\uA9B5\\\\uA9BA\\\\uA9BB\\\\uA9BD-\\\\uA9C0\\\\uAA2F\\\\uAA30\\\\uAA33\\\\uAA34\\\\uAA4D\\\\uAA7B\\\\uABE3\\\\uABE4\\\\uABE6\\\\uABE7\\\\uABE9\\\\uABEA\\\\uABEC]\"),\n connector_punctuation: new RegExp(\"[\\\\u005F\\\\u203F\\\\u2040\\\\u2054\\\\uFE33\\\\uFE34\\\\uFE4D-\\\\uFE4F\\\\uFF3F]\")\n};\n\nfunction is_letter(ch) {\n return UNICODE.letter.test(ch);\n};\n\nfunction is_digit(ch) {\n ch = ch.charCodeAt(0);\n return ch >= 48 && ch <= 57; //XXX: find out if \"UnicodeDigit\" means something else than 0..9\n};\n\nfunction is_alphanumeric_char(ch) {\n return is_digit(ch) || is_letter(ch);\n};\n\nfunction is_unicode_combining_mark(ch) {\n return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);\n};\n\nfunction is_unicode_connector_punctuation(ch) {\n return UNICODE.connector_punctuation.test(ch);\n};\n\nfunction is_identifier_start(ch) {\n return ch == \"$\" || ch == \"_\" || is_letter(ch);\n};\n\nfunction is_identifier_char(ch) {\n return is_identifier_start(ch)\n || is_unicode_combining_mark(ch)\n || is_digit(ch)\n || is_unicode_connector_punctuation(ch)\n || ch == \"\\u200c\" // zero-width non-joiner <ZWNJ>\n || ch == \"\\u200d\" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)\n ;\n};\n\nfunction parse_js_number(num) {\n if (RE_HEX_NUMBER.test(num)) {\n return parseInt(num.substr(2), 16);\n } else if (RE_OCT_NUMBER.test(num)) {\n return parseInt(num.substr(1), 8);\n } else if (RE_DEC_NUMBER.test(num)) {\n return parseFloat(num);\n }\n};\n\nfunction JS_Parse_Error(message, line, col, pos) {\n this.message = message;\n this.line = line;\n this.col = col;\n this.pos = pos;\n try {\n ({})();\n } catch(ex) {\n this.stack = ex.stack;\n };\n};\n\nJS_Parse_Error.prototype.toString = function() {\n return this.message + \" (line: \" + this.line + \", col: \" + this.col + \", pos: \" + this.pos + \")\" + \"\\n\\n\" + this.stack;\n};\n\nfunction js_error(message, line, col, pos) {\n throw new JS_Parse_Error(message, line, col, pos);\n};\n\nfunction is_token(token, type, val) {\n return token.type == type && (val == null || token.value == val);\n};\n\nvar EX_EOF = {};\n\nfunction tokenizer($TEXT) {\n\n var S = {\n text : $TEXT.replace(/\\r\\n?|[\\n\\u2028\\u2029]/g, \"\\n\").replace(/^\\uFEFF/, ''),\n pos : 0,\n tokpos : 0,\n line : 0,\n tokline : 0,\n col : 0,\n tokcol : 0,\n newline_before : false,\n regex_allowed : false,\n comments_before : []\n };\n\n function peek() { return S.text.charAt(S.pos); };\n\n function next(signal_eof) {\n var ch = S.text.charAt(S.pos++);\n if (signal_eof && !ch)\n throw EX_EOF;\n if (ch == \"\\n\") {\n S.newline_before = true;\n ++S.line;\n S.col = 0;\n } else {\n ++S.col;\n }\n return ch;\n };\n\n function eof() {\n return !S.peek();\n };\n\n function find(what, signal_eof) {\n var pos = S.text.indexOf(what, S.pos);\n if (signal_eof && pos == -1) throw EX_EOF;\n return pos;\n };\n\n function start_token() {\n S.tokline = S.line;\n S.tokcol = S.col;\n S.tokpos = S.pos;\n };\n\n function token(type, value, is_comment) {\n S.regex_allowed = ((type == \"operator\" && !HOP(UNARY_POSTFIX, value)) ||\n (type == \"keyword\" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||\n (type == \"punc\" && HOP(PUNC_BEFORE_EXPRESSION, value)));\n var ret = {\n type : type,\n value : value,\n line : S.tokline,\n col : S.tokcol,\n pos : S.tokpos,\n nlb : S.newline_before\n };\n if (!is_comment) {\n ret.comments_before = S.comments_before;\n S.comments_before = [];\n }\n S.newline_before = false;\n return ret;\n };\n\n function skip_whitespace() {\n while (HOP(WHITESPACE_CHARS, peek()))\n next();\n };\n\n function read_while(pred) {\n var ret = \"\", ch = peek(), i = 0;\n while (ch && pred(ch, i++)) {\n ret += next();\n ch = peek();\n }\n return ret;\n };\n\n function parse_error(err) {\n js_error(err, S.tokline, S.tokcol, S.tokpos);\n };\n\n function read_num(prefix) {\n var has_e = false, after_e = false, has_x = false, has_dot = prefix == \".\";\n var num = read_while(function(ch, i){\n if (ch == \"x\" || ch == \"X\") {\n if (has_x) return false;\n return has_x = true;\n }\n if (!has_x && (ch == \"E\" || ch == \"e\")) {\n if (has_e) return false;\n return has_e = after_e = true;\n }\n if (ch == \"-\") {\n if (after_e || (i == 0 && !prefix)) return true;\n return false;\n }\n if (ch == \"+\") return after_e;\n after_e = false;\n if (ch == \".\") {\n if (!has_dot && !has_x)\n return has_dot = true;\n return false;\n }\n return is_alphanumeric_char(ch);\n });\n if (prefix)\n num = prefix + num;\n var valid = parse_js_number(num);\n if (!isNaN(valid)) {\n return token(\"num\", valid);\n } else {\n parse_error(\"Invalid syntax: \" + num);\n }\n };\n\n function read_escaped_char() {\n var ch = next(true);\n switch (ch) {\n case \"n\" : return \"\\n\";\n case \"r\" : return \"\\r\";\n case \"t\" : return \"\\t\";\n case \"b\" : return \"\\b\";\n case \"v\" : return \"\\u000b\";\n case \"f\" : return \"\\f\";\n case \"0\" : return \"\\0\";\n case \"x\" : return String.fromCharCode(hex_bytes(2));\n case \"u\" : return String.fromCharCode(hex_bytes(4));\n case \"\\n\": return \"\";\n default : return ch;\n }\n };\n\n function hex_bytes(n) {\n var num = 0;\n for (; n > 0; --n) {\n var digit = parseInt(next(true), 16);\n if (isNaN(digit))\n parse_error(\"Invalid hex-character pattern in string\");\n num = (num << 4) | digit;\n }\n return num;\n };\n\n function read_string() {\n return with_eof_error(\"Unterminated string constant\", function(){\n var quote = next(), ret = \"\";\n for (;;) {\n var ch = next(true);\n if (ch == \"\\\\\") {\n // read OctalEscapeSequence (XXX: deprecated if \"strict mode\")\n // https://github.com/mishoo/UglifyJS/issues/178\n var octal_len = 0, first = null;\n ch = read_while(function(ch){\n if (ch >= \"0\" && ch <= \"7\") {\n if (!first) {\n first = ch;\n return ++octal_len;\n }\n else if (first <= \"3\" && octal_len <= 2) return ++octal_len;\n else if (first >= \"4\" && octal_len <= 1) return ++octal_len;\n }\n return false;\n });\n if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));\n else ch = read_escaped_char();\n }\n else if (ch == quote) break;\n ret += ch;\n }\n return token(\"string\", ret);\n });\n };\n\n function read_line_comment() {\n next();\n var i = find(\"\\n\"), ret;\n if (i == -1) {\n ret = S.text.substr(S.pos);\n S.pos = S.text.length;\n } else {\n ret = S.text.substring(S.pos, i);\n S.pos = i;\n }\n return token(\"comment1\", ret, true);\n };\n\n function read_multiline_comment() {\n next();\n return with_eof_error(\"Unterminated multiline comment\", function(){\n var i = find(\"*/\", true),\n text = S.text.substring(S.pos, i),\n tok = token(\"comment2\", text, true);\n S.pos = i + 2;\n S.line += text.split(\"\\n\").length - 1;\n S.newline_before = text.indexOf(\"\\n\") >= 0;\n\n // https://github.com/mishoo/UglifyJS/issues/#issue/100\n if (/^@cc_on/i.test(text)) {\n warn(\"WARNING: at line \" + S.line);\n warn(\"*** Found \\\"conditional comment\\\": \" + text);\n warn(\"*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer.\");\n }\n\n return tok;\n });\n };\n\n function read_name() {\n var backslash = false, name = \"\", ch;\n while ((ch = peek()) != null) {\n if (!backslash) {\n if (ch == \"\\\\\") backslash = true, next();\n else if (is_identifier_char(ch)) name += next();\n else break;\n }\n else {\n if (ch != \"u\") parse_error(\"Expecting UnicodeEscapeSequence -- uXXXX\");\n ch = read_escaped_char();\n if (!is_identifier_char(ch)) parse_error(\"Unicode char: \" + ch.charCodeAt(0) + \" is not valid in identifier\");\n name += ch;\n backslash = false;\n }\n }\n return name;\n };\n\n function read_regexp() {\n return with_eof_error(\"Unterminated regular expression\", function(){\n var prev_backslash = false, regexp = \"\", ch, in_class = false;\n while ((ch = next(true))) if (prev_backslash) {\n regexp += \"\\\\\" + ch;\n prev_backslash = false;\n } else if (ch == \"[\") {\n in_class = true;\n regexp += ch;\n } else if (ch == \"]\" && in_class) {\n in_class = false;\n regexp += ch;\n } else if (ch == \"/\" && !in_class) {\n break;\n } else if (ch == \"\\\\\") {\n prev_backslash = true;\n } else {\n regexp += ch;\n }\n var mods = read_name();\n return token(\"regexp\", [ regexp, mods ]);\n });\n };\n\n function read_operator(prefix) {\n function grow(op) {\n if (!peek()) return op;\n var bigger = op + peek();\n if (HOP(OPERATORS, bigger)) {\n next();\n return grow(bigger);\n } else {\n return op;\n }\n };\n return token(\"operator\", grow(prefix || next()));\n };\n\n function handle_slash() {\n next();\n var regex_allowed = S.regex_allowed;\n switch (peek()) {\n case \"/\":\n S.comments_before.push(read_line_comment());\n S.regex_allowed = regex_allowed;\n return next_token();\n case \"*\":\n S.comments_before.push(read_multiline_comment());\n S.regex_allowed = regex_allowed;\n return next_token();\n }\n return S.regex_allowed ? read_regexp() : read_operator(\"/\");\n };\n\n function handle_dot() {\n next();\n return is_digit(peek())\n ? read_num(\".\")\n : token(\"punc\", \".\");\n };\n\n function read_word() {\n var word = read_name();\n return !HOP(KEYWORDS, word)\n ? token(\"name\", word)\n : HOP(OPERATORS, word)\n ? token(\"operator\", word)\n : HOP(KEYWORDS_ATOM, word)\n ? token(\"atom\", word)\n : token(\"keyword\", word);\n };\n\n function with_eof_error(eof_error, cont) {\n try {\n return cont();\n } catch(ex) {\n if (ex === EX_EOF) parse_error(eof_error);\n else throw ex;\n }\n };\n\n function next_token(force_regexp) {\n if (force_regexp)\n return read_regexp();\n skip_whitespace();\n start_token();\n var ch = peek();\n if (!ch) return token(\"eof\");\n if (is_digit(ch)) return read_num();\n if (ch == '\"' || ch == \"'\") return read_string();\n if (HOP(PUNC_CHARS, ch)) return token(\"punc\", next());\n if (ch == \".\") return handle_dot();\n if (ch == \"/\") return handle_slash();\n if (HOP(OPERATOR_CHARS, ch)) return read_operator();\n if (ch == \"\\\\\" || is_identifier_start(ch)) return read_word();\n parse_error(\"Unexpected character '\" + ch + \"'\");\n };\n\n next_token.context = function(nc) {\n if (nc) S = nc;\n return S;\n };\n\n return next_token;\n\n};\n\n/* -----[ Parser (constants) ]----- */\n\nvar UNARY_PREFIX = array_to_hash([\n \"typeof\",\n \"void\",\n \"delete\",\n \"--\",\n \"++\",\n \"!\",\n \"~\",\n \"-\",\n \"+\"\n]);\n\nvar UNARY_POSTFIX = array_to_hash([ \"--\", \"++\" ]);\n\nvar ASSIGNMENT = (function(a, ret, i){\n while (i < a.length) {\n ret[a[i]] = a[i].substr(0, a[i].length - 1);\n i++;\n }\n return ret;\n})(\n [\"+=\", \"-=\", \"/=\", \"*=\", \"%=\", \">>=\", \"<<=\", \">>>=\", \"|=\", \"^=\", \"&=\"],\n { \"=\": true },\n 0\n);\n\nvar PRECEDENCE = (function(a, ret){\n for (var i = 0, n = 1; i < a.length; ++i, ++n) {\n var b = a[i];\n for (var j = 0; j < b.length; ++j) {\n ret[b[j]] = n;\n }\n }\n return ret;\n})(\n [\n [\"||\"],\n [\"&&\"],\n [\"|\"],\n [\"^\"],\n [\"&\"],\n [\"==\", \"===\", \"!=\", \"!==\"],\n [\"<\", \">\", \"<=\", \">=\", \"in\", \"instanceof\"],\n [\">>\", \"<<\", \">>>\"],\n [\"+\", \"-\"],\n [\"*\", \"/\", \"%\"]\n ],\n {}\n);\n\nvar STATEMENTS_WITH_LABELS = array_to_hash([ \"for\", \"do\", \"while\", \"switch\" ]);\n\nvar ATOMIC_START_TOKEN = array_to_hash([ \"atom\", \"num\", \"string\", \"regexp\", \"name\" ]);\n\n/* -----[ Parser ]----- */\n\nfunction NodeWithToken(str, start, end) {\n this.name = str;\n this.start = start;\n this.end = end;\n};\n\nNodeWithToken.prototype.toString = function() { return this.name; };\n\nfunction parse($TEXT, exigent_mode, embed_tokens) {\n\n var S = {\n input : typeof $TEXT == \"string\" ? tokenizer($TEXT, true) : $TEXT,\n token : null,\n prev : null,\n peeked : null,\n in_function : 0,\n in_loop : 0,\n labels : []\n };\n\n S.token = next();\n\n function is(type, value) {\n return is_token(S.token, type, value);\n };\n\n function peek() { return S.peeked || (S.peeked = S.input()); };\n\n function next() {\n S.prev = S.token;\n if (S.peeked) {\n S.token = S.peeked;\n S.peeked = null;\n } else {\n S.token = S.input();\n }\n return S.token;\n };\n\n function prev() {\n return S.prev;\n };\n\n function croak(msg, line, col, pos) {\n var ctx = S.input.context();\n js_error(msg,\n line != null ? line : ctx.tokline,\n col != null ? col : ctx.tokcol,\n pos != null ? pos : ctx.tokpos);\n };\n\n function token_error(token, msg) {\n croak(msg, token.line, token.col);\n };\n\n function unexpected(token) {\n if (token == null)\n token = S.token;\n token_error(token, \"Unexpected token: \" + token.type + \" (\" + token.value + \")\");\n };\n\n function expect_token(type, val) {\n if (is(type, val)) {\n return next();\n }\n token_error(S.token, \"Unexpected token \" + S.token.type + \", expected \" + type);\n };\n\n function expect(punc) { return expect_token(\"punc\", punc); };\n\n function can_insert_semicolon() {\n return !exigent_mode && (\n S.token.nlb || is(\"eof\") || is(\"punc\", \"}\")\n );\n };\n\n function semicolon() {\n if (is(\"punc\", \";\")) next();\n else if (!can_insert_semicolon()) unexpected();\n };\n\n function as() {\n return slice(arguments);\n };\n\n function parenthesised() {\n expect(\"(\");\n var ex = expression();\n expect(\")\");\n return ex;\n };\n\n function add_tokens(str, start, end) {\n return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);\n };\n\n function maybe_embed_tokens(parser) {\n if (embed_tokens) return function() {\n var start = S.token;\n var ast = parser.apply(this, arguments);\n ast[0] = add_tokens(ast[0], start, prev());\n return ast;\n };\n else return parser;\n };\n\n var statement = maybe_embed_tokens(function() {\n if (is(\"operator\", \"/\")) {\n S.peeked = null;\n S.token = S.input(true); // force regexp\n }\n switch (S.token.type) {\n case \"num\":\n case \"string\":\n case \"regexp\":\n case \"operator\":\n case \"atom\":\n return simple_statement();\n\n case \"name\":\n return is_token(peek(), \"punc\", \":\")\n ? labeled_statement(prog1(S.token.value, next, next))\n : simple_statement();\n\n case \"punc\":\n switch (S.token.value) {\n case \"{\":\n return as(\"block\", block_());\n case \"[\":\n case \"(\":\n return simple_statement();\n case \";\":\n next();\n return as(\"block\");\n default:\n unexpected();\n }\n\n case \"keyword\":\n switch (prog1(S.token.value, next)) {\n case \"break\":\n return break_cont(\"break\");\n\n case \"continue\":\n return break_cont(\"continue\");\n\n case \"debugger\":\n semicolon();\n return as(\"debugger\");\n\n case \"do\":\n return (function(body){\n expect_token(\"keyword\", \"while\");\n return as(\"do\", prog1(parenthesised, semicolon), body);\n })(in_loop(statement));\n\n case \"for\":\n return for_();\n\n case \"function\":\n return function_(true);\n\n case \"if\":\n return if_();\n\n case \"return\":\n if (S.in_function == 0)\n croak(\"'return' outside of function\");\n return as(\"return\",\n is(\"punc\", \";\")\n ? (next(), null)\n : can_insert_semicolon()\n ? null\n : prog1(expression, semicolon));\n\n case \"switch\":\n return as(\"switch\", parenthesised(), switch_block_());\n\n case \"throw\":\n return as(\"throw\", prog1(expression, semicolon));\n\n case \"try\":\n return try_();\n\n case \"var\":\n return prog1(var_, semicolon);\n\n case \"const\":\n return prog1(const_, semicolon);\n\n case \"while\":\n return as(\"while\", parenthesised(), in_loop(statement));\n\n case \"with\":\n return as(\"with\", parenthesised(), statement());\n\n default:\n unexpected();\n }\n }\n });\n\n function labeled_statement(label) {\n S.labels.push(label);\n var start = S.token, stat = statement();\n if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))\n unexpected(start);\n S.labels.pop();\n return as(\"label\", label, stat);\n };\n\n function simple_statement() {\n return as(\"stat\", prog1(expression, semicolon));\n };\n\n function break_cont(type) {\n var name;\n if (!can_insert_semicolon()) {\n name = is(\"name\") ? S.token.value : null;\n }\n if (name != null) {\n next();\n if (!member(name, S.labels))\n croak(\"Label \" + name + \" without matching loop or statement\");\n }\n else if (S.in_loop == 0)\n croak(type + \" not inside a loop or switch\");\n semicolon();\n return as(type, name);\n };\n\n function for_() {\n expect(\"(\");\n var init = null;\n if (!is(\"punc\", \";\")) {\n init = is(\"keyword\", \"var\")\n ? (next(), var_(true))\n : expression(true, true);\n if (is(\"operator\", \"in\"))\n return for_in(init);\n }\n return regular_for(init);\n };\n\n function regular_for(init) {\n expect(\";\");\n var test = is(\"punc\", \";\") ? null : expression();\n expect(\";\");\n var step = is(\"punc\", \")\") ? null : expression();\n expect(\")\");\n return as(\"for\", init, test, step, in_loop(statement));\n };\n\n function for_in(init) {\n var lhs = init[0] == \"var\" ? as(\"name\", init[1][0]) : init;\n next();\n var obj = expression();\n expect(\")\");\n return as(\"for-in\", init, lhs, obj, in_loop(statement));\n };\n\n var function_ = maybe_embed_tokens(function(in_statement) {\n var name = is(\"name\") ? prog1(S.token.value, next) : null;\n if (in_statement && !name)\n unexpected();\n expect(\"(\");\n return as(in_statement ? \"defun\" : \"function\",\n name,\n // arguments\n (function(first, a){\n while (!is(\"punc\", \")\")) {\n if (first) first = false; else expect(\",\");\n if (!is(\"name\")) unexpected();\n a.push(S.token.value);\n next();\n }\n next();\n return a;\n })(true, []),\n // body\n (function(){\n ++S.in_function;\n var loop = S.in_loop;\n S.in_loop = 0;\n var a = block_();\n --S.in_function;\n S.in_loop = loop;\n return a;\n })());\n });\n\n function if_() {\n var cond = parenthesised(), body = statement(), belse;\n if (is(\"keyword\", \"else\")) {\n next();\n belse = statement();\n }\n return as(\"if\", cond, body, belse);\n };\n\n function block_() {\n expect(\"{\");\n var a = [];\n while (!is(\"punc\", \"}\")) {\n if (is(\"eof\")) unexpected();\n a.push(statement());\n }\n next();\n return a;\n };\n\n var switch_block_ = curry(in_loop, function(){\n expect(\"{\");\n var a = [], cur = null;\n while (!is(\"punc\", \"}\")) {\n if (is(\"eof\")) unexpected();\n if (is(\"keyword\", \"case\")) {\n next();\n cur = [];\n a.push([ expression(), cur ]);\n expect(\":\");\n }\n else if (is(\"keyword\", \"default\")) {\n next();\n expect(\":\");\n cur = [];\n a.push([ null, cur ]);\n }\n else {\n if (!cur) unexpected();\n cur.push(statement());\n }\n }\n next();\n return a;\n });\n\n function try_() {\n var body = block_(), bcatch, bfinally;\n if (is(\"keyword\", \"catch\")) {\n next();\n expect(\"(\");\n if (!is(\"name\"))\n croak(\"Name expected\");\n var name = S.token.value;\n next();\n expect(\")\");\n bcatch = [ name, block_() ];\n }\n if (is(\"keyword\", \"finally\")) {\n next();\n bfinally = block_();\n }\n if (!bcatch && !bfinally)\n croak(\"Missing catch/finally blocks\");\n return as(\"try\", body, bcatch, bfinally);\n };\n\n function vardefs(no_in) {\n var a = [];\n for (;;) {\n if (!is(\"name\"))\n unexpected();\n var name = S.token.value;\n next();\n if (is(\"operator\", \"=\")) {\n next();\n a.push([ name, expression(false, no_in) ]);\n } else {\n a.push([ name ]);\n }\n if (!is(\"punc\", \",\"))\n break;\n next();\n }\n return a;\n };\n\n function var_(no_in) {\n return as(\"var\", vardefs(no_in));\n };\n\n function const_() {\n return as(\"const\", vardefs());\n };\n\n function new_() {\n var newexp = expr_atom(false), args;\n if (is(\"punc\", \"(\")) {\n next();\n args = expr_list(\")\");\n } else {\n args = [];\n }\n return subscripts(as(\"new\", newexp, args), true);\n };\n\n var expr_atom = maybe_embed_tokens(function(allow_calls) {\n if (is(\"operator\", \"new\")) {\n next();\n return new_();\n }\n if (is(\"punc\")) {\n switch (S.token.value) {\n case \"(\":\n next();\n return subscripts(prog1(expression, curry(expect, \")\")), allow_calls);\n case \"[\":\n next();\n return subscripts(array_(), allow_calls);\n case \"{\":\n next();\n return subscripts(object_(), allow_calls);\n }\n unexpected();\n }\n if (is(\"keyword\", \"function\")) {\n next();\n return subscripts(function_(false), allow_calls);\n }\n if (HOP(ATOMIC_START_TOKEN, S.token.type)) {\n var atom = S.token.type == \"regexp\"\n ? as(\"regexp\", S.token.value[0], S.token.value[1])\n : as(S.token.type, S.token.value);\n return subscripts(prog1(atom, next), allow_calls);\n }\n unexpected();\n });\n\n function expr_list(closing, allow_trailing_comma, allow_empty) {\n var first = true, a = [];\n while (!is(\"punc\", closing)) {\n if (first) first = false; else expect(\",\");\n if (allow_trailing_comma && is(\"punc\", closing)) break;\n if (is(\"punc\", \",\") && allow_empty) {\n a.push([ \"atom\", \"undefined\" ]);\n } else {\n a.push(expression(false));\n }\n }\n next();\n return a;\n };\n\n function array_() {\n return as(\"array\", expr_list(\"]\", !exigent_mode, true));\n };\n\n function object_() {\n var first = true, a = [];\n while (!is(\"punc\", \"}\")) {\n if (first) first = false; else expect(\",\");\n if (!exigent_mode && is(\"punc\", \"}\"))\n // allow trailing comma\n break;\n var type = S.token.type;\n var name = as_property_name();\n if (type == \"name\" && (name == \"get\" || name == \"set\") && !is(\"punc\", \":\")) {\n a.push([ as_name(), function_(false), name ]);\n } else {\n expect(\":\");\n a.push([ name, expression(false) ]);\n }\n }\n next();\n return as(\"object\", a);\n };\n\n function as_property_name() {\n switch (S.token.type) {\n case \"num\":\n case \"string\":\n return prog1(S.token.value, next);\n }\n return as_name();\n };\n\n function as_name() {\n switch (S.token.type) {\n case \"name\":\n case \"operator\":\n case \"keyword\":\n case \"atom\":\n return prog1(S.token.value, next);\n default:\n unexpected();\n }\n };\n\n function subscripts(expr, allow_calls) {\n if (is(\"punc\", \".\")) {\n next();\n return subscripts(as(\"dot\", expr, as_name()), allow_calls);\n }\n if (is(\"punc\", \"[\")) {\n next();\n return subscripts(as(\"sub\", expr, prog1(expression, curry(expect, \"]\"))), allow_calls);\n }\n if (allow_calls && is(\"punc\", \"(\")) {\n next();\n return subscripts(as(\"call\", expr, expr_list(\")\")), true);\n }\n return expr;\n };\n\n function maybe_unary(allow_calls) {\n if (is(\"operator\") && HOP(UNARY_PREFIX, S.token.value)) {\n return make_unary(\"unary-prefix\",\n prog1(S.token.value, next),\n maybe_unary(allow_calls));\n }\n var val = expr_atom(allow_calls);\n while (is(\"operator\") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) {\n val = make_unary(\"unary-postfix\", S.token.value, val);\n next();\n }\n return val;\n };\n\n function make_unary(tag, op, expr) {\n if ((op == \"++\" || op == \"--\") && !is_assignable(expr))\n croak(\"Invalid use of \" + op + \" operator\");\n return as(tag, op, expr);\n };\n\n function expr_op(left, min_prec, no_in) {\n var op = is(\"operator\") ? S.token.value : null;\n if (op && op == \"in\" && no_in) op = null;\n var prec = op != null ? PRECEDENCE[op] : null;\n if (prec != null && prec > min_prec) {\n next();\n var right = expr_op(maybe_unary(true), prec, no_in);\n return expr_op(as(\"binary\", op, left, right), min_prec, no_in);\n }\n return left;\n };\n\n function expr_ops(no_in) {\n return expr_op(maybe_unary(true), 0, no_in);\n };\n\n function maybe_conditional(no_in) {\n var expr = expr_ops(no_in);\n if (is(\"operator\", \"?\")) {\n next();\n var yes = expression(false);\n expect(\":\");\n return as(\"conditional\", expr, yes, expression(false, no_in));\n }\n return expr;\n };\n\n function is_assignable(expr) {\n if (!exigent_mode) return true;\n switch (expr[0]+\"\") {\n case \"dot\":\n case \"sub\":\n case \"new\":\n case \"call\":\n return true;\n case \"name\":\n return expr[1] != \"this\";\n }\n };\n\n function maybe_assign(no_in) {\n var left = maybe_conditional(no_in), val = S.token.value;\n if (is(\"operator\") && HOP(ASSIGNMENT, val)) {\n if (is_assignable(left)) {\n next();\n return as(\"assign\", ASSIGNMENT[val], left, maybe_assign(no_in));\n }\n croak(\"Invalid assignment\");\n }\n return left;\n };\n\n var expression = maybe_embed_tokens(function(commas, no_in) {\n if (arguments.length == 0)\n commas = true;\n var expr = maybe_assign(no_in);\n if (commas && is(\"punc\", \",\")) {\n next();\n return as(\"seq\", expr, expression(true, no_in));\n }\n return expr;\n });\n\n function in_loop(cont) {\n try {\n ++S.in_loop;\n return cont();\n } finally {\n --S.in_loop;\n }\n };\n\n return as(\"toplevel\", (function(a){\n while (!is(\"eof\"))\n a.push(statement());\n return a;\n })([]));\n\n};\n\n/* -----[ Utilities ]----- */\n\nfunction curry(f) {\n var args = slice(arguments, 1);\n return function() { return f.apply(this, args.concat(slice(arguments))); };\n};\n\nfunction prog1(ret) {\n if (ret instanceof Function)\n ret = ret();\n for (var i = 1, n = arguments.length; --n > 0; ++i)\n arguments[i]();\n return ret;\n};\n\nfunction array_to_hash(a) {\n var ret = {};\n for (var i = 0; i < a.length; ++i)\n ret[a[i]] = true;\n return ret;\n};\n\nfunction slice(a, start) {\n return Array.prototype.slice.call(a, start || 0);\n};\n\nfunction characters(str) {\n return str.split(\"\");\n};\n\nfunction member(name, array) {\n for (var i = array.length; --i >= 0;)\n if (array[i] === name)\n return true;\n return false;\n};\n\nfunction HOP(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\nvar warn = function() {};\n\n/* -----[ Exports ]----- */\n\nexports.tokenizer = tokenizer;\nexports.parse = parse;\nexports.slice = slice;\nexports.curry = curry;\nexports.member = member;\nexports.array_to_hash = array_to_hash;\nexports.PRECEDENCE = PRECEDENCE;\nexports.KEYWORDS_ATOM = KEYWORDS_ATOM;\nexports.RESERVED_WORDS = RESERVED_WORDS;\nexports.KEYWORDS = KEYWORDS;\nexports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;\nexports.OPERATORS = OPERATORS;\nexports.is_alphanumeric_char = is_alphanumeric_char;\nexports.set_logger = function(logger) {\n warn = logger;\n};\n\n});");spade.register("uglify-js/process", "(function(require, exports, __module, ARGV, ENV, __filename){/***********************************************************************\n\n A JavaScript tokenizer / parser / beautifier / compressor.\n\n This version is suitable for Node.js. With minimal changes (the\n exports stuff) it should work on any JS platform.\n\n This file implements some AST processors. They work on data built\n by parse-js.\n\n Exported functions:\n\n - ast_mangle(ast, options) -- mangles the variable/function names\n in the AST. Returns an AST.\n\n - ast_squeeze(ast) -- employs various optimizations to make the\n final generated code even smaller. Returns an AST.\n\n - gen_code(ast, options) -- generates JS code from the AST. Pass\n true (or an object, see the code for some options) as second\n argument to get \"pretty\" (indented) code.\n\n -------------------------------- (C) ---------------------------------\n\n Author: Mihai Bazon\n <mihai.bazon@gmail.com>\n http://mihai.bazon.net/blog\n\n Distributed under the BSD license:\n\n Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n\n * Redistributions of source code must retain the above\n copyright notice, this list of conditions and the following\n disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials\n provided with the distribution.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER â\u0080\u009cAS ISâ\u0080\u009d AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n SUCH DAMAGE.\n\n ***********************************************************************/\n\n\nvar jsp = require(\"./parse-js\"),\n slice = jsp.slice,\n member = jsp.member,\n PRECEDENCE = jsp.PRECEDENCE,\n OPERATORS = jsp.OPERATORS;\n\n/* -----[ helper for AST traversal ]----- */\n\nfunction ast_walker() {\n function _vardefs(defs) {\n return [ this[0], MAP(defs, function(def){\n var a = [ def[0] ];\n if (def.length > 1)\n a[1] = walk(def[1]);\n return a;\n }) ];\n };\n function _block(statements) {\n var out = [ this[0] ];\n if (statements != null)\n out.push(MAP(statements, walk));\n return out;\n };\n var walkers = {\n \"string\": function(str) {\n return [ this[0], str ];\n },\n \"num\": function(num) {\n return [ this[0], num ];\n },\n \"name\": function(name) {\n return [ this[0], name ];\n },\n \"toplevel\": function(statements) {\n return [ this[0], MAP(statements, walk) ];\n },\n \"block\": _block,\n \"splice\": _block,\n \"var\": _vardefs,\n \"const\": _vardefs,\n \"try\": function(t, c, f) {\n return [\n this[0],\n MAP(t, walk),\n c != null ? [ c[0], MAP(c[1], walk) ] : null,\n f != null ? MAP(f, walk) : null\n ];\n },\n \"throw\": function(expr) {\n return [ this[0], walk(expr) ];\n },\n \"new\": function(ctor, args) {\n return [ this[0], walk(ctor), MAP(args, walk) ];\n },\n \"switch\": function(expr, body) {\n return [ this[0], walk(expr), MAP(body, function(branch){\n return [ branch[0] ? walk(branch[0]) : null,\n MAP(branch[1], walk) ];\n }) ];\n },\n \"break\": function(label) {\n return [ this[0], label ];\n },\n \"continue\": function(label) {\n return [ this[0], label ];\n },\n \"conditional\": function(cond, t, e) {\n return [ this[0], walk(cond), walk(t), walk(e) ];\n },\n \"assign\": function(op, lvalue, rvalue) {\n return [ this[0], op, walk(lvalue), walk(rvalue) ];\n },\n \"dot\": function(expr) {\n return [ this[0], walk(expr) ].concat(slice(arguments, 1));\n },\n \"call\": function(expr, args) {\n return [ this[0], walk(expr), MAP(args, walk) ];\n },\n \"function\": function(name, args, body) {\n return [ this[0], name, args.slice(), MAP(body, walk) ];\n },\n \"defun\": function(name, args, body) {\n return [ this[0], name, args.slice(), MAP(body, walk) ];\n },\n \"if\": function(conditional, t, e) {\n return [ this[0], walk(conditional), walk(t), walk(e) ];\n },\n \"for\": function(init, cond, step, block) {\n return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];\n },\n \"for-in\": function(vvar, key, hash, block) {\n return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];\n },\n \"while\": function(cond, block) {\n return [ this[0], walk(cond), walk(block) ];\n },\n \"do\": function(cond, block) {\n return [ this[0], walk(cond), walk(block) ];\n },\n \"return\": function(expr) {\n return [ this[0], walk(expr) ];\n },\n \"binary\": function(op, left, right) {\n return [ this[0], op, walk(left), walk(right) ];\n },\n \"unary-prefix\": function(op, expr) {\n return [ this[0], op, walk(expr) ];\n },\n \"unary-postfix\": function(op, expr) {\n return [ this[0], op, walk(expr) ];\n },\n \"sub\": function(expr, subscript) {\n return [ this[0], walk(expr), walk(subscript) ];\n },\n \"object\": function(props) {\n return [ this[0], MAP(props, function(p){\n return p.length == 2\n ? [ p[0], walk(p[1]) ]\n : [ p[0], walk(p[1]), p[2] ]; // get/set-ter\n }) ];\n },\n \"regexp\": function(rx, mods) {\n return [ this[0], rx, mods ];\n },\n \"array\": function(elements) {\n return [ this[0], MAP(elements, walk) ];\n },\n \"stat\": function(stat) {\n return [ this[0], walk(stat) ];\n },\n \"seq\": function() {\n return [ this[0] ].concat(MAP(slice(arguments), walk));\n },\n \"label\": function(name, block) {\n return [ this[0], name, walk(block) ];\n },\n \"with\": function(expr, block) {\n return [ this[0], walk(expr), walk(block) ];\n },\n \"atom\": function(name) {\n return [ this[0], name ];\n }\n };\n\n var user = {};\n var stack = [];\n function walk(ast) {\n if (ast == null)\n return null;\n try {\n stack.push(ast);\n var type = ast[0];\n var gen = user[type];\n if (gen) {\n var ret = gen.apply(ast, ast.slice(1));\n if (ret != null)\n return ret;\n }\n gen = walkers[type];\n return gen.apply(ast, ast.slice(1));\n } finally {\n stack.pop();\n }\n };\n\n function dive(ast) {\n if (ast == null)\n return null;\n try {\n stack.push(ast);\n return walkers[ast[0]].apply(ast, ast.slice(1));\n } finally {\n stack.pop();\n }\n };\n\n function with_walkers(walkers, cont){\n var save = {}, i;\n for (i in walkers) if (HOP(walkers, i)) {\n save[i] = user[i];\n user[i] = walkers[i];\n }\n var ret = cont();\n for (i in save) if (HOP(save, i)) {\n if (!save[i]) delete user[i];\n else user[i] = save[i];\n }\n return ret;\n };\n\n return {\n walk: walk,\n dive: dive,\n with_walkers: with_walkers,\n parent: function() {\n return stack[stack.length - 2]; // last one is current node\n },\n stack: function() {\n return stack;\n }\n };\n};\n\n/* -----[ Scope and mangling ]----- */\n\nfunction Scope(parent) {\n this.names = {}; // names defined in this scope\n this.mangled = {}; // mangled names (orig.name => mangled)\n this.rev_mangled = {}; // reverse lookup (mangled => orig.name)\n this.cname = -1; // current mangled name\n this.refs = {}; // names referenced from this scope\n this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes\n this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes\n this.parent = parent; // parent scope\n this.children = []; // sub-scopes\n if (parent) {\n this.level = parent.level + 1;\n parent.children.push(this);\n } else {\n this.level = 0;\n }\n};\n\nvar base54 = (function(){\n var DIGITS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_\";\n return function(num) {\n var ret = \"\";\n do {\n ret = DIGITS.charAt(num % 54) + ret;\n num = Math.floor(num / 54);\n } while (num > 0);\n return ret;\n };\n})();\n\nScope.prototype = {\n has: function(name) {\n for (var s = this; s; s = s.parent)\n if (HOP(s.names, name))\n return s;\n },\n has_mangled: function(mname) {\n for (var s = this; s; s = s.parent)\n if (HOP(s.rev_mangled, mname))\n return s;\n },\n toJSON: function() {\n return {\n names: this.names,\n uses_eval: this.uses_eval,\n uses_with: this.uses_with\n };\n },\n\n next_mangled: function() {\n // we must be careful that the new mangled name:\n //\n // 1. doesn't shadow a mangled name from a parent\n // scope, unless we don't reference the original\n // name from this scope OR from any sub-scopes!\n // This will get slow.\n //\n // 2. doesn't shadow an original name from a parent\n // scope, in the event that the name is not mangled\n // in the parent scope and we reference that name\n // here OR IN ANY SUBSCOPES!\n //\n // 3. doesn't shadow a name that is referenced but not\n // defined (possibly global defined elsewhere).\n for (;;) {\n var m = base54(++this.cname), prior;\n\n // case 1.\n prior = this.has_mangled(m);\n if (prior && this.refs[prior.rev_mangled[m]] === prior)\n continue;\n\n // case 2.\n prior = this.has(m);\n if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))\n continue;\n\n // case 3.\n if (HOP(this.refs, m) && this.refs[m] == null)\n continue;\n\n // I got \"do\" once. :-/\n if (!is_identifier(m))\n continue;\n\n return m;\n }\n },\n set_mangle: function(name, m) {\n this.rev_mangled[m] = name;\n return this.mangled[name] = m;\n },\n get_mangled: function(name, newMangle) {\n if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use\n var s = this.has(name);\n if (!s) return name; // not in visible scope, no mangle\n if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope\n if (!newMangle) return name; // not found and no mangling requested\n return s.set_mangle(name, s.next_mangled());\n },\n references: function(name) {\n return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name];\n },\n define: function(name, type) {\n if (name != null) {\n if (type == \"var\" || !HOP(this.names, name))\n this.names[name] = type || \"var\";\n return name;\n }\n }\n};\n\nfunction ast_add_scope(ast) {\n\n var current_scope = null;\n var w = ast_walker(), walk = w.walk;\n var having_eval = [];\n\n function with_new_scope(cont) {\n current_scope = new Scope(current_scope);\n var ret = current_scope.body = cont();\n ret.scope = current_scope;\n current_scope = current_scope.parent;\n return ret;\n };\n\n function define(name, type) {\n return current_scope.define(name, type);\n };\n\n function reference(name) {\n current_scope.refs[name] = true;\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\";\n return [ this[0], is_defun ? define(name, \"defun\") : name, args, with_new_scope(function(){\n if (!is_defun) define(name, \"lambda\");\n MAP(args, function(name){ define(name, \"arg\") });\n return MAP(body, walk);\n })];\n };\n\n function _vardefs(type) {\n return function(defs) {\n MAP(defs, function(d){\n define(d[0], type);\n if (d[1]) reference(d[0]);\n });\n };\n };\n\n return with_new_scope(function(){\n // process AST\n var ret = w.with_walkers({\n \"function\": _lambda,\n \"defun\": _lambda,\n \"label\": function(name, stat) { define(name, \"label\") },\n \"break\": function(label) { if (label) reference(label) },\n \"continue\": function(label) { if (label) reference(label) },\n \"with\": function(expr, block) {\n for (var s = current_scope; s; s = s.parent)\n s.uses_with = true;\n },\n \"var\": _vardefs(\"var\"),\n \"const\": _vardefs(\"const\"),\n \"try\": function(t, c, f) {\n if (c != null) return [\n this[0],\n MAP(t, walk),\n [ define(c[0], \"catch\"), MAP(c[1], walk) ],\n f != null ? MAP(f, walk) : null\n ];\n },\n \"name\": function(name) {\n if (name == \"eval\")\n having_eval.push(current_scope);\n reference(name);\n }\n }, function(){\n return walk(ast);\n });\n\n // the reason why we need an additional pass here is\n // that names can be used prior to their definition.\n\n // scopes where eval was detected and their parents\n // are marked with uses_eval, unless they define the\n // \"eval\" name.\n MAP(having_eval, function(scope){\n if (!scope.has(\"eval\")) while (scope) {\n scope.uses_eval = true;\n scope = scope.parent;\n }\n });\n\n // for referenced names it might be useful to know\n // their origin scope. current_scope here is the\n // toplevel one.\n function fixrefs(scope, i) {\n // do children first; order shouldn't matter\n for (i = scope.children.length; --i >= 0;)\n fixrefs(scope.children[i]);\n for (i in scope.refs) if (HOP(scope.refs, i)) {\n // find origin scope and propagate the reference to origin\n for (var origin = scope.has(i), s = scope; s; s = s.parent) {\n s.refs[i] = origin;\n if (s === origin) break;\n }\n }\n };\n fixrefs(current_scope);\n\n return ret;\n });\n\n};\n\n/* -----[ mangle names ]----- */\n\nfunction ast_mangle(ast, options) {\n var w = ast_walker(), walk = w.walk, scope;\n options = options || {};\n\n function get_mangled(name, newMangle) {\n if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel\n if (options.except && member(name, options.except))\n return name;\n return scope.get_mangled(name, newMangle);\n };\n\n function get_define(name) {\n if (options.defines) {\n // we always lookup a defined symbol for the current scope FIRST, so declared\n // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value\n if (!scope.has(name)) {\n if (HOP(options.defines, name)) {\n return options.defines[name];\n }\n }\n return null;\n }\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\", extra;\n if (name) {\n if (is_defun) name = get_mangled(name);\n else {\n extra = {};\n if (!(scope.uses_eval || scope.uses_with))\n name = extra[name] = scope.next_mangled();\n else\n extra[name] = name;\n }\n }\n body = with_scope(body.scope, function(){\n args = MAP(args, function(name){ return get_mangled(name) });\n return MAP(body, walk);\n }, extra);\n return [ this[0], name, args, body ];\n };\n\n function with_scope(s, cont, extra) {\n var _scope = scope;\n scope = s;\n if (extra) for (var i in extra) if (HOP(extra, i)) {\n s.set_mangle(i, extra[i]);\n }\n for (var i in s.names) if (HOP(s.names, i)) {\n get_mangled(i, true);\n }\n var ret = cont();\n ret.scope = s;\n scope = _scope;\n return ret;\n };\n\n function _vardefs(defs) {\n return [ this[0], MAP(defs, function(d){\n return [ get_mangled(d[0]), walk(d[1]) ];\n }) ];\n };\n\n return w.with_walkers({\n \"function\": _lambda,\n \"defun\": function() {\n // move function declarations to the top when\n // they are not in some block.\n var ast = _lambda.apply(this, arguments);\n switch (w.parent()[0]) {\n case \"toplevel\":\n case \"function\":\n case \"defun\":\n return MAP.at_top(ast);\n }\n return ast;\n },\n \"label\": function(label, stat) { return [ this[0], get_mangled(label), walk(stat) ] },\n \"break\": function(label) { if (label) return [ this[0], get_mangled(label) ] },\n \"continue\": function(label) { if (label) return [ this[0], get_mangled(label) ] },\n \"var\": _vardefs,\n \"const\": _vardefs,\n \"name\": function(name) {\n return get_define(name) || [ this[0], get_mangled(name) ];\n },\n \"try\": function(t, c, f) {\n return [ this[0],\n MAP(t, walk),\n c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,\n f != null ? MAP(f, walk) : null ];\n },\n \"toplevel\": function(body) {\n var self = this;\n return with_scope(self.scope, function(){\n return [ self[0], MAP(body, walk) ];\n });\n }\n }, function() {\n return walk(ast_add_scope(ast));\n });\n};\n\n/* -----[\n - compress foo[\"bar\"] into foo.bar,\n - remove block brackets {} where possible\n - join consecutive var declarations\n - various optimizations for IFs:\n - if (cond) foo(); else bar(); ==> cond?foo():bar();\n - if (cond) foo(); ==> cond&&foo();\n - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw\n - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n ]----- */\n\nvar warn = function(){};\n\nfunction best_of(ast1, ast2) {\n return gen_code(ast1).length > gen_code(ast2[0] == \"stat\" ? ast2[1] : ast2).length ? ast2 : ast1;\n};\n\nfunction last_stat(b) {\n if (b[0] == \"block\" && b[1] && b[1].length > 0)\n return b[1][b[1].length - 1];\n return b;\n}\n\nfunction aborts(t) {\n if (t) switch (last_stat(t)[0]) {\n case \"return\":\n case \"break\":\n case \"continue\":\n case \"throw\":\n return true;\n }\n};\n\nfunction boolean_expr(expr) {\n return ( (expr[0] == \"unary-prefix\"\n && member(expr[1], [ \"!\", \"delete\" ])) ||\n\n (expr[0] == \"binary\"\n && member(expr[1], [ \"in\", \"instanceof\", \"==\", \"!=\", \"===\", \"!==\", \"<\", \"<=\", \">=\", \">\" ])) ||\n\n (expr[0] == \"binary\"\n && member(expr[1], [ \"&&\", \"||\" ])\n && boolean_expr(expr[2])\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"conditional\"\n && boolean_expr(expr[2])\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"assign\"\n && expr[1] === true\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"seq\"\n && boolean_expr(expr[expr.length - 1]))\n );\n};\n\nfunction make_conditional(c, t, e) {\n var make_real_conditional = function() {\n if (c[0] == \"unary-prefix\" && c[1] == \"!\") {\n return e ? [ \"conditional\", c[2], e, t ] : [ \"binary\", \"||\", c[2], t ];\n } else {\n return e ? [ \"conditional\", c, t, e ] : [ \"binary\", \"&&\", c, t ];\n }\n };\n // shortcut the conditional if the expression has a constant value\n return when_constant(c, function(ast, val){\n warn_unreachable(val ? e : t);\n return (val ? t : e);\n }, make_real_conditional);\n};\n\nfunction empty(b) {\n return !b || (b[0] == \"block\" && (!b[1] || b[1].length == 0));\n};\n\nfunction is_string(node) {\n return (node[0] == \"string\" ||\n node[0] == \"unary-prefix\" && node[1] == \"typeof\" ||\n node[0] == \"binary\" && node[1] == \"+\" &&\n (is_string(node[2]) || is_string(node[3])));\n};\n\nvar when_constant = (function(){\n\n var $NOT_CONSTANT = {};\n\n // this can only evaluate constant expressions. If it finds anything\n // not constant, it throws $NOT_CONSTANT.\n function evaluate(expr) {\n switch (expr[0]) {\n case \"string\":\n case \"num\":\n return expr[1];\n case \"name\":\n case \"atom\":\n switch (expr[1]) {\n case \"true\": return true;\n case \"false\": return false;\n }\n break;\n case \"unary-prefix\":\n switch (expr[1]) {\n case \"!\": return !evaluate(expr[2]);\n case \"typeof\": return typeof evaluate(expr[2]);\n case \"~\": return ~evaluate(expr[2]);\n case \"-\": return -evaluate(expr[2]);\n case \"+\": return +evaluate(expr[2]);\n }\n break;\n case \"binary\":\n var left = expr[2], right = expr[3];\n switch (expr[1]) {\n case \"&&\" : return evaluate(left) && evaluate(right);\n case \"||\" : return evaluate(left) || evaluate(right);\n case \"|\" : return evaluate(left) | evaluate(right);\n case \"&\" : return evaluate(left) & evaluate(right);\n case \"^\" : return evaluate(left) ^ evaluate(right);\n case \"+\" : return evaluate(left) + evaluate(right);\n case \"*\" : return evaluate(left) * evaluate(right);\n case \"/\" : return evaluate(left) / evaluate(right);\n case \"%\" : return evaluate(left) % evaluate(right);\n case \"-\" : return evaluate(left) - evaluate(right);\n case \"<<\" : return evaluate(left) << evaluate(right);\n case \">>\" : return evaluate(left) >> evaluate(right);\n case \">>>\" : return evaluate(left) >>> evaluate(right);\n case \"==\" : return evaluate(left) == evaluate(right);\n case \"===\" : return evaluate(left) === evaluate(right);\n case \"!=\" : return evaluate(left) != evaluate(right);\n case \"!==\" : return evaluate(left) !== evaluate(right);\n case \"<\" : return evaluate(left) < evaluate(right);\n case \"<=\" : return evaluate(left) <= evaluate(right);\n case \">\" : return evaluate(left) > evaluate(right);\n case \">=\" : return evaluate(left) >= evaluate(right);\n case \"in\" : return evaluate(left) in evaluate(right);\n case \"instanceof\" : return evaluate(left) instanceof evaluate(right);\n }\n }\n throw $NOT_CONSTANT;\n };\n\n return function(expr, yes, no) {\n try {\n var val = evaluate(expr), ast;\n switch (typeof val) {\n case \"string\": ast = [ \"string\", val ]; break;\n case \"number\": ast = [ \"num\", val ]; break;\n case \"boolean\": ast = [ \"name\", String(val) ]; break;\n default: throw new Error(\"Can't handle constant of type: \" + (typeof val));\n }\n return yes.call(expr, ast, val);\n } catch(ex) {\n if (ex === $NOT_CONSTANT) {\n if (expr[0] == \"binary\"\n && (expr[1] == \"===\" || expr[1] == \"!==\")\n && ((is_string(expr[2]) && is_string(expr[3]))\n || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {\n expr[1] = expr[1].substr(0, 2);\n }\n else if (no && expr[0] == \"binary\"\n && (expr[1] == \"||\" || expr[1] == \"&&\")) {\n // the whole expression is not constant but the lval may be...\n try {\n var lval = evaluate(expr[2]);\n expr = ((expr[1] == \"&&\" && (lval ? expr[3] : lval)) ||\n (expr[1] == \"||\" && (lval ? lval : expr[3])) ||\n expr);\n } catch(ex2) {\n // IGNORE... lval is not constant\n }\n }\n return no ? no.call(expr, expr) : null;\n }\n else throw ex;\n }\n };\n\n})();\n\nfunction warn_unreachable(ast) {\n if (!empty(ast))\n warn(\"Dropping unreachable code: \" + gen_code(ast, true));\n};\n\nfunction prepare_ifs(ast) {\n var w = ast_walker(), walk = w.walk;\n // In this first pass, we rewrite ifs which abort with no else with an\n // if-else. For example:\n //\n // if (x) {\n // blah();\n // return y;\n // }\n // foobar();\n //\n // is rewritten into:\n //\n // if (x) {\n // blah();\n // return y;\n // } else {\n // foobar();\n // }\n function redo_if(statements) {\n statements = MAP(statements, walk);\n\n for (var i = 0; i < statements.length; ++i) {\n var fi = statements[i];\n if (fi[0] != \"if\") continue;\n\n if (fi[3] && walk(fi[3])) continue;\n\n var t = walk(fi[2]);\n if (!aborts(t)) continue;\n\n var conditional = walk(fi[1]);\n\n var e_body = statements.slice(i + 1);\n var e = e_body.length == 1 ? e_body[0] : [ \"block\", e_body ];\n\n var ret = statements.slice(0, i).concat([ [\n fi[0], // \"if\"\n conditional, // conditional\n t, // then\n e // else\n ] ]);\n\n return redo_if(ret);\n }\n\n return statements;\n };\n\n function redo_if_lambda(name, args, body) {\n body = redo_if(body);\n return [ this[0], name, args, body ];\n };\n\n function redo_if_block(statements) {\n return [ this[0], statements != null ? redo_if(statements) : null ];\n };\n\n return w.with_walkers({\n \"defun\": redo_if_lambda,\n \"function\": redo_if_lambda,\n \"block\": redo_if_block,\n \"splice\": redo_if_block,\n \"toplevel\": function(statements) {\n return [ this[0], redo_if(statements) ];\n },\n \"try\": function(t, c, f) {\n return [\n this[0],\n redo_if(t),\n c != null ? [ c[0], redo_if(c[1]) ] : null,\n f != null ? redo_if(f) : null\n ];\n }\n }, function() {\n return walk(ast);\n });\n};\n\nfunction for_side_effects(ast, handler) {\n var w = ast_walker(), walk = w.walk;\n var $stop = {}, $restart = {};\n function stop() { throw $stop };\n function restart() { throw $restart };\n function found(){ return handler.call(this, this, w, stop, restart) };\n function unary(op) {\n if (op == \"++\" || op == \"--\")\n return found.apply(this, arguments);\n };\n return w.with_walkers({\n \"try\": found,\n \"throw\": found,\n \"return\": found,\n \"new\": found,\n \"switch\": found,\n \"break\": found,\n \"continue\": found,\n \"assign\": found,\n \"call\": found,\n \"if\": found,\n \"for\": found,\n \"for-in\": found,\n \"while\": found,\n \"do\": found,\n \"return\": found,\n \"unary-prefix\": unary,\n \"unary-postfix\": unary,\n \"defun\": found\n }, function(){\n while (true) try {\n walk(ast);\n break;\n } catch(ex) {\n if (ex === $stop) break;\n if (ex === $restart) continue;\n throw ex;\n }\n });\n};\n\nfunction ast_lift_variables(ast) {\n var w = ast_walker(), walk = w.walk, scope;\n function do_body(body, env) {\n var _scope = scope;\n scope = env;\n body = MAP(body, walk);\n var hash = {}, names = MAP(env.names, function(type, name){\n if (type != \"var\") return MAP.skip;\n if (!env.references(name)) return MAP.skip;\n hash[name] = true;\n return [ name ];\n });\n if (names.length > 0) {\n // looking for assignments to any of these variables.\n // we can save considerable space by moving the definitions\n // in the var declaration.\n for_side_effects([ \"block\", body ], function(ast, walker, stop, restart) {\n if (ast[0] == \"assign\"\n && ast[1] === true\n && ast[2][0] == \"name\"\n && HOP(hash, ast[2][1])) {\n // insert the definition into the var declaration\n for (var i = names.length; --i >= 0;) {\n if (names[i][0] == ast[2][1]) {\n if (names[i][1]) // this name already defined, we must stop\n stop();\n names[i][1] = ast[3]; // definition\n names.push(names.splice(i, 1)[0]);\n break;\n }\n }\n // remove this assignment from the AST.\n var p = walker.parent();\n if (p[0] == \"seq\") {\n var a = p[2];\n a.unshift(0, p.length);\n p.splice.apply(p, a);\n }\n else if (p[0] == \"stat\") {\n p.splice(0, p.length, \"block\"); // empty statement\n }\n else {\n stop();\n }\n restart();\n }\n stop();\n });\n body.unshift([ \"var\", names ]);\n }\n scope = _scope;\n return body;\n };\n function _vardefs(defs) {\n var ret = null;\n for (var i = defs.length; --i >= 0;) {\n var d = defs[i];\n if (!d[1]) continue;\n d = [ \"assign\", true, [ \"name\", d[0] ], d[1] ];\n if (ret == null) ret = d;\n else ret = [ \"seq\", d, ret ];\n }\n if (ret == null) {\n if (w.parent()[0] == \"for-in\")\n return [ \"name\", defs[0][0] ];\n return MAP.skip;\n }\n return [ \"stat\", ret ];\n };\n function _toplevel(body) {\n return [ this[0], do_body(body, this.scope) ];\n };\n return w.with_walkers({\n \"function\": function(name, args, body){\n for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)\n args.pop();\n if (!body.scope.references(name)) name = null;\n return [ this[0], name, args, do_body(body, body.scope) ];\n },\n \"defun\": function(name, args, body){\n if (!scope.references(name)) return MAP.skip;\n for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)\n args.pop();\n return [ this[0], name, args, do_body(body, body.scope) ];\n },\n \"var\": _vardefs,\n \"toplevel\": _toplevel\n }, function(){\n return walk(ast_add_scope(ast));\n });\n};\n\nfunction ast_squeeze(ast, options) {\n options = defaults(options, {\n make_seqs : true,\n dead_code : true,\n keep_comps : true,\n no_warnings : false\n });\n\n var w = ast_walker(), walk = w.walk, scope;\n\n function negate(c) {\n var not_c = [ \"unary-prefix\", \"!\", c ];\n switch (c[0]) {\n case \"unary-prefix\":\n return c[1] == \"!\" && boolean_expr(c[2]) ? c[2] : not_c;\n case \"seq\":\n c = slice(c);\n c[c.length - 1] = negate(c[c.length - 1]);\n return c;\n case \"conditional\":\n return best_of(not_c, [ \"conditional\", c[1], negate(c[2]), negate(c[3]) ]);\n case \"binary\":\n var op = c[1], left = c[2], right = c[3];\n if (!options.keep_comps) switch (op) {\n case \"<=\" : return [ \"binary\", \">\", left, right ];\n case \"<\" : return [ \"binary\", \">=\", left, right ];\n case \">=\" : return [ \"binary\", \"<\", left, right ];\n case \">\" : return [ \"binary\", \"<=\", left, right ];\n }\n switch (op) {\n case \"==\" : return [ \"binary\", \"!=\", left, right ];\n case \"!=\" : return [ \"binary\", \"==\", left, right ];\n case \"===\" : return [ \"binary\", \"!==\", left, right ];\n case \"!==\" : return [ \"binary\", \"===\", left, right ];\n case \"&&\" : return best_of(not_c, [ \"binary\", \"||\", negate(left), negate(right) ]);\n case \"||\" : return best_of(not_c, [ \"binary\", \"&&\", negate(left), negate(right) ]);\n }\n break;\n }\n return not_c;\n };\n\n function with_scope(s, cont) {\n var _scope = scope;\n scope = s;\n var ret = cont();\n ret.scope = s;\n scope = _scope;\n return ret;\n };\n\n function rmblock(block) {\n if (block != null && block[0] == \"block\" && block[1]) {\n if (block[1].length == 1)\n block = block[1][0];\n else if (block[1].length == 0)\n block = [ \"block\" ];\n }\n return block;\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\";\n body = with_scope(body.scope, function(){\n var ret = tighten(body, \"lambda\");\n if (!is_defun && name && !scope.references(name))\n name = null;\n return ret;\n });\n return [ this[0], name, args, body ];\n };\n\n // this function does a few things:\n // 1. discard useless blocks\n // 2. join consecutive var declarations\n // 3. remove obviously dead code\n // 4. transform consecutive statements using the comma operator\n // 5. if block_type == \"lambda\" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }\n function tighten(statements, block_type) {\n statements = MAP(statements, walk);\n\n statements = statements.reduce(function(a, stat){\n if (stat[0] == \"block\") {\n if (stat[1]) {\n a.push.apply(a, stat[1]);\n }\n } else {\n a.push(stat);\n }\n return a;\n }, []);\n\n statements = (function(a, prev){\n statements.forEach(function(cur){\n if (prev && ((cur[0] == \"var\" && prev[0] == \"var\") ||\n (cur[0] == \"const\" && prev[0] == \"const\"))) {\n prev[1] = prev[1].concat(cur[1]);\n } else {\n a.push(cur);\n prev = cur;\n }\n });\n return a;\n })([]);\n\n if (options.dead_code) statements = (function(a, has_quit){\n statements.forEach(function(st){\n if (has_quit) {\n if (st[0] == \"function\" || st[0] == \"defun\") {\n a.push(st);\n }\n else if (st[0] == \"var\" || st[0] == \"const\") {\n if (!options.no_warnings)\n warn(\"Variables declared in unreachable code\");\n st[1] = MAP(st[1], function(def){\n if (def[1] && !options.no_warnings)\n warn_unreachable([ \"assign\", true, [ \"name\", def[0] ], def[1] ]);\n return [ def[0] ];\n });\n a.push(st);\n }\n else if (!options.no_warnings)\n warn_unreachable(st);\n }\n else {\n a.push(st);\n if (member(st[0], [ \"return\", \"throw\", \"break\", \"continue\" ]))\n has_quit = true;\n }\n });\n return a;\n })([]);\n\n if (options.make_seqs) statements = (function(a, prev) {\n statements.forEach(function(cur){\n if (prev && prev[0] == \"stat\" && cur[0] == \"stat\") {\n prev[1] = [ \"seq\", prev[1], cur[1] ];\n } else {\n a.push(cur);\n prev = cur;\n }\n });\n if (a.length >= 2\n && a[a.length-2][0] == \"stat\"\n && (a[a.length-1][0] == \"return\" || a[a.length-1][0] == \"throw\")\n && a[a.length-1][1])\n {\n a.splice(a.length - 2, 2,\n [ a[a.length-1][0],\n [ \"seq\", a[a.length-2][1], a[a.length-1][1] ]]);\n }\n return a;\n })([]);\n\n // this increases jQuery by 1K. Probably not such a good idea after all..\n // part of this is done in prepare_ifs anyway.\n // if (block_type == \"lambda\") statements = (function(i, a, stat){\n // while (i < statements.length) {\n // stat = statements[i++];\n // if (stat[0] == \"if\" && !stat[3]) {\n // if (stat[2][0] == \"return\" && stat[2][1] == null) {\n // a.push(make_if(negate(stat[1]), [ \"block\", statements.slice(i) ]));\n // break;\n // }\n // var last = last_stat(stat[2]);\n // if (last[0] == \"return\" && last[1] == null) {\n // a.push(make_if(stat[1], [ \"block\", stat[2][1].slice(0, -1) ], [ \"block\", statements.slice(i) ]));\n // break;\n // }\n // }\n // a.push(stat);\n // }\n // return a;\n // })(0, []);\n\n return statements;\n };\n\n function make_if(c, t, e) {\n return when_constant(c, function(ast, val){\n if (val) {\n warn_unreachable(e);\n return t;\n } else {\n warn_unreachable(t);\n return e;\n }\n }, function() {\n return make_real_if(c, t, e);\n });\n };\n\n function make_real_if(c, t, e) {\n c = walk(c);\n t = walk(t);\n e = walk(e);\n\n if (empty(t)) {\n c = negate(c);\n t = e;\n e = null;\n } else if (empty(e)) {\n e = null;\n } else {\n // if we have both else and then, maybe it makes sense to switch them?\n (function(){\n var a = gen_code(c);\n var n = negate(c);\n var b = gen_code(n);\n if (b.length < a.length) {\n var tmp = t;\n t = e;\n e = tmp;\n c = n;\n }\n })();\n }\n if (empty(e) && empty(t))\n return [ \"stat\", c ];\n var ret = [ \"if\", c, t, e ];\n if (t[0] == \"if\" && empty(t[3]) && empty(e)) {\n ret = best_of(ret, walk([ \"if\", [ \"binary\", \"&&\", c, t[1] ], t[2] ]));\n }\n else if (t[0] == \"stat\") {\n if (e) {\n if (e[0] == \"stat\") {\n ret = best_of(ret, [ \"stat\", make_conditional(c, t[1], e[1]) ]);\n }\n }\n else {\n ret = best_of(ret, [ \"stat\", make_conditional(c, t[1]) ]);\n }\n }\n else if (e && t[0] == e[0] && (t[0] == \"return\" || t[0] == \"throw\") && t[1] && e[1]) {\n ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);\n }\n else if (e && aborts(t)) {\n ret = [ [ \"if\", c, t ] ];\n if (e[0] == \"block\") {\n if (e[1]) ret = ret.concat(e[1]);\n }\n else {\n ret.push(e);\n }\n ret = walk([ \"block\", ret ]);\n }\n else if (t && aborts(e)) {\n ret = [ [ \"if\", negate(c), e ] ];\n if (t[0] == \"block\") {\n if (t[1]) ret = ret.concat(t[1]);\n } else {\n ret.push(t);\n }\n ret = walk([ \"block\", ret ]);\n }\n return ret;\n };\n\n function _do_while(cond, body) {\n return when_constant(cond, function(cond, val){\n if (!val) {\n warn_unreachable(body);\n return [ \"block\" ];\n } else {\n return [ \"for\", null, null, null, walk(body) ];\n }\n });\n };\n\n return w.with_walkers({\n \"sub\": function(expr, subscript) {\n if (subscript[0] == \"string\") {\n var name = subscript[1];\n if (is_identifier(name))\n return [ \"dot\", walk(expr), name ];\n else if (/^[1-9][0-9]*$/.test(name) || name === \"0\")\n return [ \"sub\", walk(expr), [ \"num\", parseInt(name, 10) ] ];\n }\n },\n \"if\": make_if,\n \"toplevel\": function(body) {\n return [ \"toplevel\", with_scope(this.scope, function(){\n return tighten(body);\n }) ];\n },\n \"switch\": function(expr, body) {\n var last = body.length - 1;\n return [ \"switch\", walk(expr), MAP(body, function(branch, i){\n var block = tighten(branch[1]);\n if (i == last && block.length > 0) {\n var node = block[block.length - 1];\n if (node[0] == \"break\" && !node[1])\n block.pop();\n }\n return [ branch[0] ? walk(branch[0]) : null, block ];\n }) ];\n },\n \"function\": _lambda,\n \"defun\": _lambda,\n \"block\": function(body) {\n if (body) return rmblock([ \"block\", tighten(body) ]);\n },\n \"binary\": function(op, left, right) {\n return when_constant([ \"binary\", op, walk(left), walk(right) ], function yes(c){\n return best_of(walk(c), this);\n }, function no() {\n return this;\n });\n },\n \"conditional\": function(c, t, e) {\n return make_conditional(walk(c), walk(t), walk(e));\n },\n \"try\": function(t, c, f) {\n return [\n \"try\",\n tighten(t),\n c != null ? [ c[0], tighten(c[1]) ] : null,\n f != null ? tighten(f) : null\n ];\n },\n \"unary-prefix\": function(op, expr) {\n expr = walk(expr);\n var ret = [ \"unary-prefix\", op, expr ];\n if (op == \"!\")\n ret = best_of(ret, negate(expr));\n return when_constant(ret, function(ast, val){\n return walk(ast); // it's either true or false, so minifies to !0 or !1\n }, function() { return ret });\n },\n \"name\": function(name) {\n switch (name) {\n case \"true\": return [ \"unary-prefix\", \"!\", [ \"num\", 0 ]];\n case \"false\": return [ \"unary-prefix\", \"!\", [ \"num\", 1 ]];\n }\n },\n \"while\": _do_while\n }, function() {\n for (var i = 0; i < 2; ++i) {\n ast = prepare_ifs(ast);\n ast = ast_add_scope(ast);\n ast = walk(ast);\n }\n return ast;\n });\n};\n\n/* -----[ re-generate code from the AST ]----- */\n\nvar DOT_CALL_NO_PARENS = jsp.array_to_hash([\n \"name\",\n \"array\",\n \"object\",\n \"string\",\n \"dot\",\n \"sub\",\n \"call\",\n \"regexp\"\n]);\n\nfunction make_string(str, ascii_only) {\n var dq = 0, sq = 0;\n str = str.replace(/[\\\\\\b\\f\\n\\r\\t\\x22\\x27\\u2028\\u2029]/g, function(s){\n switch (s) {\n case \"\\\\\": return \"\\\\\\\\\";\n case \"\\b\": return \"\\\\b\";\n case \"\\f\": return \"\\\\f\";\n case \"\\n\": return \"\\\\n\";\n case \"\\r\": return \"\\\\r\";\n case \"\\t\": return \"\\\\t\";\n case \"\\u2028\": return \"\\\\u2028\";\n case \"\\u2029\": return \"\\\\u2029\";\n case '\"': ++dq; return '\"';\n case \"'\": ++sq; return \"'\";\n }\n return s;\n });\n if (ascii_only) str = to_ascii(str);\n if (dq > sq) return \"'\" + str.replace(/\\x27/g, \"\\\\'\") + \"'\";\n else return '\"' + str.replace(/\\x22/g, '\\\\\"') + '\"';\n};\n\nfunction to_ascii(str) {\n return str.replace(/[\\u0080-\\uffff]/g, function(ch) {\n var code = ch.charCodeAt(0).toString(16);\n while (code.length < 4) code = \"0\" + code;\n return \"\\\\u\" + code;\n });\n};\n\nvar SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ \"if\", \"while\", \"do\", \"for\", \"for-in\", \"with\" ]);\n\nfunction gen_code(ast, options) {\n options = defaults(options, {\n indent_start : 0,\n indent_level : 4,\n quote_keys : false,\n space_colon : false,\n beautify : false,\n ascii_only : false,\n inline_script: false\n });\n var beautify = !!options.beautify;\n var indentation = 0,\n newline = beautify ? \"\\n\" : \"\",\n space = beautify ? \" \" : \"\";\n\n function encode_string(str) {\n var ret = make_string(str, options.ascii_only);\n if (options.inline_script)\n ret = ret.replace(/<\\x2fscript([>/\\t\\n\\f\\r ])/gi, \"<\\\\/script$1\");\n return ret;\n };\n\n function make_name(name) {\n name = name.toString();\n if (options.ascii_only)\n name = to_ascii(name);\n return name;\n };\n\n function indent(line) {\n if (line == null)\n line = \"\";\n if (beautify)\n line = repeat_string(\" \", options.indent_start + indentation * options.indent_level) + line;\n return line;\n };\n\n function with_indent(cont, incr) {\n if (incr == null) incr = 1;\n indentation += incr;\n try { return cont.apply(null, slice(arguments, 1)); }\n finally { indentation -= incr; }\n };\n\n function add_spaces(a) {\n if (beautify)\n return a.join(\" \");\n var b = [];\n for (var i = 0; i < a.length; ++i) {\n var next = a[i + 1];\n b.push(a[i]);\n if (next &&\n ((/[a-z0-9_\\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\\x24]/i.test(next.toString())) ||\n (/[\\+\\-]$/.test(a[i].toString()) && /^[\\+\\-]/.test(next.toString())))) {\n b.push(\" \");\n }\n }\n return b.join(\"\");\n };\n\n function add_commas(a) {\n return a.join(\",\" + space);\n };\n\n function parenthesize(expr) {\n var gen = make(expr);\n for (var i = 1; i < arguments.length; ++i) {\n var el = arguments[i];\n if ((el instanceof Function && el(expr)) || expr[0] == el)\n return \"(\" + gen + \")\";\n }\n return gen;\n };\n\n function best_of(a) {\n if (a.length == 1) {\n return a[0];\n }\n if (a.length == 2) {\n var b = a[1];\n a = a[0];\n return a.length <= b.length ? a : b;\n }\n return best_of([ a[0], best_of(a.slice(1)) ]);\n };\n\n function needs_parens(expr) {\n if (expr[0] == \"function\" || expr[0] == \"object\") {\n // dot/call on a literal function requires the\n // function literal itself to be parenthesized\n // only if it's the first \"thing\" in a\n // statement. This means that the parent is\n // \"stat\", but it could also be a \"seq\" and\n // we're the first in this \"seq\" and the\n // parent is \"stat\", and so on. Messy stuff,\n // but it worths the trouble.\n var a = slice(w.stack()), self = a.pop(), p = a.pop();\n while (p) {\n if (p[0] == \"stat\") return true;\n if (((p[0] == \"seq\" || p[0] == \"call\" || p[0] == \"dot\" || p[0] == \"sub\" || p[0] == \"conditional\") && p[1] === self) ||\n ((p[0] == \"binary\" || p[0] == \"assign\" || p[0] == \"unary-postfix\") && p[2] === self)) {\n self = p;\n p = a.pop();\n } else {\n return false;\n }\n }\n }\n return !HOP(DOT_CALL_NO_PARENS, expr[0]);\n };\n\n function make_num(num) {\n var str = num.toString(10), a = [ str.replace(/^0\\./, \".\") ], m;\n if (Math.floor(num) === num) {\n if (num >= 0) {\n a.push(\"0x\" + num.toString(16).toLowerCase(), // probably pointless\n \"0\" + num.toString(8)); // same.\n } else {\n a.push(\"-0x\" + (-num).toString(16).toLowerCase(), // probably pointless\n \"-0\" + (-num).toString(8)); // same.\n }\n if ((m = /^(.*?)(0+)$/.exec(num))) {\n a.push(m[1] + \"e\" + m[2].length);\n }\n } else if ((m = /^0?\\.(0+)(.*)$/.exec(num))) {\n a.push(m[2] + \"e-\" + (m[1].length + m[2].length),\n str.substr(str.indexOf(\".\")));\n }\n return best_of(a);\n };\n\n var w = ast_walker();\n var make = w.walk;\n return w.with_walkers({\n \"string\": encode_string,\n \"num\": make_num,\n \"name\": make_name,\n \"toplevel\": function(statements) {\n return make_block_statements(statements)\n .join(newline + newline);\n },\n \"splice\": function(statements) {\n var parent = w.parent();\n if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {\n // we need block brackets in this case\n return make_block.apply(this, arguments);\n } else {\n return MAP(make_block_statements(statements, true),\n function(line, i) {\n // the first line is already indented\n return i > 0 ? indent(line) : line;\n }).join(newline);\n }\n },\n \"block\": make_block,\n \"var\": function(defs) {\n return \"var \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n },\n \"const\": function(defs) {\n return \"const \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n },\n \"try\": function(tr, ca, fi) {\n var out = [ \"try\", make_block(tr) ];\n if (ca) out.push(\"catch\", \"(\" + ca[0] + \")\", make_block(ca[1]));\n if (fi) out.push(\"finally\", make_block(fi));\n return add_spaces(out);\n },\n \"throw\": function(expr) {\n return add_spaces([ \"throw\", make(expr) ]) + \";\";\n },\n \"new\": function(ctor, args) {\n args = args.length > 0 ? \"(\" + add_commas(MAP(args, make)) + \")\" : \"\";\n return add_spaces([ \"new\", parenthesize(ctor, \"seq\", \"binary\", \"conditional\", \"assign\", function(expr){\n var w = ast_walker(), has_call = {};\n try {\n w.with_walkers({\n \"call\": function() { throw has_call },\n \"function\": function() { return this }\n }, function(){\n w.walk(expr);\n });\n } catch(ex) {\n if (ex === has_call)\n return true;\n throw ex;\n }\n }) + args ]);\n },\n \"switch\": function(expr, body) {\n return add_spaces([ \"switch\", \"(\" + make(expr) + \")\", make_switch_block(body) ]);\n },\n \"break\": function(label) {\n var out = \"break\";\n if (label != null)\n out += \" \" + make_name(label);\n return out + \";\";\n },\n \"continue\": function(label) {\n var out = \"continue\";\n if (label != null)\n out += \" \" + make_name(label);\n return out + \";\";\n },\n \"conditional\": function(co, th, el) {\n return add_spaces([ parenthesize(co, \"assign\", \"seq\", \"conditional\"), \"?\",\n parenthesize(th, \"seq\"), \":\",\n parenthesize(el, \"seq\") ]);\n },\n \"assign\": function(op, lvalue, rvalue) {\n if (op && op !== true) op += \"=\";\n else op = \"=\";\n return add_spaces([ make(lvalue), op, parenthesize(rvalue, \"seq\") ]);\n },\n \"dot\": function(expr) {\n var out = make(expr), i = 1;\n if (expr[0] == \"num\") {\n if (!/\\./.test(expr[1]))\n out += \".\";\n } else if (needs_parens(expr))\n out = \"(\" + out + \")\";\n while (i < arguments.length)\n out += \".\" + make_name(arguments[i++]);\n return out;\n },\n \"call\": function(func, args) {\n var f = make(func);\n if (needs_parens(func))\n f = \"(\" + f + \")\";\n return f + \"(\" + add_commas(MAP(args, function(expr){\n return parenthesize(expr, \"seq\");\n })) + \")\";\n },\n \"function\": make_function,\n \"defun\": make_function,\n \"if\": function(co, th, el) {\n var out = [ \"if\", \"(\" + make(co) + \")\", el ? make_then(th) : make(th) ];\n if (el) {\n out.push(\"else\", make(el));\n }\n return add_spaces(out);\n },\n \"for\": function(init, cond, step, block) {\n var out = [ \"for\" ];\n init = (init != null ? make(init) : \"\").replace(/;*\\s*$/, \";\" + space);\n cond = (cond != null ? make(cond) : \"\").replace(/;*\\s*$/, \";\" + space);\n step = (step != null ? make(step) : \"\").replace(/;*\\s*$/, \"\");\n var args = init + cond + step;\n if (args == \"; ; \") args = \";;\";\n out.push(\"(\" + args + \")\", make(block));\n return add_spaces(out);\n },\n \"for-in\": function(vvar, key, hash, block) {\n return add_spaces([ \"for\", \"(\" +\n (vvar ? make(vvar).replace(/;+$/, \"\") : make(key)),\n \"in\",\n make(hash) + \")\", make(block) ]);\n },\n \"while\": function(condition, block) {\n return add_spaces([ \"while\", \"(\" + make(condition) + \")\", make(block) ]);\n },\n \"do\": function(condition, block) {\n return add_spaces([ \"do\", make(block), \"while\", \"(\" + make(condition) + \")\" ]) + \";\";\n },\n \"return\": function(expr) {\n var out = [ \"return\" ];\n if (expr != null) out.push(make(expr));\n return add_spaces(out) + \";\";\n },\n \"binary\": function(operator, lvalue, rvalue) {\n var left = make(lvalue), right = make(rvalue);\n // XXX: I'm pretty sure other cases will bite here.\n // we need to be smarter.\n // adding parens all the time is the safest bet.\n if (member(lvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n lvalue[0] == \"binary\" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] ||\n lvalue[0] == \"function\" && needs_parens(this)) {\n left = \"(\" + left + \")\";\n }\n if (member(rvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n rvalue[0] == \"binary\" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&\n !(rvalue[1] == operator && member(operator, [ \"&&\", \"||\", \"*\" ]))) {\n right = \"(\" + right + \")\";\n }\n else if (!beautify && options.inline_script && (operator == \"<\" || operator == \"<<\")\n && rvalue[0] == \"regexp\" && /^script/i.test(rvalue[1])) {\n right = \" \" + right;\n }\n return add_spaces([ left, operator, right ]);\n },\n \"unary-prefix\": function(operator, expr) {\n var val = make(expr);\n if (!(expr[0] == \"num\" || (expr[0] == \"unary-prefix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n val = \"(\" + val + \")\";\n return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? \" \" : \"\") + val;\n },\n \"unary-postfix\": function(operator, expr) {\n var val = make(expr);\n if (!(expr[0] == \"num\" || (expr[0] == \"unary-postfix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n val = \"(\" + val + \")\";\n return val + operator;\n },\n \"sub\": function(expr, subscript) {\n var hash = make(expr);\n if (needs_parens(expr))\n hash = \"(\" + hash + \")\";\n return hash + \"[\" + make(subscript) + \"]\";\n },\n \"object\": function(props) {\n if (props.length == 0)\n return \"{}\";\n return \"{\" + newline + with_indent(function(){\n return MAP(props, function(p){\n if (p.length == 3) {\n // getter/setter. The name is in p[0], the arg.list in p[1][2], the\n // body in p[1][3] and type (\"get\" / \"set\") in p[2].\n return indent(make_function(p[0], p[1][2], p[1][3], p[2]));\n }\n var key = p[0], val = parenthesize(p[1], \"seq\");\n if (options.quote_keys) {\n key = encode_string(key);\n } else if ((typeof key == \"number\" || !beautify && +key + \"\" == key)\n && parseFloat(key) >= 0) {\n key = make_num(+key);\n } else if (!is_identifier(key)) {\n key = encode_string(key);\n }\n return indent(add_spaces(beautify && options.space_colon\n ? [ key, \":\", val ]\n : [ key + \":\", val ]));\n }).join(\",\" + newline);\n }) + newline + indent(\"}\");\n },\n \"regexp\": function(rx, mods) {\n return \"/\" + rx + \"/\" + mods;\n },\n \"array\": function(elements) {\n if (elements.length == 0) return \"[]\";\n return add_spaces([ \"[\", add_commas(MAP(elements, function(el, i){\n if (!beautify && el[0] == \"atom\" && el[1] == \"undefined\") return i === elements.length - 1 ? \",\" : \"\";\n return parenthesize(el, \"seq\");\n })), \"]\" ]);\n },\n \"stat\": function(stmt) {\n return make(stmt).replace(/;*\\s*$/, \";\");\n },\n \"seq\": function() {\n return add_commas(MAP(slice(arguments), make));\n },\n \"label\": function(name, block) {\n return add_spaces([ make_name(name), \":\", make(block) ]);\n },\n \"with\": function(expr, block) {\n return add_spaces([ \"with\", \"(\" + make(expr) + \")\", make(block) ]);\n },\n \"atom\": function(name) {\n return make_name(name);\n }\n }, function(){ return make(ast) });\n\n // The squeezer replaces \"block\"-s that contain only a single\n // statement with the statement itself; technically, the AST\n // is correct, but this can create problems when we output an\n // IF having an ELSE clause where the THEN clause ends in an\n // IF *without* an ELSE block (then the outer ELSE would refer\n // to the inner IF). This function checks for this case and\n // adds the block brackets if needed.\n function make_then(th) {\n if (th[0] == \"do\") {\n // https://github.com/mishoo/UglifyJS/issues/#issue/57\n // IE croaks with \"syntax error\" on code like this:\n // if (foo) do ... while(cond); else ...\n // we need block brackets around do/while\n return make_block([ th ]);\n }\n var b = th;\n while (true) {\n var type = b[0];\n if (type == \"if\") {\n if (!b[3])\n // no else, we must add the block\n return make([ \"block\", [ th ]]);\n b = b[3];\n }\n else if (type == \"while\" || type == \"do\") b = b[2];\n else if (type == \"for\" || type == \"for-in\") b = b[4];\n else break;\n }\n return make(th);\n };\n\n function make_function(name, args, body, keyword) {\n var out = keyword || \"function\";\n if (name) {\n out += \" \" + make_name(name);\n }\n out += \"(\" + add_commas(MAP(args, make_name)) + \")\";\n return add_spaces([ out, make_block(body) ]);\n };\n\n function must_has_semicolon(node) {\n switch (node[0]) {\n case \"with\":\n case \"while\":\n return empty(node[2]); // `with' or `while' with empty body?\n case \"for\":\n case \"for-in\":\n return empty(node[4]); // `for' with empty body?\n case \"if\":\n if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else'\n if (node[3]) {\n if (empty(node[3])) return true; // `else' present but empty\n return must_has_semicolon(node[3]); // dive into the `else' branch\n }\n return must_has_semicolon(node[2]); // dive into the `then' branch\n }\n };\n\n function make_block_statements(statements, noindent) {\n for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {\n var stat = statements[i];\n var code = make(stat);\n if (code != \";\") {\n if (!beautify && i == last && !must_has_semicolon(stat)) {\n code = code.replace(/;+\\s*$/, \"\");\n }\n a.push(code);\n }\n }\n return noindent ? a : MAP(a, indent);\n };\n\n function make_switch_block(body) {\n var n = body.length;\n if (n == 0) return \"{}\";\n return \"{\" + newline + MAP(body, function(branch, i){\n var has_body = branch[1].length > 0, code = with_indent(function(){\n return indent(branch[0]\n ? add_spaces([ \"case\", make(branch[0]) + \":\" ])\n : \"default:\");\n }, 0.5) + (has_body ? newline + with_indent(function(){\n return make_block_statements(branch[1]).join(newline);\n }) : \"\");\n if (!beautify && has_body && i < n - 1)\n code += \";\";\n return code;\n }).join(newline) + newline + indent(\"}\");\n };\n\n function make_block(statements) {\n if (!statements) return \";\";\n if (statements.length == 0) return \"{}\";\n return \"{\" + newline + with_indent(function(){\n return make_block_statements(statements).join(newline);\n }) + newline + indent(\"}\");\n };\n\n function make_1vardef(def) {\n var name = def[0], val = def[1];\n if (val != null)\n name = add_spaces([ make_name(name), \"=\", parenthesize(val, \"seq\") ]);\n return name;\n };\n\n};\n\nfunction split_lines(code, max_line_length) {\n var splits = [ 0 ];\n jsp.parse(function(){\n var next_token = jsp.tokenizer(code);\n var last_split = 0;\n var prev_token;\n function current_length(tok) {\n return tok.pos - last_split;\n };\n function split_here(tok) {\n last_split = tok.pos;\n splits.push(last_split);\n };\n function custom(){\n var tok = next_token.apply(this, arguments);\n out: {\n if (prev_token) {\n if (prev_token.type == \"keyword\") break out;\n }\n if (current_length(tok) > max_line_length) {\n switch (tok.type) {\n case \"keyword\":\n case \"atom\":\n case \"name\":\n case \"punc\":\n split_here(tok);\n break out;\n }\n }\n }\n prev_token = tok;\n return tok;\n };\n custom.context = function() {\n return next_token.context.apply(this, arguments);\n };\n return custom;\n }());\n return splits.map(function(pos, i){\n return code.substring(pos, splits[i + 1] || code.length);\n }).join(\"\\n\");\n};\n\n/* -----[ Utilities ]----- */\n\nfunction repeat_string(str, i) {\n if (i <= 0) return \"\";\n if (i == 1) return str;\n var d = repeat_string(str, i >> 1);\n d += d;\n if (i & 1) d += str;\n return d;\n};\n\nfunction defaults(args, defs) {\n var ret = {};\n if (args === true)\n args = {};\n for (var i in defs) if (HOP(defs, i)) {\n ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];\n }\n return ret;\n};\n\nfunction is_identifier(name) {\n return /^[a-z_$][a-z0-9_$]*$/i.test(name)\n && name != \"this\"\n && !HOP(jsp.KEYWORDS_ATOM, name)\n && !HOP(jsp.RESERVED_WORDS, name)\n && !HOP(jsp.KEYWORDS, name);\n};\n\nfunction HOP(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\n// some utilities\n\nvar MAP;\n\n(function(){\n MAP = function(a, f, o) {\n var ret = [], top = [], i;\n function doit() {\n var val = f.call(o, a[i], i);\n if (val instanceof AtTop) {\n val = val.v;\n if (val instanceof Splice) {\n top.push.apply(top, val.v);\n } else {\n top.push(val);\n }\n }\n else if (val != skip) {\n if (val instanceof Splice) {\n ret.push.apply(ret, val.v);\n } else {\n ret.push(val);\n }\n }\n };\n if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();\n else for (i in a) if (HOP(a, i)) doit();\n return top.concat(ret);\n };\n MAP.at_top = function(val) { return new AtTop(val) };\n MAP.splice = function(val) { return new Splice(val) };\n var skip = MAP.skip = {};\n function AtTop(val) { this.v = val };\n function Splice(val) { this.v = val };\n})();\n\n/* -----[ Exports ]----- */\n\nexports.ast_walker = ast_walker;\nexports.ast_mangle = ast_mangle;\nexports.ast_squeeze = ast_squeeze;\nexports.ast_lift_variables = ast_lift_variables;\nexports.gen_code = gen_code;\nexports.ast_add_scope = ast_add_scope;\nexports.set_logger = function(logger) { warn = logger };\nexports.make_string = make_string;\nexports.split_lines = split_lines;\nexports.MAP = MAP;\n\n// keep this last!\nexports.ast_squeeze_more = require(\"./squeeze-more\").ast_squeeze_more;\n\n});");spade.register("uglify-js/squeeze-more", "(function(require, exports, __module, ARGV, ENV, __filename){var jsp = require(\"./parse-js\"),\n pro = require(\"./process\"),\n slice = jsp.slice,\n member = jsp.member,\n curry = jsp.curry,\n MAP = pro.MAP,\n PRECEDENCE = jsp.PRECEDENCE,\n OPERATORS = jsp.OPERATORS;\n\nfunction ast_squeeze_more(ast) {\n var w = pro.ast_walker(), walk = w.walk, scope;\n function with_scope(s, cont) {\n var save = scope, ret;\n scope = s;\n ret = cont();\n scope = save;\n return ret;\n };\n function _lambda(name, args, body) {\n return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];\n };\n return w.with_walkers({\n \"toplevel\": function(body) {\n return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];\n },\n \"function\": _lambda,\n \"defun\": _lambda,\n \"new\": function(ctor, args) {\n if (ctor[0] == \"name\" && ctor[1] == \"Array\" && !scope.has(\"Array\")) {\n if (args.length != 1) {\n return [ \"array\", args ];\n } else {\n return walk([ \"call\", [ \"name\", \"Array\" ], args ]);\n }\n }\n },\n \"call\": function(expr, args) {\n if (expr[0] == \"dot\" && expr[2] == \"toString\" && args.length == 0) {\n // foo.toString() ==> foo+\"\"\n return [ \"binary\", \"+\", expr[1], [ \"string\", \"\" ]];\n }\n if (expr[0] == \"name\" && expr[1] == \"Array\" && args.length != 1 && !scope.has(\"Array\")) {\n return [ \"array\", args ];\n }\n }\n }, function() {\n return walk(pro.ast_add_scope(ast));\n });\n};\n\nexports.ast_squeeze_more = ast_squeeze_more;\n\n});");// BPM PLUGIN: uglify-js/plugins/minifier
(function(exports) {
/*globals exports spade */
exports.minify = function(orig_code, pkg) {
var jsp = spade.require("uglify-js/parse-js");
var pro = spade.require("uglify-js/process");
var ast = jsp.parse(orig_code); // parse code and get the initial AST
ast = pro.ast_mangle(ast); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
return pro.gen_code(ast); // compressed code here
};
})(BPM_PLUGIN);
; // Safety
CTX = {"package":{"name":"uglify-js","author":"Mihai Bazon","summary":"AST-powered minifier for JavaScript","description":"Minify JavaScript applications. Includes plugin support for bpm.","version":"1.0.7","repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"},"homepage":"http://github.com/getbpm/UglifyJS","bpm:provides":{"minifier":"uglify-js/plugins/minifier"},"directories":{"lib":"lib","plugins":"plugins"},"dependencies":{"spade":"~> 1.0.0"}},"moduleId":null,"settings":{"files":[],"minifier":"uglify-js"}};
CTX.minify = function(body){ return body; };
DATA = "\n";
window={};
if (typeof BPM_PLUGIN === 'undefined') BPM_PLUGIN={};
// ==========================================================================
// Project: Spade - CommonJS Runtime
// Copyright: ©2010 Strobe Inc. All rights reserved.
// License: Licened under MIT license
// ==========================================================================
/*jslint evil:true */
/*globals spade ARGS ARGV ENV __module ActiveXObject */
(function() {
var K, Sandbox, Sp, Evaluator, Ep, Loader, Lp, Spade, Tp;
// ..........................................................
// HELPER FUNCTIONS
//
K = function() {}; // noop
// assume id is already normalized
function packageIdFor(normalizedId) {
return normalizedId.slice(0, normalizedId.indexOf('/'));
}
function remap(id, contextPkg) {
var mappings = contextPkg ? contextPkg.mappings : null;
if (!mappings) { return id; }
var packageId = packageIdFor(id);
if (mappings[packageId]) {
id = mappings[packageId] + id.slice(id.indexOf('/'));
}
return id;
}
// convert a relative or otherwise de-normalized module id into canoncial form
// normalize('./foo', 'bar/baz') -> 'bar/foo'
// normalize('foo', 'bar/baz') -> 'foo/main' (or foo/~package is asPackage)
// normalize('foo/bar', 'bar/baz') -> 'foo/bar'
function normalize(id, contextId, contextPkg, _asPackage) {
var idx, len;
// slice separator off the end since it is not used...
if (id[id.length-1]==='/') { id = id.slice(0,-1); }
// need to walk if there is a .
if (id.indexOf('.')>=0) {
var parts = contextId && (id.charAt(0) ==='.') ? contextId.split('/') : [],
part, next,
packageName = parts[0],
needsCleanup = false;
idx = 0;
len = id.length;
if (contextPkg && contextPkg.main && contextId === packageName+'/main') {
// If we're requiring from main we need to handle relative requires specially
needsCleanup = true;
parts = contextPkg.main.replace(/^\.?\//, '').split('/');
}
parts.pop(); // get rid of the last path element since it is a module.
while(idx<len) {
next = id.indexOf('/', idx);
if (next<0) { next = len; }
part = id.slice(idx, next);
if (part==='..') { parts.pop(); }
else if (part!=='.' && part!=='' && part!==null) { parts.push(part); }
// skip .., empty, and null.
idx = next+1;
}
id = parts.join('/');
if (needsCleanup) {
var libPaths = contextPkg.directories.lib;
for (idx=0,len=libPaths.length; idx<len; idx++){
id = id.replace(libPaths[idx].replace(/^\.?\//, '')+'/', '');
}
id = packageName+'/'+id;
}
// else, just slice off beginning '/' if needed
} else if (id[0]==='/') { id = id.slice(1); }
// if we end up with no separators, make this a pkg
if (id.indexOf('/')<0) { id = id+(_asPackage ? '/~package' : '/main'); }
// slice separators off begin and end
if (id[0]==='/') { id = id.slice(1); }
// Remove unnecessary ~lib references
id = id.replace('~lib/', '');
return remap(id, contextPkg);
}
// ..........................................................
// SANDBOX - you could make a secure version if you want
//
// runs a factory within context and returns exports...
function execFactory(id, factory, sandbox, spade) {
var require, mod, factoryData, fullId;
var filename = factory.filename,
ARGV = sandbox.ARGV,
ENV = sandbox.ENV;
require = sandbox.makeRequire(id, spade);
sandbox._modules[id] = mod = {
id: id,
exports: {},
sandbox: sandbox
};
factoryData = factory.data; // extract the raw module body
// evaluate if needed - use cache so we only do it once per sandbox
if ('string' === typeof factoryData) {
if (sandbox._factories[id]) {
factoryData = sandbox._factories[id];
} else {
sandbox._loading[id] = true;
// The __evalFunc keeps IE 9 happy since it doesn't like
// unassigned anonymous functions
factoryData = sandbox.evaluate('__evalFunc = '+factoryData+'\n//@ sourceURL='+filename+'\n', filename);
sandbox._factories[id] = factoryData;
sandbox._loading[id] = false;
}
}
if ('function' === typeof factoryData) {
var ret = factoryData(require, mod.exports, mod, ARGV, ENV, filename);
if (ret !== undefined) { mod.exports = ret; } // allow return exports
} else {
mod.exports = factoryData;
}
return mod.exports;
}
/**
@constructor
Sandbox provides an isolated context for loading and running modules.
You can create new sandboxes anytime you want. If you pass true for the
isolate flag, then the sandbox will be created in a separate context if
supported on the platform. Otherwise it will share globals with the
default sandbox context.
Note that isolated sandboxes are not the same as secure sandboxes. For
example in the browser, a isolated sandbox is created using an iframe
which still exposes access to the DOM and parent environment.
Isolated sandboxes are mostly useful for testing and sharing plugin code
that might want to use different versions of packages.
@param {Spade} spade
The spade instance
@param {String} name
(Optional) name of the sandbox for debugging purposes
@param {Boolean} isolate
Set to true if you want to isolate it
@returns {Sandbox} instance
*/
Sandbox = function(spade, name, isolate) {
// name parameter is optional
if (typeof name !== 'string') {
isolate = name;
name = null;
}
if (!name) { name = '(anonymous)'; }
this.spade = spade;
this.name = name;
this.isIsolated = !!isolate;
this._factories = {}; // evaluated factories
this._loading = {}; // list of loading modules
this._modules = {}; // cached export results
this._used = {}; // to detect circular references
};
// alias this to help minifier make the page a bit smaller.
Sp = Sandbox.prototype;
Sp.toString = function() {
return '[Sandbox '+this.name+']';
};
/**
Evaluate the passed string in the Sandbox context, returning the result.
This is the primitive used to evalute string-encoded factories into
modules that can execute within a specific context.
*/
Sp.evaluate = function(code, filename) {
if (this.isDestroyed) { throw new Error("Sandbox destroyed"); }
if (!this._evaluatorInited) {
this._evaluatorInited = true;
this.spade.evaluator.setup(this);
}
return this.spade.evaluator.evaluate(code, this, filename);
};
/**
NOTE: This is a primitive form of the require() method. Usually you should
use the require() method defined in your module.
Sandbox-specific require. This is the most primitive form of require. All
other requires() pass through here.
@param {String} id
The module id you want to require.
@param {String} callingId
(Optional) The id of the module requiring the module. This is needed if
you the id you pass in might be relative.
@returns {Object} exports of the required module
*/
Sp.require = function(id, callingId) {
var spade = this.spade,
pkg, ret, factory;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
ret = this._modules[id];
if (ret) { ret = ret.exports; }
if (ret) {
// save so we can detect circular references later
if (!this._used[id]) { this._used[id] = ret; }
return ret ;
} else {
factory = spade.loadFactory(spade.resolve(id, this));
if (!factory) { throw new Error('Module '+id+' not found'); }
if (!this.ENV) { this.ENV = spade.env(); } // get at the last minute
if (!this.ARGV) { this.ARGV = spade.argv(); }
ret = execFactory(id, factory, this, spade);
if (this._used[id] && (this._used[id] !== ret)) {
throw new Error("Circular require detected for module "+id);
}
}
return ret ;
};
/**
NOTE: This is a primitive form of the exists() method. Usually you should
use the require.exists() method defined on the require() function in your
module.
Sandbox-specific test to determine if the named module exists or not.
This property only reflects what is immediately available through the
sync-loader. Using the async loader may change the return value of this
call.
@param {String} id
The module id you want to test
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@returns {Object} exports of the required module
*/
Sp.exists = function(id, callingId) {
var spade = this.spade, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
if (this._modules[id]) { return true; }
return spade.factoryExists(spade.resolve(id, this));
};
/**
NOTE: This is a primitive form of the async() method. Usually you should
use the require.async() method defined on the require() function in your
module.
Asynchronously attempts to load a module, invoking a callback if and when
the module is loaded. If the module is already defined, the callback will
be invoked immediately. Otherwise, this will use the Loader plugin on the
main spade context to attempt to load the module. If the module cannot
be loaded, the callback will be invoked with an error object as its first
parameter to inform you that it failed.
Note that the default Loader that ships with spade is not actually capable
of asynchronously loading modules, which means this method will always fail
unless the module is already present. You can use the spade-loader package
to install an async loader that will work.
@param {String} id
The module id you want to load
@param {Function} callback
A callback to invoke when the module is loaded or if the load has failed.
The calback should expect an error object (or null) as the first
parameter.
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@returns {void}
*/
Sp.async = function(id, callback, callingId) {
var spade = this.spade, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = spade.resolve(normalize(id, callingId, pkg), this);
spade.loadFactory(id, callback);
};
/**
NOTE: This is a primitive form of the url() method. Usually you should
use the require.url() method defined on the require() function in your
module.
Returns the URL of the given resource based on the settings of the named
package. This method requires the package information to include a `root`
property that defines the root URL where resources can be found.
This method is useful for finding non-JavaScript resources such as images,
video, etc.
@param {String} id
A module id form of the reference you want to load.
@param {String} ext
(Optional) and extension to append to the returned URL.
@param {String} callingId
(Optional) The id of the module requesting the module. Required if the id
you pass in might be relative.
@param {String} the computed URL.
*/
Sp.url = function(id, ext, callingId) {
var spade = this.spade, ret, pkg;
pkg = callingId ? spade.package(callingId) : null;
id = normalize(id, callingId, pkg);
pkg = spade.package(id);
if (!pkg) {
var packageId = packageIdFor(id)+'/~package';
if (spade.exists(packageId)) { spade.require(packageId); }
pkg = spade.package(id);
}
if (!pkg) {
throw new Error("Can't get url for non-existent package "+id);
}
if (!pkg.root) {
throw new Error('Package for '+id+' does not support urls');
}
ret = pkg.root + id.slice(id.indexOf('/'));
if (ext) { ret = ret+'.'+ext; }
return ret ;
};
Sp.isDestroyed = false;
Sp.destroy = function() {
if (!this.isDestroyed) {
this.isDestroyed = true;
this.spade.evaluator.teardown(this);
}
return this;
};
/**
Return a new require function for the normalized module ID. Normally you
would not call this method yourself but you might override it if you want
to add new API to the require() methods passed into modules.
*/
Sp.makeRequire = function(id, spade) {
var pkg = spade.package(id),
sandbox = this,
require;
require = function(moduleId) {
return sandbox.require(moduleId, id, pkg);
};
// make the require 'object' have the same API as sandbox and spade.
require.require = require;
require.exists = function(moduleId) {
return sandbox.exists(normalize(moduleId, id, pkg));
};
require.normalize = function(moduleId) {
return normalize(moduleId, id, pkg);
};
require.async = function(moduleId, callback) {
return sandbox.async(normalize(moduleId, id, pkg), callback);
};
require.sandbox = function(name, isolate) {
return spade.sandbox(name, isolate);
};
require.url = function(moduleId, ext) {
return sandbox.url(normalize(moduleId, id, pkg), ext);
};
require.id = id; // so you can tell one require from another
return require;
};
// ..........................................................
// LOADER
//
/**
@constructor
The Loader object is used to asynchronously load modules from the server.
It also provides other low-level URL resolution and event handling
functions needed to integrate with the low-level environment. The default
implementation does not support any kind of async loading. See the
spade-loader package for a way to add support for this.
*/
Loader = function() {
this._loading = {};
};
Lp = Loader.prototype;
/**
Called by spade whenever a module is requested that has not already been
registered in memory. This function should attempt to load the module if
possible, registering any packages on the spade instance.
If a `done` is a function, then this method should run asynchronously -
invoking the callback when complete. If the load failed, this method should
pass an error as the first parameter. Otherwise it should not pass any
parameter.
If `done` is null, then this method should run synchronously and then simply
return when it is complete. If the named module cannot be loaded, you can
just return with no errors as the spade environment will detect this
condition and fail.
Note that loaders are not required to support both sync and async loading.
If you don't support one or the other, simply throw an error.
@method
@param {Spade} spade
The spade instance.
@param {String} id
The normalized module id to load.
@param {Function} done
(Optional) if passed, run this function async and invoke the done callback
when complete.
@returns {void}
*/
Lp.loadFactory = null;
/**
Called by spade whenever it wants to detect if a given module exists and the
id is not yet registered with the spade instance.
This method should do its best to determine if the module exists and return
the appropriate value. Note that if you only support async loading of
modules then you may not be able to detect when a module is defined outside
of what is already registered. In this case it is OK to simply return false.
@method
@param {Spade} spade
The spade instance.
@param {String} id
The normalized module id to load
@returns {Boolean} true if module exists
*/
Lp.exists = null;
// NOTE: On ready stuff mostly stolen from jQuery 1.4. Need to incl here
// because spade will often be used to load jQuery.
// Will only be invoked once. Just be prepared to call it
/**
Called once by spade on page load to schedule a ready callback, which should
be invoked once the documents 'ready' event (or an equivalent) is fired.
You should never call this method yourself but you might override it when
using spade outside of a proper browser.
@param {Function} callback
The callback to be invoked when the document is 'ready'.
@returns {void}
*/
Lp.scheduleReady = function(callback) {
// handle case where ready is invoked AFTER the document is already ready
if ( document.readyState === "complete" ) { return setTimeout(callback, 1); }
var handler, handled = false;
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if (handled) { return; }
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
handler();
}
// Mozilla, Opera and webkit nightlies currently support this event
if (document.addEventListener) {
handler = function() {
if (handled) { return; }
handled = true;
document.removeEventListener("DOMContentLoaded", handler, false);
window.removeEventListener('load', handler, false);
callback();
};
document.addEventListener( "DOMContentLoaded", handler, false);
// A fallback to window.onload, that will always work
window.addEventListener( "load", handler, false );
// If IE event model is used
} else if ( document.attachEvent ) {
handler = function() {
if (!handled && document.readyState === "complete") {
handled = true;
document.detachEvent( "onreadystatechange", handler );
window.detachEvent('onload', handler);
callback();
}
};
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", handler);
// A fallback to window.onload, that will always work
window.attachEvent( "onload", handler);
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement === null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); }
}
};
// ..........................................................
// Evaluator Class
//
/**
@constructor
An Evaluator instance is used to evaluate code inside of a sandbox. A
default instance is created on spade and used automatically by sandboxes.
You can extend this class and replace the default one on spade in order to
provide additional new features, such as sandbox isolation or secure eval.
The default Evaluator simply evals code in the current context using the
built-in eval() function. It does not support isolated sandboxes. To add
isolated sandbox support, add the `spade-isolate` package.
*/
Evaluator = function() {};
Ep = Evaluator.prototype;
/**
Called once on each new sandbox to allow the evaluator to setup any required
context for future calls. For isolated sandboxes, this is usually where
you would create the new compilation context and store it on the sandbox for
future use.
The default implementation does nothing, but will throw an exception if you
try to setup a new isolated sandbox. (Since the feature is not supported.).
If you override this method, you do not need to call the default function.
@param {Sandbox} sandbox
The sandbox to setup.
@returns {void}
*/
Ep.setup = function(sandbox) {
if (sandbox.isIsolated) {
throw new Error("Isolated sandboxes are not supported.");
}
};
/**
Evaluates the passed JavaScript within the context of a sandbox and returns
the resulting value (usually a function). The default version simply calls
the built-in eval().
@param {String} text
The code to evaluate.
@param {Sandbox} sandbox
The sandbox owning the code.
@param {String} filename
An optional filename to associate with the text (may be useful for debug
support)
@returns {Object} evaluated result.
*/
Ep.evaluate = function(text, sandbox, filename) {
return eval(text);
};
/**
Called once by the sandbox when it is destroyed to allow the evaluator to
cleanup any data it might have stashed on the sandbox. For isolated
sandboxes, this method might destroy the compilation context to allow its
memory to be reclaimed.
Since the default evaluator does not support isolated contexts, this method
is a no-op.
@param {Sandbox} sandbox
The sandbox about to be destroyed.
@returns {void}
*/
Ep.teardown = function(sandbox) {
// noop by default
};
// ..........................................................
// Spade Class - defined so we can recreate
//
/**
@constructor
The root object used to coordinate the entire spade environment. A global
instance of this class is created on page load called `spade`. Most of the
time you will only interact with this object directly to register new
modules and perhaps to load a new module outside of traditional module code.
Note that if you are using BPM and your app is actually published as modules
then you won't actually need reference this object at all as the details are
handled for you.
# Registering a Module
If you are manually constructing a JavaScript file to load from the server
and you want to register new modules, you will need to use the
`spade.register()` method:
spade.register('package_name/module_name', function() { ... });
This will make the module `package_name/module_name` available to all other
modules. The first time the module is required, your passed function will
be called.
You can also register metadata about a package by registering the
`package_name/~package` module:
spade.register('package_name/~package', {
"name": "package_name",
"version": "1.0.0",
...
});
Note that in addition to factory functions you can also pass in JSON hashes
(which will simply be returned directory) or a string of code - which will
be eval'd on demand.
The string format is particularly important because defining modules as
strings can dramatically improve load time on mobile devices while also
allowing you to easily support isolated sandbox contexts.
# Requiring a Module
Normally when you write module code that is managed by Spade you will have
a `require()` method defined within the module that you should use to load
modules.
If you happen to be writing code outside of a spade module and need to
require a module, however, you can use the `spade.require()` method instead:
var jQuery = spade.require('jquery');
This works just like the built-in require method except it will not support
relative modules (since there is no module to be relative too). This
method will require modules from the default sandbox, found at
`spade.defaultSandbox`.
# Plugins
Spade supports a number of plugins that you can use to enhance the way
spade discovers and loads modules. The two plugins currently supported are
a `loader` and `evaluator`.
The `loader` plugin is used to asynchronously discover and load modules. It
expects the object to be an instance of Spade.Loader. See `Loader`
documentation for more information.
The `evaluator` plugin is used to evaluate code within a sandbox context. It
can be enhanced to support isolated sandboxes as well as worker threads and
many other contexts. See the `Evaluator` documentation for more
information.
*/
Spade = function() {
this.loader = new this.Loader(this);
this.evaluator = new this.Evaluator(this);
this.defaultSandbox = this.sandbox();
this._factories = {};
this._packages = {};
};
Tp = Spade.prototype;
Tp.VERSION = "1.0.0";
// expose the classes. We do it this way so that you can create a new
// Spade instance and treat it like the spade module
Tp.Spade = Spade;
Tp.Sandbox = Sandbox;
Tp.Loader = Loader;
Tp.Evaluator = Evaluator;
/**
Computes and returns a normalized ENV hash. By default this will look for
a globally defined variable called `ENV` and use that. If not defined,
it will look for a locally defined `ENV` variable instead.
In either case, this method will also normalize the variable to include at
least the `LANG` and `SPADE_PLATFORM` properties.
@returns {Hash} the environment hash
*/
Tp.env = function() {
var env = this.ENV;
if (!env) { this.ENV = env = ('undefined' !== typeof ENV) ? ENV : {}; }
if (!env.SPADE_PLATFORM) { env.SPADE_PLATFORM = 'browser'; }
if (!env.LANG) {
env.LANG = ('undefined' !== typeof navigator) ? navigator.language : 'en-US';
}
return env;
};
/**
Computes and returns the ARGV array for the current spade environment. By
default this will look for a globally defined variable called `ARGV` and
use that.
ARGV is a useful way to pass in startup options to spade modules.
@returns {Array} the argv array
*/
Tp.argv = function() {
var argv = this.ARGV;
if (!argv) { argv= this.ARGV = ('undefined' !== typeof ARGV) ? ARGV : []; }
return argv;
};
/**
Restores original values after a call to `spade.globalize()`. If you call
this method more than once it will have no effect.
@returns {void}
*/
Tp.noConflict = function() {
var c = this._conflict;
if (c) {
delete this._conflict;
spade = this._conflict;
}
return this;
};
/**
Returns a new sandbox instance attached to the current spade instance.
If you pass true for the `isolate` parameter, the new sandbox will attempt
to load its code in an isolated compilation context (possibly using an
iframe in browsers). Note that isolated sandboxes are not supported by
default. Include the spade-isolate package instead.
@param {String} name
(Optional) name for the sandbox for debugging purposes.
@param {Boolean} isolate
true if you want the sandbox to be isolated. Throws exception if
platform cannot isolate.
@returns {Sandbox} sandbox instance
*/
Tp.sandbox = function(name, isolate) {
return new this.Sandbox(this, name, isolate);
};
/**
Register a module or package information. You can pass one of the
following:
'module/id', 'module body string'
'module/id', function() { module func }
'module/id', { exports: 'foo' }
'module/id' - just register module id and no body to indicate presence
Note also that if you pass just a packageId, it will be normalized to
packageId/~package. This is how you register a package.
@param {String} id
The module or package id
@param {String|Function|Hash} data
A module function, module body (as string), or hash of exports to use.
@param {String} opts
Additional metadata only if you are registering a module factory. Known
keys include 'filename' and 'format' (for compilation of DSLs).
@returns {void}
*/
Tp.register = function(id, data, opts) {
if (!data) { data = K ; }
var t = typeof data, isExtern, factory, isPkg;
id = normalize(id, null, null, true);
isPkg = id.slice(-9) === '/~package';
// register - note packages can only accept hashes
if (isPkg && 'object'!==typeof data) {
throw new Error('You can only register hashes for packages');
}
// Set some package defaults
if (isPkg) {
if (!data.directories) { data.directories = {}; }
if (!data.directories.lib) {
data.directories.lib = ['lib'];
} else if (typeof data.directories.lib === 'string') {
data.directories.lib = [data.directories.lib];
}
}
factory = { data: data };
factory.filename = opts && opts.filename ? opts.filename : id;
// Store with generic id if none, or if JS
this._factories[id] = factory;
return this;
};
/**
Efficient way to register external packages. Pass a hash of packageIds
and source URLs. If the package is already registered, the extern will
not replace it so this is safe to call multiple times.
@param {Hash} externs
A hash of package names and package settings.
@returns {void}
*/
Tp.externs = function(externs, extern) {
var tmp, packages = this._packages;
// normalize method call.
if ('string' === typeof externs) {
tmp = {};
tmp[externs] = extern;
externs = tmp;
extern = null;
}
for(var packageId in externs) {
if (!externs.hasOwnProperty(packageId)) { continue; }
if (packages[packageId] && !packages[packageId].extern) { continue; }
extern = externs[packageId];
if ('string' === typeof extern) { extern = {name: packageId, src: extern}; }
extern.extern = true;
this.register(packageId, extern);
}
};
/**
Require a module from the default sandbox.
@param {String} id
The module id.
@returns {Hash} module exports
*/
Tp.require = function(id) {
return this.defaultSandbox.require(id, this.defaultSandbox.callerId);
};
/**
Async load a module if it is not already a registered factory. Invoke
the passed callback with an optional error object when the module is
ready to load.
*/
Tp.async = function(id, callback) {
return this.defaultSandbox.async(id, callback);
};
/**
Returns true if the passed module exists in the default sandbox.
@param {String} id
The module id to check.
@returns {Boolean} true if module id exists
*/
Tp.exists = function(id) {
return this.defaultSandbox.exists(id);
};
/**
Returns the URL for a resource matching the passed module id and optional
extension.
@param {String} id
the module id to resolve
@param {String} ext
(Optional) extension to append to URL
@returns {String} url
*/
Tp.url = function(id, ext) {
return this.defaultSandbox.url(id, ext);
};
/**
Called by the sandbox to get a factory object for the named moduleId.
Normally you will not need to call this method directly or even override it.
@param {String} id
Fully normalized module id
@param {Function} callback
(Optional) callback to invoke once factory is loaded. If not passed, this
method will run sync. Otherwise it will run async.
@returns {Hash} factory hash.
*/
Tp.loadFactory = function(id, callback) {
var ret = this._factories[id],
loader = this.loader;
if (callback) {
if (!ret) {
if (loader && loader.loadFactory) {
loader.loadFactory(this, id, callback);
} else { callback(new Error('Module '+id+' not found')); }
} else { callback(); }
} else if (!ret && loader && loader.loadFactory) {
loader.loadFactory(this, id);
ret = this._factories[id];
}
return ret ;
};
/**
Called by the sandbox to determine if the named id exists on the system.
The id should already be normalized. If the id is not yet registered, the
loader will also be consulted.
Normally you will not need to call this method directly or override it.
@param {String} id
Fully normalized module id
@returns {Boolean} true if factory exists
*/
Tp.factoryExists = function(id) {
if (this._factories[id]) { return true; }
var loader = this.loader;
return loader && loader.exists && loader.exists(this, id);
};
/**
Returns the package info, if any, for the named module or packageId
@param {String} id
A package name or fully normalized module id.
@returns {Hash} package info or null if package is not registered
*/
Tp.package = function(id) {
id = packageIdFor(normalize(id))+'/~package';
var ret = this._factories[id];
return ret ? ret.data : null;
};
/**
Normalize a moduleId, expanding relative values if needed.
@param {String} id
The module id, possibly de-normalized.
@param {String} contextId
(Optional) The normalized module id of the calling module. Required if
your module id might be relative.
@returns {String} the normalized module id
*/
Tp.normalize = function(id, contextId) {
return normalize(id, contextId);
};
/**
Maps the passed module id to a potentially location specific module id.
This gives the loader a way to vary the factory function returns for a given
module id per sandbox. Useful when supporting multiple versions of the
same package.
@param {String} id
Normalized module id
@param {Sandbox} sandbox
The requesting sandbox
@returns {String} resolved module id
*/
Tp.resolve = function(id, sandbox) {
var loader = this.loader;
return sandbox && loader && loader.resolve ? loader.resolve(id, sandbox):id;
};
/**
Invokes the passed callback when the browser is ready. This will work
regardless of the environment you are in.
@param {Function} callback
Invoked when the browser is ready. If browser is alrady ready, invoked
immediately.
@returns {void}
*/
Tp.ready = function(callback) {
switch(this.readyState) {
case 'ready':
callback();
break;
case 'scheduled':
this._readyQueue.push(callback);
break;
default:
this._readyQueue = [callback];
this.readyState = 'scheduled';
if (this.loader.scheduleReady) {
var that = this;
this.loader.scheduleReady(function() {
var queue = that._readyQueue, len = queue ? queue.length : 0;
that._readyQueue = null;
that.readyState = 'ready';
for(var idx=0;idx<len;idx++) { queue[idx](); }
});
} else {
throw new Error('Loader does not support activate on ready state');
}
}
};
// instantiate spade and also attach class for testing
var newSpade = new Spade();
if ('undefined' !== typeof spade) newSpade._conflict = spade;
spade = newSpade;
// make this work when called as a module - both from within spade and from
// node.
if ('undefined' !== typeof require) {
if ('undefined' !== typeof __module) { __module.exports = spade; }
else if ('undefined' !== typeof module) { module.exports = spade; }
}
})();
spade.register("uglify-js/parse-js", "(function(require, exports, __module, ARGV, ENV, __filename){/***********************************************************************\n\n A JavaScript tokenizer / parser / beautifier / compressor.\n\n This version is suitable for Node.js. With minimal changes (the\n exports stuff) it should work on any JS platform.\n\n This file contains the tokenizer/parser. It is a port to JavaScript\n of parse-js [1], a JavaScript parser library written in Common Lisp\n by Marijn Haverbeke. Thank you Marijn!\n\n [1] http://marijn.haverbeke.nl/parse-js/\n\n Exported functions:\n\n - tokenizer(code) -- returns a function. Call the returned\n function to fetch the next token.\n\n - parse(code) -- returns an AST of the given JavaScript code.\n\n -------------------------------- (C) ---------------------------------\n\n Author: Mihai Bazon\n <mihai.bazon@gmail.com>\n http://mihai.bazon.net/blog\n\n Distributed under the BSD license:\n\n Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n Based on parse-js (http://marijn.haverbeke.nl/parse-js/).\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n\n * Redistributions of source code must retain the above\n copyright notice, this list of conditions and the following\n disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials\n provided with the distribution.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER \u0080\u009cAS IS\u0080\u009d AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n SUCH DAMAGE.\n\n ***********************************************************************/\n\n/* -----[ Tokenizer (constants) ]----- */\n\n\nvar KEYWORDS = array_to_hash([\n \"break\",\n \"case\",\n \"catch\",\n \"const\",\n \"continue\",\n \"default\",\n \"delete\",\n \"do\",\n \"else\",\n \"finally\",\n \"for\",\n \"function\",\n \"if\",\n \"in\",\n \"instanceof\",\n \"new\",\n \"return\",\n \"switch\",\n \"throw\",\n \"try\",\n \"typeof\",\n \"var\",\n \"void\",\n \"while\",\n \"with\"\n]);\n\nvar RESERVED_WORDS = array_to_hash([\n \"abstract\",\n \"boolean\",\n \"byte\",\n \"char\",\n \"class\",\n \"debugger\",\n \"double\",\n \"enum\",\n \"export\",\n \"extends\",\n \"final\",\n \"float\",\n \"goto\",\n \"implements\",\n \"import\",\n \"int\",\n \"interface\",\n \"long\",\n \"native\",\n \"package\",\n \"private\",\n \"protected\",\n \"public\",\n \"short\",\n \"static\",\n \"super\",\n \"synchronized\",\n \"throws\",\n \"transient\",\n \"volatile\"\n]);\n\nvar KEYWORDS_BEFORE_EXPRESSION = array_to_hash([\n \"return\",\n \"new\",\n \"delete\",\n \"throw\",\n \"else\",\n \"case\"\n]);\n\nvar KEYWORDS_ATOM = array_to_hash([\n \"false\",\n \"null\",\n \"true\",\n \"undefined\"\n]);\n\nvar OPERATOR_CHARS = array_to_hash(characters(\"+-*&%=<>!?|~^\"));\n\nvar RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;\nvar RE_OCT_NUMBER = /^0[0-7]+$/;\nvar RE_DEC_NUMBER = /^\\d*\\.?\\d*(?:e[+-]?\\d*(?:\\d\\.?|\\.?\\d)\\d*)?$/i;\n\nvar OPERATORS = array_to_hash([\n \"in\",\n \"instanceof\",\n \"typeof\",\n \"new\",\n \"void\",\n \"delete\",\n \"++\",\n \"--\",\n \"+\",\n \"-\",\n \"!\",\n \"~\",\n \"&\",\n \"|\",\n \"^\",\n \"*\",\n \"/\",\n \"%\",\n \">>\",\n \"<<\",\n \">>>\",\n \"<\",\n \">\",\n \"<=\",\n \">=\",\n \"==\",\n \"===\",\n \"!=\",\n \"!==\",\n \"?\",\n \"=\",\n \"+=\",\n \"-=\",\n \"/=\",\n \"*=\",\n \"%=\",\n \">>=\",\n \"<<=\",\n \">>>=\",\n \"|=\",\n \"^=\",\n \"&=\",\n \"&&\",\n \"||\"\n]);\n\nvar WHITESPACE_CHARS = array_to_hash(characters(\" \\u00a0\\n\\r\\t\\f\\u000b\\u200b\"));\n\nvar PUNC_BEFORE_EXPRESSION = array_to_hash(characters(\"[{}(,.;:\"));\n\nvar PUNC_CHARS = array_to_hash(characters(\"[]{}(),;:\"));\n\nvar REGEXP_MODIFIERS = array_to_hash(characters(\"gmsiy\"));\n\n/* -----[ Tokenizer ]----- */\n\n// regexps adapted from http://xregexp.com/plugins/#unicode\nvar UNICODE = {\n letter: new RegExp(\"[\\\\u0041-\\\\u005A\\\\u0061-\\\\u007A\\\\u00AA\\\\u00B5\\\\u00BA\\\\u00C0-\\\\u00D6\\\\u00D8-\\\\u00F6\\\\u00F8-\\\\u02C1\\\\u02C6-\\\\u02D1\\\\u02E0-\\\\u02E4\\\\u02EC\\\\u02EE\\\\u0370-\\\\u0374\\\\u0376\\\\u0377\\\\u037A-\\\\u037D\\\\u0386\\\\u0388-\\\\u038A\\\\u038C\\\\u038E-\\\\u03A1\\\\u03A3-\\\\u03F5\\\\u03F7-\\\\u0481\\\\u048A-\\\\u0523\\\\u0531-\\\\u0556\\\\u0559\\\\u0561-\\\\u0587\\\\u05D0-\\\\u05EA\\\\u05F0-\\\\u05F2\\\\u0621-\\\\u064A\\\\u066E\\\\u066F\\\\u0671-\\\\u06D3\\\\u06D5\\\\u06E5\\\\u06E6\\\\u06EE\\\\u06EF\\\\u06FA-\\\\u06FC\\\\u06FF\\\\u0710\\\\u0712-\\\\u072F\\\\u074D-\\\\u07A5\\\\u07B1\\\\u07CA-\\\\u07EA\\\\u07F4\\\\u07F5\\\\u07FA\\\\u0904-\\\\u0939\\\\u093D\\\\u0950\\\\u0958-\\\\u0961\\\\u0971\\\\u0972\\\\u097B-\\\\u097F\\\\u0985-\\\\u098C\\\\u098F\\\\u0990\\\\u0993-\\\\u09A8\\\\u09AA-\\\\u09B0\\\\u09B2\\\\u09B6-\\\\u09B9\\\\u09BD\\\\u09CE\\\\u09DC\\\\u09DD\\\\u09DF-\\\\u09E1\\\\u09F0\\\\u09F1\\\\u0A05-\\\\u0A0A\\\\u0A0F\\\\u0A10\\\\u0A13-\\\\u0A28\\\\u0A2A-\\\\u0A30\\\\u0A32\\\\u0A33\\\\u0A35\\\\u0A36\\\\u0A38\\\\u0A39\\\\u0A59-\\\\u0A5C\\\\u0A5E\\\\u0A72-\\\\u0A74\\\\u0A85-\\\\u0A8D\\\\u0A8F-\\\\u0A91\\\\u0A93-\\\\u0AA8\\\\u0AAA-\\\\u0AB0\\\\u0AB2\\\\u0AB3\\\\u0AB5-\\\\u0AB9\\\\u0ABD\\\\u0AD0\\\\u0AE0\\\\u0AE1\\\\u0B05-\\\\u0B0C\\\\u0B0F\\\\u0B10\\\\u0B13-\\\\u0B28\\\\u0B2A-\\\\u0B30\\\\u0B32\\\\u0B33\\\\u0B35-\\\\u0B39\\\\u0B3D\\\\u0B5C\\\\u0B5D\\\\u0B5F-\\\\u0B61\\\\u0B71\\\\u0B83\\\\u0B85-\\\\u0B8A\\\\u0B8E-\\\\u0B90\\\\u0B92-\\\\u0B95\\\\u0B99\\\\u0B9A\\\\u0B9C\\\\u0B9E\\\\u0B9F\\\\u0BA3\\\\u0BA4\\\\u0BA8-\\\\u0BAA\\\\u0BAE-\\\\u0BB9\\\\u0BD0\\\\u0C05-\\\\u0C0C\\\\u0C0E-\\\\u0C10\\\\u0C12-\\\\u0C28\\\\u0C2A-\\\\u0C33\\\\u0C35-\\\\u0C39\\\\u0C3D\\\\u0C58\\\\u0C59\\\\u0C60\\\\u0C61\\\\u0C85-\\\\u0C8C\\\\u0C8E-\\\\u0C90\\\\u0C92-\\\\u0CA8\\\\u0CAA-\\\\u0CB3\\\\u0CB5-\\\\u0CB9\\\\u0CBD\\\\u0CDE\\\\u0CE0\\\\u0CE1\\\\u0D05-\\\\u0D0C\\\\u0D0E-\\\\u0D10\\\\u0D12-\\\\u0D28\\\\u0D2A-\\\\u0D39\\\\u0D3D\\\\u0D60\\\\u0D61\\\\u0D7A-\\\\u0D7F\\\\u0D85-\\\\u0D96\\\\u0D9A-\\\\u0DB1\\\\u0DB3-\\\\u0DBB\\\\u0DBD\\\\u0DC0-\\\\u0DC6\\\\u0E01-\\\\u0E30\\\\u0E32\\\\u0E33\\\\u0E40-\\\\u0E46\\\\u0E81\\\\u0E82\\\\u0E84\\\\u0E87\\\\u0E88\\\\u0E8A\\\\u0E8D\\\\u0E94-\\\\u0E97\\\\u0E99-\\\\u0E9F\\\\u0EA1-\\\\u0EA3\\\\u0EA5\\\\u0EA7\\\\u0EAA\\\\u0EAB\\\\u0EAD-\\\\u0EB0\\\\u0EB2\\\\u0EB3\\\\u0EBD\\\\u0EC0-\\\\u0EC4\\\\u0EC6\\\\u0EDC\\\\u0EDD\\\\u0F00\\\\u0F40-\\\\u0F47\\\\u0F49-\\\\u0F6C\\\\u0F88-\\\\u0F8B\\\\u1000-\\\\u102A\\\\u103F\\\\u1050-\\\\u1055\\\\u105A-\\\\u105D\\\\u1061\\\\u1065\\\\u1066\\\\u106E-\\\\u1070\\\\u1075-\\\\u1081\\\\u108E\\\\u10A0-\\\\u10C5\\\\u10D0-\\\\u10FA\\\\u10FC\\\\u1100-\\\\u1159\\\\u115F-\\\\u11A2\\\\u11A8-\\\\u11F9\\\\u1200-\\\\u1248\\\\u124A-\\\\u124D\\\\u1250-\\\\u1256\\\\u1258\\\\u125A-\\\\u125D\\\\u1260-\\\\u1288\\\\u128A-\\\\u128D\\\\u1290-\\\\u12B0\\\\u12B2-\\\\u12B5\\\\u12B8-\\\\u12BE\\\\u12C0\\\\u12C2-\\\\u12C5\\\\u12C8-\\\\u12D6\\\\u12D8-\\\\u1310\\\\u1312-\\\\u1315\\\\u1318-\\\\u135A\\\\u1380-\\\\u138F\\\\u13A0-\\\\u13F4\\\\u1401-\\\\u166C\\\\u166F-\\\\u1676\\\\u1681-\\\\u169A\\\\u16A0-\\\\u16EA\\\\u1700-\\\\u170C\\\\u170E-\\\\u1711\\\\u1720-\\\\u1731\\\\u1740-\\\\u1751\\\\u1760-\\\\u176C\\\\u176E-\\\\u1770\\\\u1780-\\\\u17B3\\\\u17D7\\\\u17DC\\\\u1820-\\\\u1877\\\\u1880-\\\\u18A8\\\\u18AA\\\\u1900-\\\\u191C\\\\u1950-\\\\u196D\\\\u1970-\\\\u1974\\\\u1980-\\\\u19A9\\\\u19C1-\\\\u19C7\\\\u1A00-\\\\u1A16\\\\u1B05-\\\\u1B33\\\\u1B45-\\\\u1B4B\\\\u1B83-\\\\u1BA0\\\\u1BAE\\\\u1BAF\\\\u1C00-\\\\u1C23\\\\u1C4D-\\\\u1C4F\\\\u1C5A-\\\\u1C7D\\\\u1D00-\\\\u1DBF\\\\u1E00-\\\\u1F15\\\\u1F18-\\\\u1F1D\\\\u1F20-\\\\u1F45\\\\u1F48-\\\\u1F4D\\\\u1F50-\\\\u1F57\\\\u1F59\\\\u1F5B\\\\u1F5D\\\\u1F5F-\\\\u1F7D\\\\u1F80-\\\\u1FB4\\\\u1FB6-\\\\u1FBC\\\\u1FBE\\\\u1FC2-\\\\u1FC4\\\\u1FC6-\\\\u1FCC\\\\u1FD0-\\\\u1FD3\\\\u1FD6-\\\\u1FDB\\\\u1FE0-\\\\u1FEC\\\\u1FF2-\\\\u1FF4\\\\u1FF6-\\\\u1FFC\\\\u2071\\\\u207F\\\\u2090-\\\\u2094\\\\u2102\\\\u2107\\\\u210A-\\\\u2113\\\\u2115\\\\u2119-\\\\u211D\\\\u2124\\\\u2126\\\\u2128\\\\u212A-\\\\u212D\\\\u212F-\\\\u2139\\\\u213C-\\\\u213F\\\\u2145-\\\\u2149\\\\u214E\\\\u2183\\\\u2184\\\\u2C00-\\\\u2C2E\\\\u2C30-\\\\u2C5E\\\\u2C60-\\\\u2C6F\\\\u2C71-\\\\u2C7D\\\\u2C80-\\\\u2CE4\\\\u2D00-\\\\u2D25\\\\u2D30-\\\\u2D65\\\\u2D6F\\\\u2D80-\\\\u2D96\\\\u2DA0-\\\\u2DA6\\\\u2DA8-\\\\u2DAE\\\\u2DB0-\\\\u2DB6\\\\u2DB8-\\\\u2DBE\\\\u2DC0-\\\\u2DC6\\\\u2DC8-\\\\u2DCE\\\\u2DD0-\\\\u2DD6\\\\u2DD8-\\\\u2DDE\\\\u2E2F\\\\u3005\\\\u3006\\\\u3031-\\\\u3035\\\\u303B\\\\u303C\\\\u3041-\\\\u3096\\\\u309D-\\\\u309F\\\\u30A1-\\\\u30FA\\\\u30FC-\\\\u30FF\\\\u3105-\\\\u312D\\\\u3131-\\\\u318E\\\\u31A0-\\\\u31B7\\\\u31F0-\\\\u31FF\\\\u3400\\\\u4DB5\\\\u4E00\\\\u9FC3\\\\uA000-\\\\uA48C\\\\uA500-\\\\uA60C\\\\uA610-\\\\uA61F\\\\uA62A\\\\uA62B\\\\uA640-\\\\uA65F\\\\uA662-\\\\uA66E\\\\uA67F-\\\\uA697\\\\uA717-\\\\uA71F\\\\uA722-\\\\uA788\\\\uA78B\\\\uA78C\\\\uA7FB-\\\\uA801\\\\uA803-\\\\uA805\\\\uA807-\\\\uA80A\\\\uA80C-\\\\uA822\\\\uA840-\\\\uA873\\\\uA882-\\\\uA8B3\\\\uA90A-\\\\uA925\\\\uA930-\\\\uA946\\\\uAA00-\\\\uAA28\\\\uAA40-\\\\uAA42\\\\uAA44-\\\\uAA4B\\\\uAC00\\\\uD7A3\\\\uF900-\\\\uFA2D\\\\uFA30-\\\\uFA6A\\\\uFA70-\\\\uFAD9\\\\uFB00-\\\\uFB06\\\\uFB13-\\\\uFB17\\\\uFB1D\\\\uFB1F-\\\\uFB28\\\\uFB2A-\\\\uFB36\\\\uFB38-\\\\uFB3C\\\\uFB3E\\\\uFB40\\\\uFB41\\\\uFB43\\\\uFB44\\\\uFB46-\\\\uFBB1\\\\uFBD3-\\\\uFD3D\\\\uFD50-\\\\uFD8F\\\\uFD92-\\\\uFDC7\\\\uFDF0-\\\\uFDFB\\\\uFE70-\\\\uFE74\\\\uFE76-\\\\uFEFC\\\\uFF21-\\\\uFF3A\\\\uFF41-\\\\uFF5A\\\\uFF66-\\\\uFFBE\\\\uFFC2-\\\\uFFC7\\\\uFFCA-\\\\uFFCF\\\\uFFD2-\\\\uFFD7\\\\uFFDA-\\\\uFFDC]\"),\n non_spacing_mark: new RegExp(\"[\\\\u0300-\\\\u036F\\\\u0483-\\\\u0487\\\\u0591-\\\\u05BD\\\\u05BF\\\\u05C1\\\\u05C2\\\\u05C4\\\\u05C5\\\\u05C7\\\\u0610-\\\\u061A\\\\u064B-\\\\u065E\\\\u0670\\\\u06D6-\\\\u06DC\\\\u06DF-\\\\u06E4\\\\u06E7\\\\u06E8\\\\u06EA-\\\\u06ED\\\\u0711\\\\u0730-\\\\u074A\\\\u07A6-\\\\u07B0\\\\u07EB-\\\\u07F3\\\\u0816-\\\\u0819\\\\u081B-\\\\u0823\\\\u0825-\\\\u0827\\\\u0829-\\\\u082D\\\\u0900-\\\\u0902\\\\u093C\\\\u0941-\\\\u0948\\\\u094D\\\\u0951-\\\\u0955\\\\u0962\\\\u0963\\\\u0981\\\\u09BC\\\\u09C1-\\\\u09C4\\\\u09CD\\\\u09E2\\\\u09E3\\\\u0A01\\\\u0A02\\\\u0A3C\\\\u0A41\\\\u0A42\\\\u0A47\\\\u0A48\\\\u0A4B-\\\\u0A4D\\\\u0A51\\\\u0A70\\\\u0A71\\\\u0A75\\\\u0A81\\\\u0A82\\\\u0ABC\\\\u0AC1-\\\\u0AC5\\\\u0AC7\\\\u0AC8\\\\u0ACD\\\\u0AE2\\\\u0AE3\\\\u0B01\\\\u0B3C\\\\u0B3F\\\\u0B41-\\\\u0B44\\\\u0B4D\\\\u0B56\\\\u0B62\\\\u0B63\\\\u0B82\\\\u0BC0\\\\u0BCD\\\\u0C3E-\\\\u0C40\\\\u0C46-\\\\u0C48\\\\u0C4A-\\\\u0C4D\\\\u0C55\\\\u0C56\\\\u0C62\\\\u0C63\\\\u0CBC\\\\u0CBF\\\\u0CC6\\\\u0CCC\\\\u0CCD\\\\u0CE2\\\\u0CE3\\\\u0D41-\\\\u0D44\\\\u0D4D\\\\u0D62\\\\u0D63\\\\u0DCA\\\\u0DD2-\\\\u0DD4\\\\u0DD6\\\\u0E31\\\\u0E34-\\\\u0E3A\\\\u0E47-\\\\u0E4E\\\\u0EB1\\\\u0EB4-\\\\u0EB9\\\\u0EBB\\\\u0EBC\\\\u0EC8-\\\\u0ECD\\\\u0F18\\\\u0F19\\\\u0F35\\\\u0F37\\\\u0F39\\\\u0F71-\\\\u0F7E\\\\u0F80-\\\\u0F84\\\\u0F86\\\\u0F87\\\\u0F90-\\\\u0F97\\\\u0F99-\\\\u0FBC\\\\u0FC6\\\\u102D-\\\\u1030\\\\u1032-\\\\u1037\\\\u1039\\\\u103A\\\\u103D\\\\u103E\\\\u1058\\\\u1059\\\\u105E-\\\\u1060\\\\u1071-\\\\u1074\\\\u1082\\\\u1085\\\\u1086\\\\u108D\\\\u109D\\\\u135F\\\\u1712-\\\\u1714\\\\u1732-\\\\u1734\\\\u1752\\\\u1753\\\\u1772\\\\u1773\\\\u17B7-\\\\u17BD\\\\u17C6\\\\u17C9-\\\\u17D3\\\\u17DD\\\\u180B-\\\\u180D\\\\u18A9\\\\u1920-\\\\u1922\\\\u1927\\\\u1928\\\\u1932\\\\u1939-\\\\u193B\\\\u1A17\\\\u1A18\\\\u1A56\\\\u1A58-\\\\u1A5E\\\\u1A60\\\\u1A62\\\\u1A65-\\\\u1A6C\\\\u1A73-\\\\u1A7C\\\\u1A7F\\\\u1B00-\\\\u1B03\\\\u1B34\\\\u1B36-\\\\u1B3A\\\\u1B3C\\\\u1B42\\\\u1B6B-\\\\u1B73\\\\u1B80\\\\u1B81\\\\u1BA2-\\\\u1BA5\\\\u1BA8\\\\u1BA9\\\\u1C2C-\\\\u1C33\\\\u1C36\\\\u1C37\\\\u1CD0-\\\\u1CD2\\\\u1CD4-\\\\u1CE0\\\\u1CE2-\\\\u1CE8\\\\u1CED\\\\u1DC0-\\\\u1DE6\\\\u1DFD-\\\\u1DFF\\\\u20D0-\\\\u20DC\\\\u20E1\\\\u20E5-\\\\u20F0\\\\u2CEF-\\\\u2CF1\\\\u2DE0-\\\\u2DFF\\\\u302A-\\\\u302F\\\\u3099\\\\u309A\\\\uA66F\\\\uA67C\\\\uA67D\\\\uA6F0\\\\uA6F1\\\\uA802\\\\uA806\\\\uA80B\\\\uA825\\\\uA826\\\\uA8C4\\\\uA8E0-\\\\uA8F1\\\\uA926-\\\\uA92D\\\\uA947-\\\\uA951\\\\uA980-\\\\uA982\\\\uA9B3\\\\uA9B6-\\\\uA9B9\\\\uA9BC\\\\uAA29-\\\\uAA2E\\\\uAA31\\\\uAA32\\\\uAA35\\\\uAA36\\\\uAA43\\\\uAA4C\\\\uAAB0\\\\uAAB2-\\\\uAAB4\\\\uAAB7\\\\uAAB8\\\\uAABE\\\\uAABF\\\\uAAC1\\\\uABE5\\\\uABE8\\\\uABED\\\\uFB1E\\\\uFE00-\\\\uFE0F\\\\uFE20-\\\\uFE26]\"),\n space_combining_mark: new RegExp(\"[\\\\u0903\\\\u093E-\\\\u0940\\\\u0949-\\\\u094C\\\\u094E\\\\u0982\\\\u0983\\\\u09BE-\\\\u09C0\\\\u09C7\\\\u09C8\\\\u09CB\\\\u09CC\\\\u09D7\\\\u0A03\\\\u0A3E-\\\\u0A40\\\\u0A83\\\\u0ABE-\\\\u0AC0\\\\u0AC9\\\\u0ACB\\\\u0ACC\\\\u0B02\\\\u0B03\\\\u0B3E\\\\u0B40\\\\u0B47\\\\u0B48\\\\u0B4B\\\\u0B4C\\\\u0B57\\\\u0BBE\\\\u0BBF\\\\u0BC1\\\\u0BC2\\\\u0BC6-\\\\u0BC8\\\\u0BCA-\\\\u0BCC\\\\u0BD7\\\\u0C01-\\\\u0C03\\\\u0C41-\\\\u0C44\\\\u0C82\\\\u0C83\\\\u0CBE\\\\u0CC0-\\\\u0CC4\\\\u0CC7\\\\u0CC8\\\\u0CCA\\\\u0CCB\\\\u0CD5\\\\u0CD6\\\\u0D02\\\\u0D03\\\\u0D3E-\\\\u0D40\\\\u0D46-\\\\u0D48\\\\u0D4A-\\\\u0D4C\\\\u0D57\\\\u0D82\\\\u0D83\\\\u0DCF-\\\\u0DD1\\\\u0DD8-\\\\u0DDF\\\\u0DF2\\\\u0DF3\\\\u0F3E\\\\u0F3F\\\\u0F7F\\\\u102B\\\\u102C\\\\u1031\\\\u1038\\\\u103B\\\\u103C\\\\u1056\\\\u1057\\\\u1062-\\\\u1064\\\\u1067-\\\\u106D\\\\u1083\\\\u1084\\\\u1087-\\\\u108C\\\\u108F\\\\u109A-\\\\u109C\\\\u17B6\\\\u17BE-\\\\u17C5\\\\u17C7\\\\u17C8\\\\u1923-\\\\u1926\\\\u1929-\\\\u192B\\\\u1930\\\\u1931\\\\u1933-\\\\u1938\\\\u19B0-\\\\u19C0\\\\u19C8\\\\u19C9\\\\u1A19-\\\\u1A1B\\\\u1A55\\\\u1A57\\\\u1A61\\\\u1A63\\\\u1A64\\\\u1A6D-\\\\u1A72\\\\u1B04\\\\u1B35\\\\u1B3B\\\\u1B3D-\\\\u1B41\\\\u1B43\\\\u1B44\\\\u1B82\\\\u1BA1\\\\u1BA6\\\\u1BA7\\\\u1BAA\\\\u1C24-\\\\u1C2B\\\\u1C34\\\\u1C35\\\\u1CE1\\\\u1CF2\\\\uA823\\\\uA824\\\\uA827\\\\uA880\\\\uA881\\\\uA8B4-\\\\uA8C3\\\\uA952\\\\uA953\\\\uA983\\\\uA9B4\\\\uA9B5\\\\uA9BA\\\\uA9BB\\\\uA9BD-\\\\uA9C0\\\\uAA2F\\\\uAA30\\\\uAA33\\\\uAA34\\\\uAA4D\\\\uAA7B\\\\uABE3\\\\uABE4\\\\uABE6\\\\uABE7\\\\uABE9\\\\uABEA\\\\uABEC]\"),\n connector_punctuation: new RegExp(\"[\\\\u005F\\\\u203F\\\\u2040\\\\u2054\\\\uFE33\\\\uFE34\\\\uFE4D-\\\\uFE4F\\\\uFF3F]\")\n};\n\nfunction is_letter(ch) {\n return UNICODE.letter.test(ch);\n};\n\nfunction is_digit(ch) {\n ch = ch.charCodeAt(0);\n return ch >= 48 && ch <= 57; //XXX: find out if \"UnicodeDigit\" means something else than 0..9\n};\n\nfunction is_alphanumeric_char(ch) {\n return is_digit(ch) || is_letter(ch);\n};\n\nfunction is_unicode_combining_mark(ch) {\n return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);\n};\n\nfunction is_unicode_connector_punctuation(ch) {\n return UNICODE.connector_punctuation.test(ch);\n};\n\nfunction is_identifier_start(ch) {\n return ch == \"$\" || ch == \"_\" || is_letter(ch);\n};\n\nfunction is_identifier_char(ch) {\n return is_identifier_start(ch)\n || is_unicode_combining_mark(ch)\n || is_digit(ch)\n || is_unicode_connector_punctuation(ch)\n || ch == \"\\u200c\" // zero-width non-joiner <ZWNJ>\n || ch == \"\\u200d\" // zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)\n ;\n};\n\nfunction parse_js_number(num) {\n if (RE_HEX_NUMBER.test(num)) {\n return parseInt(num.substr(2), 16);\n } else if (RE_OCT_NUMBER.test(num)) {\n return parseInt(num.substr(1), 8);\n } else if (RE_DEC_NUMBER.test(num)) {\n return parseFloat(num);\n }\n};\n\nfunction JS_Parse_Error(message, line, col, pos) {\n this.message = message;\n this.line = line;\n this.col = col;\n this.pos = pos;\n try {\n ({})();\n } catch(ex) {\n this.stack = ex.stack;\n };\n};\n\nJS_Parse_Error.prototype.toString = function() {\n return this.message + \" (line: \" + this.line + \", col: \" + this.col + \", pos: \" + this.pos + \")\" + \"\\n\\n\" + this.stack;\n};\n\nfunction js_error(message, line, col, pos) {\n throw new JS_Parse_Error(message, line, col, pos);\n};\n\nfunction is_token(token, type, val) {\n return token.type == type && (val == null || token.value == val);\n};\n\nvar EX_EOF = {};\n\nfunction tokenizer($TEXT) {\n\n var S = {\n text : $TEXT.replace(/\\r\\n?|[\\n\\u2028\\u2029]/g, \"\\n\").replace(/^\\uFEFF/, ''),\n pos : 0,\n tokpos : 0,\n line : 0,\n tokline : 0,\n col : 0,\n tokcol : 0,\n newline_before : false,\n regex_allowed : false,\n comments_before : []\n };\n\n function peek() { return S.text.charAt(S.pos); };\n\n function next(signal_eof) {\n var ch = S.text.charAt(S.pos++);\n if (signal_eof && !ch)\n throw EX_EOF;\n if (ch == \"\\n\") {\n S.newline_before = true;\n ++S.line;\n S.col = 0;\n } else {\n ++S.col;\n }\n return ch;\n };\n\n function eof() {\n return !S.peek();\n };\n\n function find(what, signal_eof) {\n var pos = S.text.indexOf(what, S.pos);\n if (signal_eof && pos == -1) throw EX_EOF;\n return pos;\n };\n\n function start_token() {\n S.tokline = S.line;\n S.tokcol = S.col;\n S.tokpos = S.pos;\n };\n\n function token(type, value, is_comment) {\n S.regex_allowed = ((type == \"operator\" && !HOP(UNARY_POSTFIX, value)) ||\n (type == \"keyword\" && HOP(KEYWORDS_BEFORE_EXPRESSION, value)) ||\n (type == \"punc\" && HOP(PUNC_BEFORE_EXPRESSION, value)));\n var ret = {\n type : type,\n value : value,\n line : S.tokline,\n col : S.tokcol,\n pos : S.tokpos,\n nlb : S.newline_before\n };\n if (!is_comment) {\n ret.comments_before = S.comments_before;\n S.comments_before = [];\n }\n S.newline_before = false;\n return ret;\n };\n\n function skip_whitespace() {\n while (HOP(WHITESPACE_CHARS, peek()))\n next();\n };\n\n function read_while(pred) {\n var ret = \"\", ch = peek(), i = 0;\n while (ch && pred(ch, i++)) {\n ret += next();\n ch = peek();\n }\n return ret;\n };\n\n function parse_error(err) {\n js_error(err, S.tokline, S.tokcol, S.tokpos);\n };\n\n function read_num(prefix) {\n var has_e = false, after_e = false, has_x = false, has_dot = prefix == \".\";\n var num = read_while(function(ch, i){\n if (ch == \"x\" || ch == \"X\") {\n if (has_x) return false;\n return has_x = true;\n }\n if (!has_x && (ch == \"E\" || ch == \"e\")) {\n if (has_e) return false;\n return has_e = after_e = true;\n }\n if (ch == \"-\") {\n if (after_e || (i == 0 && !prefix)) return true;\n return false;\n }\n if (ch == \"+\") return after_e;\n after_e = false;\n if (ch == \".\") {\n if (!has_dot && !has_x)\n return has_dot = true;\n return false;\n }\n return is_alphanumeric_char(ch);\n });\n if (prefix)\n num = prefix + num;\n var valid = parse_js_number(num);\n if (!isNaN(valid)) {\n return token(\"num\", valid);\n } else {\n parse_error(\"Invalid syntax: \" + num);\n }\n };\n\n function read_escaped_char() {\n var ch = next(true);\n switch (ch) {\n case \"n\" : return \"\\n\";\n case \"r\" : return \"\\r\";\n case \"t\" : return \"\\t\";\n case \"b\" : return \"\\b\";\n case \"v\" : return \"\\u000b\";\n case \"f\" : return \"\\f\";\n case \"0\" : return \"\\0\";\n case \"x\" : return String.fromCharCode(hex_bytes(2));\n case \"u\" : return String.fromCharCode(hex_bytes(4));\n case \"\\n\": return \"\";\n default : return ch;\n }\n };\n\n function hex_bytes(n) {\n var num = 0;\n for (; n > 0; --n) {\n var digit = parseInt(next(true), 16);\n if (isNaN(digit))\n parse_error(\"Invalid hex-character pattern in string\");\n num = (num << 4) | digit;\n }\n return num;\n };\n\n function read_string() {\n return with_eof_error(\"Unterminated string constant\", function(){\n var quote = next(), ret = \"\";\n for (;;) {\n var ch = next(true);\n if (ch == \"\\\\\") {\n // read OctalEscapeSequence (XXX: deprecated if \"strict mode\")\n // https://github.com/mishoo/UglifyJS/issues/178\n var octal_len = 0, first = null;\n ch = read_while(function(ch){\n if (ch >= \"0\" && ch <= \"7\") {\n if (!first) {\n first = ch;\n return ++octal_len;\n }\n else if (first <= \"3\" && octal_len <= 2) return ++octal_len;\n else if (first >= \"4\" && octal_len <= 1) return ++octal_len;\n }\n return false;\n });\n if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8));\n else ch = read_escaped_char();\n }\n else if (ch == quote) break;\n ret += ch;\n }\n return token(\"string\", ret);\n });\n };\n\n function read_line_comment() {\n next();\n var i = find(\"\\n\"), ret;\n if (i == -1) {\n ret = S.text.substr(S.pos);\n S.pos = S.text.length;\n } else {\n ret = S.text.substring(S.pos, i);\n S.pos = i;\n }\n return token(\"comment1\", ret, true);\n };\n\n function read_multiline_comment() {\n next();\n return with_eof_error(\"Unterminated multiline comment\", function(){\n var i = find(\"*/\", true),\n text = S.text.substring(S.pos, i),\n tok = token(\"comment2\", text, true);\n S.pos = i + 2;\n S.line += text.split(\"\\n\").length - 1;\n S.newline_before = text.indexOf(\"\\n\") >= 0;\n\n // https://github.com/mishoo/UglifyJS/issues/#issue/100\n if (/^@cc_on/i.test(text)) {\n warn(\"WARNING: at line \" + S.line);\n warn(\"*** Found \\\"conditional comment\\\": \" + text);\n warn(\"*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer.\");\n }\n\n return tok;\n });\n };\n\n function read_name() {\n var backslash = false, name = \"\", ch;\n while ((ch = peek()) != null) {\n if (!backslash) {\n if (ch == \"\\\\\") backslash = true, next();\n else if (is_identifier_char(ch)) name += next();\n else break;\n }\n else {\n if (ch != \"u\") parse_error(\"Expecting UnicodeEscapeSequence -- uXXXX\");\n ch = read_escaped_char();\n if (!is_identifier_char(ch)) parse_error(\"Unicode char: \" + ch.charCodeAt(0) + \" is not valid in identifier\");\n name += ch;\n backslash = false;\n }\n }\n return name;\n };\n\n function read_regexp() {\n return with_eof_error(\"Unterminated regular expression\", function(){\n var prev_backslash = false, regexp = \"\", ch, in_class = false;\n while ((ch = next(true))) if (prev_backslash) {\n regexp += \"\\\\\" + ch;\n prev_backslash = false;\n } else if (ch == \"[\") {\n in_class = true;\n regexp += ch;\n } else if (ch == \"]\" && in_class) {\n in_class = false;\n regexp += ch;\n } else if (ch == \"/\" && !in_class) {\n break;\n } else if (ch == \"\\\\\") {\n prev_backslash = true;\n } else {\n regexp += ch;\n }\n var mods = read_name();\n return token(\"regexp\", [ regexp, mods ]);\n });\n };\n\n function read_operator(prefix) {\n function grow(op) {\n if (!peek()) return op;\n var bigger = op + peek();\n if (HOP(OPERATORS, bigger)) {\n next();\n return grow(bigger);\n } else {\n return op;\n }\n };\n return token(\"operator\", grow(prefix || next()));\n };\n\n function handle_slash() {\n next();\n var regex_allowed = S.regex_allowed;\n switch (peek()) {\n case \"/\":\n S.comments_before.push(read_line_comment());\n S.regex_allowed = regex_allowed;\n return next_token();\n case \"*\":\n S.comments_before.push(read_multiline_comment());\n S.regex_allowed = regex_allowed;\n return next_token();\n }\n return S.regex_allowed ? read_regexp() : read_operator(\"/\");\n };\n\n function handle_dot() {\n next();\n return is_digit(peek())\n ? read_num(\".\")\n : token(\"punc\", \".\");\n };\n\n function read_word() {\n var word = read_name();\n return !HOP(KEYWORDS, word)\n ? token(\"name\", word)\n : HOP(OPERATORS, word)\n ? token(\"operator\", word)\n : HOP(KEYWORDS_ATOM, word)\n ? token(\"atom\", word)\n : token(\"keyword\", word);\n };\n\n function with_eof_error(eof_error, cont) {\n try {\n return cont();\n } catch(ex) {\n if (ex === EX_EOF) parse_error(eof_error);\n else throw ex;\n }\n };\n\n function next_token(force_regexp) {\n if (force_regexp)\n return read_regexp();\n skip_whitespace();\n start_token();\n var ch = peek();\n if (!ch) return token(\"eof\");\n if (is_digit(ch)) return read_num();\n if (ch == '\"' || ch == \"'\") return read_string();\n if (HOP(PUNC_CHARS, ch)) return token(\"punc\", next());\n if (ch == \".\") return handle_dot();\n if (ch == \"/\") return handle_slash();\n if (HOP(OPERATOR_CHARS, ch)) return read_operator();\n if (ch == \"\\\\\" || is_identifier_start(ch)) return read_word();\n parse_error(\"Unexpected character '\" + ch + \"'\");\n };\n\n next_token.context = function(nc) {\n if (nc) S = nc;\n return S;\n };\n\n return next_token;\n\n};\n\n/* -----[ Parser (constants) ]----- */\n\nvar UNARY_PREFIX = array_to_hash([\n \"typeof\",\n \"void\",\n \"delete\",\n \"--\",\n \"++\",\n \"!\",\n \"~\",\n \"-\",\n \"+\"\n]);\n\nvar UNARY_POSTFIX = array_to_hash([ \"--\", \"++\" ]);\n\nvar ASSIGNMENT = (function(a, ret, i){\n while (i < a.length) {\n ret[a[i]] = a[i].substr(0, a[i].length - 1);\n i++;\n }\n return ret;\n})(\n [\"+=\", \"-=\", \"/=\", \"*=\", \"%=\", \">>=\", \"<<=\", \">>>=\", \"|=\", \"^=\", \"&=\"],\n { \"=\": true },\n 0\n);\n\nvar PRECEDENCE = (function(a, ret){\n for (var i = 0, n = 1; i < a.length; ++i, ++n) {\n var b = a[i];\n for (var j = 0; j < b.length; ++j) {\n ret[b[j]] = n;\n }\n }\n return ret;\n})(\n [\n [\"||\"],\n [\"&&\"],\n [\"|\"],\n [\"^\"],\n [\"&\"],\n [\"==\", \"===\", \"!=\", \"!==\"],\n [\"<\", \">\", \"<=\", \">=\", \"in\", \"instanceof\"],\n [\">>\", \"<<\", \">>>\"],\n [\"+\", \"-\"],\n [\"*\", \"/\", \"%\"]\n ],\n {}\n);\n\nvar STATEMENTS_WITH_LABELS = array_to_hash([ \"for\", \"do\", \"while\", \"switch\" ]);\n\nvar ATOMIC_START_TOKEN = array_to_hash([ \"atom\", \"num\", \"string\", \"regexp\", \"name\" ]);\n\n/* -----[ Parser ]----- */\n\nfunction NodeWithToken(str, start, end) {\n this.name = str;\n this.start = start;\n this.end = end;\n};\n\nNodeWithToken.prototype.toString = function() { return this.name; };\n\nfunction parse($TEXT, exigent_mode, embed_tokens) {\n\n var S = {\n input : typeof $TEXT == \"string\" ? tokenizer($TEXT, true) : $TEXT,\n token : null,\n prev : null,\n peeked : null,\n in_function : 0,\n in_loop : 0,\n labels : []\n };\n\n S.token = next();\n\n function is(type, value) {\n return is_token(S.token, type, value);\n };\n\n function peek() { return S.peeked || (S.peeked = S.input()); };\n\n function next() {\n S.prev = S.token;\n if (S.peeked) {\n S.token = S.peeked;\n S.peeked = null;\n } else {\n S.token = S.input();\n }\n return S.token;\n };\n\n function prev() {\n return S.prev;\n };\n\n function croak(msg, line, col, pos) {\n var ctx = S.input.context();\n js_error(msg,\n line != null ? line : ctx.tokline,\n col != null ? col : ctx.tokcol,\n pos != null ? pos : ctx.tokpos);\n };\n\n function token_error(token, msg) {\n croak(msg, token.line, token.col);\n };\n\n function unexpected(token) {\n if (token == null)\n token = S.token;\n token_error(token, \"Unexpected token: \" + token.type + \" (\" + token.value + \")\");\n };\n\n function expect_token(type, val) {\n if (is(type, val)) {\n return next();\n }\n token_error(S.token, \"Unexpected token \" + S.token.type + \", expected \" + type);\n };\n\n function expect(punc) { return expect_token(\"punc\", punc); };\n\n function can_insert_semicolon() {\n return !exigent_mode && (\n S.token.nlb || is(\"eof\") || is(\"punc\", \"}\")\n );\n };\n\n function semicolon() {\n if (is(\"punc\", \";\")) next();\n else if (!can_insert_semicolon()) unexpected();\n };\n\n function as() {\n return slice(arguments);\n };\n\n function parenthesised() {\n expect(\"(\");\n var ex = expression();\n expect(\")\");\n return ex;\n };\n\n function add_tokens(str, start, end) {\n return str instanceof NodeWithToken ? str : new NodeWithToken(str, start, end);\n };\n\n function maybe_embed_tokens(parser) {\n if (embed_tokens) return function() {\n var start = S.token;\n var ast = parser.apply(this, arguments);\n ast[0] = add_tokens(ast[0], start, prev());\n return ast;\n };\n else return parser;\n };\n\n var statement = maybe_embed_tokens(function() {\n if (is(\"operator\", \"/\")) {\n S.peeked = null;\n S.token = S.input(true); // force regexp\n }\n switch (S.token.type) {\n case \"num\":\n case \"string\":\n case \"regexp\":\n case \"operator\":\n case \"atom\":\n return simple_statement();\n\n case \"name\":\n return is_token(peek(), \"punc\", \":\")\n ? labeled_statement(prog1(S.token.value, next, next))\n : simple_statement();\n\n case \"punc\":\n switch (S.token.value) {\n case \"{\":\n return as(\"block\", block_());\n case \"[\":\n case \"(\":\n return simple_statement();\n case \";\":\n next();\n return as(\"block\");\n default:\n unexpected();\n }\n\n case \"keyword\":\n switch (prog1(S.token.value, next)) {\n case \"break\":\n return break_cont(\"break\");\n\n case \"continue\":\n return break_cont(\"continue\");\n\n case \"debugger\":\n semicolon();\n return as(\"debugger\");\n\n case \"do\":\n return (function(body){\n expect_token(\"keyword\", \"while\");\n return as(\"do\", prog1(parenthesised, semicolon), body);\n })(in_loop(statement));\n\n case \"for\":\n return for_();\n\n case \"function\":\n return function_(true);\n\n case \"if\":\n return if_();\n\n case \"return\":\n if (S.in_function == 0)\n croak(\"'return' outside of function\");\n return as(\"return\",\n is(\"punc\", \";\")\n ? (next(), null)\n : can_insert_semicolon()\n ? null\n : prog1(expression, semicolon));\n\n case \"switch\":\n return as(\"switch\", parenthesised(), switch_block_());\n\n case \"throw\":\n return as(\"throw\", prog1(expression, semicolon));\n\n case \"try\":\n return try_();\n\n case \"var\":\n return prog1(var_, semicolon);\n\n case \"const\":\n return prog1(const_, semicolon);\n\n case \"while\":\n return as(\"while\", parenthesised(), in_loop(statement));\n\n case \"with\":\n return as(\"with\", parenthesised(), statement());\n\n default:\n unexpected();\n }\n }\n });\n\n function labeled_statement(label) {\n S.labels.push(label);\n var start = S.token, stat = statement();\n if (exigent_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))\n unexpected(start);\n S.labels.pop();\n return as(\"label\", label, stat);\n };\n\n function simple_statement() {\n return as(\"stat\", prog1(expression, semicolon));\n };\n\n function break_cont(type) {\n var name;\n if (!can_insert_semicolon()) {\n name = is(\"name\") ? S.token.value : null;\n }\n if (name != null) {\n next();\n if (!member(name, S.labels))\n croak(\"Label \" + name + \" without matching loop or statement\");\n }\n else if (S.in_loop == 0)\n croak(type + \" not inside a loop or switch\");\n semicolon();\n return as(type, name);\n };\n\n function for_() {\n expect(\"(\");\n var init = null;\n if (!is(\"punc\", \";\")) {\n init = is(\"keyword\", \"var\")\n ? (next(), var_(true))\n : expression(true, true);\n if (is(\"operator\", \"in\"))\n return for_in(init);\n }\n return regular_for(init);\n };\n\n function regular_for(init) {\n expect(\";\");\n var test = is(\"punc\", \";\") ? null : expression();\n expect(\";\");\n var step = is(\"punc\", \")\") ? null : expression();\n expect(\")\");\n return as(\"for\", init, test, step, in_loop(statement));\n };\n\n function for_in(init) {\n var lhs = init[0] == \"var\" ? as(\"name\", init[1][0]) : init;\n next();\n var obj = expression();\n expect(\")\");\n return as(\"for-in\", init, lhs, obj, in_loop(statement));\n };\n\n var function_ = maybe_embed_tokens(function(in_statement) {\n var name = is(\"name\") ? prog1(S.token.value, next) : null;\n if (in_statement && !name)\n unexpected();\n expect(\"(\");\n return as(in_statement ? \"defun\" : \"function\",\n name,\n // arguments\n (function(first, a){\n while (!is(\"punc\", \")\")) {\n if (first) first = false; else expect(\",\");\n if (!is(\"name\")) unexpected();\n a.push(S.token.value);\n next();\n }\n next();\n return a;\n })(true, []),\n // body\n (function(){\n ++S.in_function;\n var loop = S.in_loop;\n S.in_loop = 0;\n var a = block_();\n --S.in_function;\n S.in_loop = loop;\n return a;\n })());\n });\n\n function if_() {\n var cond = parenthesised(), body = statement(), belse;\n if (is(\"keyword\", \"else\")) {\n next();\n belse = statement();\n }\n return as(\"if\", cond, body, belse);\n };\n\n function block_() {\n expect(\"{\");\n var a = [];\n while (!is(\"punc\", \"}\")) {\n if (is(\"eof\")) unexpected();\n a.push(statement());\n }\n next();\n return a;\n };\n\n var switch_block_ = curry(in_loop, function(){\n expect(\"{\");\n var a = [], cur = null;\n while (!is(\"punc\", \"}\")) {\n if (is(\"eof\")) unexpected();\n if (is(\"keyword\", \"case\")) {\n next();\n cur = [];\n a.push([ expression(), cur ]);\n expect(\":\");\n }\n else if (is(\"keyword\", \"default\")) {\n next();\n expect(\":\");\n cur = [];\n a.push([ null, cur ]);\n }\n else {\n if (!cur) unexpected();\n cur.push(statement());\n }\n }\n next();\n return a;\n });\n\n function try_() {\n var body = block_(), bcatch, bfinally;\n if (is(\"keyword\", \"catch\")) {\n next();\n expect(\"(\");\n if (!is(\"name\"))\n croak(\"Name expected\");\n var name = S.token.value;\n next();\n expect(\")\");\n bcatch = [ name, block_() ];\n }\n if (is(\"keyword\", \"finally\")) {\n next();\n bfinally = block_();\n }\n if (!bcatch && !bfinally)\n croak(\"Missing catch/finally blocks\");\n return as(\"try\", body, bcatch, bfinally);\n };\n\n function vardefs(no_in) {\n var a = [];\n for (;;) {\n if (!is(\"name\"))\n unexpected();\n var name = S.token.value;\n next();\n if (is(\"operator\", \"=\")) {\n next();\n a.push([ name, expression(false, no_in) ]);\n } else {\n a.push([ name ]);\n }\n if (!is(\"punc\", \",\"))\n break;\n next();\n }\n return a;\n };\n\n function var_(no_in) {\n return as(\"var\", vardefs(no_in));\n };\n\n function const_() {\n return as(\"const\", vardefs());\n };\n\n function new_() {\n var newexp = expr_atom(false), args;\n if (is(\"punc\", \"(\")) {\n next();\n args = expr_list(\")\");\n } else {\n args = [];\n }\n return subscripts(as(\"new\", newexp, args), true);\n };\n\n var expr_atom = maybe_embed_tokens(function(allow_calls) {\n if (is(\"operator\", \"new\")) {\n next();\n return new_();\n }\n if (is(\"punc\")) {\n switch (S.token.value) {\n case \"(\":\n next();\n return subscripts(prog1(expression, curry(expect, \")\")), allow_calls);\n case \"[\":\n next();\n return subscripts(array_(), allow_calls);\n case \"{\":\n next();\n return subscripts(object_(), allow_calls);\n }\n unexpected();\n }\n if (is(\"keyword\", \"function\")) {\n next();\n return subscripts(function_(false), allow_calls);\n }\n if (HOP(ATOMIC_START_TOKEN, S.token.type)) {\n var atom = S.token.type == \"regexp\"\n ? as(\"regexp\", S.token.value[0], S.token.value[1])\n : as(S.token.type, S.token.value);\n return subscripts(prog1(atom, next), allow_calls);\n }\n unexpected();\n });\n\n function expr_list(closing, allow_trailing_comma, allow_empty) {\n var first = true, a = [];\n while (!is(\"punc\", closing)) {\n if (first) first = false; else expect(\",\");\n if (allow_trailing_comma && is(\"punc\", closing)) break;\n if (is(\"punc\", \",\") && allow_empty) {\n a.push([ \"atom\", \"undefined\" ]);\n } else {\n a.push(expression(false));\n }\n }\n next();\n return a;\n };\n\n function array_() {\n return as(\"array\", expr_list(\"]\", !exigent_mode, true));\n };\n\n function object_() {\n var first = true, a = [];\n while (!is(\"punc\", \"}\")) {\n if (first) first = false; else expect(\",\");\n if (!exigent_mode && is(\"punc\", \"}\"))\n // allow trailing comma\n break;\n var type = S.token.type;\n var name = as_property_name();\n if (type == \"name\" && (name == \"get\" || name == \"set\") && !is(\"punc\", \":\")) {\n a.push([ as_name(), function_(false), name ]);\n } else {\n expect(\":\");\n a.push([ name, expression(false) ]);\n }\n }\n next();\n return as(\"object\", a);\n };\n\n function as_property_name() {\n switch (S.token.type) {\n case \"num\":\n case \"string\":\n return prog1(S.token.value, next);\n }\n return as_name();\n };\n\n function as_name() {\n switch (S.token.type) {\n case \"name\":\n case \"operator\":\n case \"keyword\":\n case \"atom\":\n return prog1(S.token.value, next);\n default:\n unexpected();\n }\n };\n\n function subscripts(expr, allow_calls) {\n if (is(\"punc\", \".\")) {\n next();\n return subscripts(as(\"dot\", expr, as_name()), allow_calls);\n }\n if (is(\"punc\", \"[\")) {\n next();\n return subscripts(as(\"sub\", expr, prog1(expression, curry(expect, \"]\"))), allow_calls);\n }\n if (allow_calls && is(\"punc\", \"(\")) {\n next();\n return subscripts(as(\"call\", expr, expr_list(\")\")), true);\n }\n return expr;\n };\n\n function maybe_unary(allow_calls) {\n if (is(\"operator\") && HOP(UNARY_PREFIX, S.token.value)) {\n return make_unary(\"unary-prefix\",\n prog1(S.token.value, next),\n maybe_unary(allow_calls));\n }\n var val = expr_atom(allow_calls);\n while (is(\"operator\") && HOP(UNARY_POSTFIX, S.token.value) && !S.token.nlb) {\n val = make_unary(\"unary-postfix\", S.token.value, val);\n next();\n }\n return val;\n };\n\n function make_unary(tag, op, expr) {\n if ((op == \"++\" || op == \"--\") && !is_assignable(expr))\n croak(\"Invalid use of \" + op + \" operator\");\n return as(tag, op, expr);\n };\n\n function expr_op(left, min_prec, no_in) {\n var op = is(\"operator\") ? S.token.value : null;\n if (op && op == \"in\" && no_in) op = null;\n var prec = op != null ? PRECEDENCE[op] : null;\n if (prec != null && prec > min_prec) {\n next();\n var right = expr_op(maybe_unary(true), prec, no_in);\n return expr_op(as(\"binary\", op, left, right), min_prec, no_in);\n }\n return left;\n };\n\n function expr_ops(no_in) {\n return expr_op(maybe_unary(true), 0, no_in);\n };\n\n function maybe_conditional(no_in) {\n var expr = expr_ops(no_in);\n if (is(\"operator\", \"?\")) {\n next();\n var yes = expression(false);\n expect(\":\");\n return as(\"conditional\", expr, yes, expression(false, no_in));\n }\n return expr;\n };\n\n function is_assignable(expr) {\n if (!exigent_mode) return true;\n switch (expr[0]+\"\") {\n case \"dot\":\n case \"sub\":\n case \"new\":\n case \"call\":\n return true;\n case \"name\":\n return expr[1] != \"this\";\n }\n };\n\n function maybe_assign(no_in) {\n var left = maybe_conditional(no_in), val = S.token.value;\n if (is(\"operator\") && HOP(ASSIGNMENT, val)) {\n if (is_assignable(left)) {\n next();\n return as(\"assign\", ASSIGNMENT[val], left, maybe_assign(no_in));\n }\n croak(\"Invalid assignment\");\n }\n return left;\n };\n\n var expression = maybe_embed_tokens(function(commas, no_in) {\n if (arguments.length == 0)\n commas = true;\n var expr = maybe_assign(no_in);\n if (commas && is(\"punc\", \",\")) {\n next();\n return as(\"seq\", expr, expression(true, no_in));\n }\n return expr;\n });\n\n function in_loop(cont) {\n try {\n ++S.in_loop;\n return cont();\n } finally {\n --S.in_loop;\n }\n };\n\n return as(\"toplevel\", (function(a){\n while (!is(\"eof\"))\n a.push(statement());\n return a;\n })([]));\n\n};\n\n/* -----[ Utilities ]----- */\n\nfunction curry(f) {\n var args = slice(arguments, 1);\n return function() { return f.apply(this, args.concat(slice(arguments))); };\n};\n\nfunction prog1(ret) {\n if (ret instanceof Function)\n ret = ret();\n for (var i = 1, n = arguments.length; --n > 0; ++i)\n arguments[i]();\n return ret;\n};\n\nfunction array_to_hash(a) {\n var ret = {};\n for (var i = 0; i < a.length; ++i)\n ret[a[i]] = true;\n return ret;\n};\n\nfunction slice(a, start) {\n return Array.prototype.slice.call(a, start || 0);\n};\n\nfunction characters(str) {\n return str.split(\"\");\n};\n\nfunction member(name, array) {\n for (var i = array.length; --i >= 0;)\n if (array[i] === name)\n return true;\n return false;\n};\n\nfunction HOP(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\nvar warn = function() {};\n\n/* -----[ Exports ]----- */\n\nexports.tokenizer = tokenizer;\nexports.parse = parse;\nexports.slice = slice;\nexports.curry = curry;\nexports.member = member;\nexports.array_to_hash = array_to_hash;\nexports.PRECEDENCE = PRECEDENCE;\nexports.KEYWORDS_ATOM = KEYWORDS_ATOM;\nexports.RESERVED_WORDS = RESERVED_WORDS;\nexports.KEYWORDS = KEYWORDS;\nexports.ATOMIC_START_TOKEN = ATOMIC_START_TOKEN;\nexports.OPERATORS = OPERATORS;\nexports.is_alphanumeric_char = is_alphanumeric_char;\nexports.set_logger = function(logger) {\n warn = logger;\n};\n\n});");spade.register("uglify-js/process", "(function(require, exports, __module, ARGV, ENV, __filename){/***********************************************************************\n\n A JavaScript tokenizer / parser / beautifier / compressor.\n\n This version is suitable for Node.js. With minimal changes (the\n exports stuff) it should work on any JS platform.\n\n This file implements some AST processors. They work on data built\n by parse-js.\n\n Exported functions:\n\n - ast_mangle(ast, options) -- mangles the variable/function names\n in the AST. Returns an AST.\n\n - ast_squeeze(ast) -- employs various optimizations to make the\n final generated code even smaller. Returns an AST.\n\n - gen_code(ast, options) -- generates JS code from the AST. Pass\n true (or an object, see the code for some options) as second\n argument to get \"pretty\" (indented) code.\n\n -------------------------------- (C) ---------------------------------\n\n Author: Mihai Bazon\n <mihai.bazon@gmail.com>\n http://mihai.bazon.net/blog\n\n Distributed under the BSD license:\n\n Copyright 2010 (c) Mihai Bazon <mihai.bazon@gmail.com>\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n\n * Redistributions of source code must retain the above\n copyright notice, this list of conditions and the following\n disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials\n provided with the distribution.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER \u0080\u009cAS IS\u0080\u009d AND ANY\n EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE\n LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,\n OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR\n TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF\n THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n SUCH DAMAGE.\n\n ***********************************************************************/\n\n\nvar jsp = require(\"./parse-js\"),\n slice = jsp.slice,\n member = jsp.member,\n PRECEDENCE = jsp.PRECEDENCE,\n OPERATORS = jsp.OPERATORS;\n\n/* -----[ helper for AST traversal ]----- */\n\nfunction ast_walker() {\n function _vardefs(defs) {\n return [ this[0], MAP(defs, function(def){\n var a = [ def[0] ];\n if (def.length > 1)\n a[1] = walk(def[1]);\n return a;\n }) ];\n };\n function _block(statements) {\n var out = [ this[0] ];\n if (statements != null)\n out.push(MAP(statements, walk));\n return out;\n };\n var walkers = {\n \"string\": function(str) {\n return [ this[0], str ];\n },\n \"num\": function(num) {\n return [ this[0], num ];\n },\n \"name\": function(name) {\n return [ this[0], name ];\n },\n \"toplevel\": function(statements) {\n return [ this[0], MAP(statements, walk) ];\n },\n \"block\": _block,\n \"splice\": _block,\n \"var\": _vardefs,\n \"const\": _vardefs,\n \"try\": function(t, c, f) {\n return [\n this[0],\n MAP(t, walk),\n c != null ? [ c[0], MAP(c[1], walk) ] : null,\n f != null ? MAP(f, walk) : null\n ];\n },\n \"throw\": function(expr) {\n return [ this[0], walk(expr) ];\n },\n \"new\": function(ctor, args) {\n return [ this[0], walk(ctor), MAP(args, walk) ];\n },\n \"switch\": function(expr, body) {\n return [ this[0], walk(expr), MAP(body, function(branch){\n return [ branch[0] ? walk(branch[0]) : null,\n MAP(branch[1], walk) ];\n }) ];\n },\n \"break\": function(label) {\n return [ this[0], label ];\n },\n \"continue\": function(label) {\n return [ this[0], label ];\n },\n \"conditional\": function(cond, t, e) {\n return [ this[0], walk(cond), walk(t), walk(e) ];\n },\n \"assign\": function(op, lvalue, rvalue) {\n return [ this[0], op, walk(lvalue), walk(rvalue) ];\n },\n \"dot\": function(expr) {\n return [ this[0], walk(expr) ].concat(slice(arguments, 1));\n },\n \"call\": function(expr, args) {\n return [ this[0], walk(expr), MAP(args, walk) ];\n },\n \"function\": function(name, args, body) {\n return [ this[0], name, args.slice(), MAP(body, walk) ];\n },\n \"defun\": function(name, args, body) {\n return [ this[0], name, args.slice(), MAP(body, walk) ];\n },\n \"if\": function(conditional, t, e) {\n return [ this[0], walk(conditional), walk(t), walk(e) ];\n },\n \"for\": function(init, cond, step, block) {\n return [ this[0], walk(init), walk(cond), walk(step), walk(block) ];\n },\n \"for-in\": function(vvar, key, hash, block) {\n return [ this[0], walk(vvar), walk(key), walk(hash), walk(block) ];\n },\n \"while\": function(cond, block) {\n return [ this[0], walk(cond), walk(block) ];\n },\n \"do\": function(cond, block) {\n return [ this[0], walk(cond), walk(block) ];\n },\n \"return\": function(expr) {\n return [ this[0], walk(expr) ];\n },\n \"binary\": function(op, left, right) {\n return [ this[0], op, walk(left), walk(right) ];\n },\n \"unary-prefix\": function(op, expr) {\n return [ this[0], op, walk(expr) ];\n },\n \"unary-postfix\": function(op, expr) {\n return [ this[0], op, walk(expr) ];\n },\n \"sub\": function(expr, subscript) {\n return [ this[0], walk(expr), walk(subscript) ];\n },\n \"object\": function(props) {\n return [ this[0], MAP(props, function(p){\n return p.length == 2\n ? [ p[0], walk(p[1]) ]\n : [ p[0], walk(p[1]), p[2] ]; // get/set-ter\n }) ];\n },\n \"regexp\": function(rx, mods) {\n return [ this[0], rx, mods ];\n },\n \"array\": function(elements) {\n return [ this[0], MAP(elements, walk) ];\n },\n \"stat\": function(stat) {\n return [ this[0], walk(stat) ];\n },\n \"seq\": function() {\n return [ this[0] ].concat(MAP(slice(arguments), walk));\n },\n \"label\": function(name, block) {\n return [ this[0], name, walk(block) ];\n },\n \"with\": function(expr, block) {\n return [ this[0], walk(expr), walk(block) ];\n },\n \"atom\": function(name) {\n return [ this[0], name ];\n }\n };\n\n var user = {};\n var stack = [];\n function walk(ast) {\n if (ast == null)\n return null;\n try {\n stack.push(ast);\n var type = ast[0];\n var gen = user[type];\n if (gen) {\n var ret = gen.apply(ast, ast.slice(1));\n if (ret != null)\n return ret;\n }\n gen = walkers[type];\n return gen.apply(ast, ast.slice(1));\n } finally {\n stack.pop();\n }\n };\n\n function dive(ast) {\n if (ast == null)\n return null;\n try {\n stack.push(ast);\n return walkers[ast[0]].apply(ast, ast.slice(1));\n } finally {\n stack.pop();\n }\n };\n\n function with_walkers(walkers, cont){\n var save = {}, i;\n for (i in walkers) if (HOP(walkers, i)) {\n save[i] = user[i];\n user[i] = walkers[i];\n }\n var ret = cont();\n for (i in save) if (HOP(save, i)) {\n if (!save[i]) delete user[i];\n else user[i] = save[i];\n }\n return ret;\n };\n\n return {\n walk: walk,\n dive: dive,\n with_walkers: with_walkers,\n parent: function() {\n return stack[stack.length - 2]; // last one is current node\n },\n stack: function() {\n return stack;\n }\n };\n};\n\n/* -----[ Scope and mangling ]----- */\n\nfunction Scope(parent) {\n this.names = {}; // names defined in this scope\n this.mangled = {}; // mangled names (orig.name => mangled)\n this.rev_mangled = {}; // reverse lookup (mangled => orig.name)\n this.cname = -1; // current mangled name\n this.refs = {}; // names referenced from this scope\n this.uses_with = false; // will become TRUE if with() is detected in this or any subscopes\n this.uses_eval = false; // will become TRUE if eval() is detected in this or any subscopes\n this.parent = parent; // parent scope\n this.children = []; // sub-scopes\n if (parent) {\n this.level = parent.level + 1;\n parent.children.push(this);\n } else {\n this.level = 0;\n }\n};\n\nvar base54 = (function(){\n var DIGITS = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_\";\n return function(num) {\n var ret = \"\";\n do {\n ret = DIGITS.charAt(num % 54) + ret;\n num = Math.floor(num / 54);\n } while (num > 0);\n return ret;\n };\n})();\n\nScope.prototype = {\n has: function(name) {\n for (var s = this; s; s = s.parent)\n if (HOP(s.names, name))\n return s;\n },\n has_mangled: function(mname) {\n for (var s = this; s; s = s.parent)\n if (HOP(s.rev_mangled, mname))\n return s;\n },\n toJSON: function() {\n return {\n names: this.names,\n uses_eval: this.uses_eval,\n uses_with: this.uses_with\n };\n },\n\n next_mangled: function() {\n // we must be careful that the new mangled name:\n //\n // 1. doesn't shadow a mangled name from a parent\n // scope, unless we don't reference the original\n // name from this scope OR from any sub-scopes!\n // This will get slow.\n //\n // 2. doesn't shadow an original name from a parent\n // scope, in the event that the name is not mangled\n // in the parent scope and we reference that name\n // here OR IN ANY SUBSCOPES!\n //\n // 3. doesn't shadow a name that is referenced but not\n // defined (possibly global defined elsewhere).\n for (;;) {\n var m = base54(++this.cname), prior;\n\n // case 1.\n prior = this.has_mangled(m);\n if (prior && this.refs[prior.rev_mangled[m]] === prior)\n continue;\n\n // case 2.\n prior = this.has(m);\n if (prior && prior !== this && this.refs[m] === prior && !prior.has_mangled(m))\n continue;\n\n // case 3.\n if (HOP(this.refs, m) && this.refs[m] == null)\n continue;\n\n // I got \"do\" once. :-/\n if (!is_identifier(m))\n continue;\n\n return m;\n }\n },\n set_mangle: function(name, m) {\n this.rev_mangled[m] = name;\n return this.mangled[name] = m;\n },\n get_mangled: function(name, newMangle) {\n if (this.uses_eval || this.uses_with) return name; // no mangle if eval or with is in use\n var s = this.has(name);\n if (!s) return name; // not in visible scope, no mangle\n if (HOP(s.mangled, name)) return s.mangled[name]; // already mangled in this scope\n if (!newMangle) return name; // not found and no mangling requested\n return s.set_mangle(name, s.next_mangled());\n },\n references: function(name) {\n return name && !this.parent || this.uses_with || this.uses_eval || this.refs[name];\n },\n define: function(name, type) {\n if (name != null) {\n if (type == \"var\" || !HOP(this.names, name))\n this.names[name] = type || \"var\";\n return name;\n }\n }\n};\n\nfunction ast_add_scope(ast) {\n\n var current_scope = null;\n var w = ast_walker(), walk = w.walk;\n var having_eval = [];\n\n function with_new_scope(cont) {\n current_scope = new Scope(current_scope);\n var ret = current_scope.body = cont();\n ret.scope = current_scope;\n current_scope = current_scope.parent;\n return ret;\n };\n\n function define(name, type) {\n return current_scope.define(name, type);\n };\n\n function reference(name) {\n current_scope.refs[name] = true;\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\";\n return [ this[0], is_defun ? define(name, \"defun\") : name, args, with_new_scope(function(){\n if (!is_defun) define(name, \"lambda\");\n MAP(args, function(name){ define(name, \"arg\") });\n return MAP(body, walk);\n })];\n };\n\n function _vardefs(type) {\n return function(defs) {\n MAP(defs, function(d){\n define(d[0], type);\n if (d[1]) reference(d[0]);\n });\n };\n };\n\n return with_new_scope(function(){\n // process AST\n var ret = w.with_walkers({\n \"function\": _lambda,\n \"defun\": _lambda,\n \"label\": function(name, stat) { define(name, \"label\") },\n \"break\": function(label) { if (label) reference(label) },\n \"continue\": function(label) { if (label) reference(label) },\n \"with\": function(expr, block) {\n for (var s = current_scope; s; s = s.parent)\n s.uses_with = true;\n },\n \"var\": _vardefs(\"var\"),\n \"const\": _vardefs(\"const\"),\n \"try\": function(t, c, f) {\n if (c != null) return [\n this[0],\n MAP(t, walk),\n [ define(c[0], \"catch\"), MAP(c[1], walk) ],\n f != null ? MAP(f, walk) : null\n ];\n },\n \"name\": function(name) {\n if (name == \"eval\")\n having_eval.push(current_scope);\n reference(name);\n }\n }, function(){\n return walk(ast);\n });\n\n // the reason why we need an additional pass here is\n // that names can be used prior to their definition.\n\n // scopes where eval was detected and their parents\n // are marked with uses_eval, unless they define the\n // \"eval\" name.\n MAP(having_eval, function(scope){\n if (!scope.has(\"eval\")) while (scope) {\n scope.uses_eval = true;\n scope = scope.parent;\n }\n });\n\n // for referenced names it might be useful to know\n // their origin scope. current_scope here is the\n // toplevel one.\n function fixrefs(scope, i) {\n // do children first; order shouldn't matter\n for (i = scope.children.length; --i >= 0;)\n fixrefs(scope.children[i]);\n for (i in scope.refs) if (HOP(scope.refs, i)) {\n // find origin scope and propagate the reference to origin\n for (var origin = scope.has(i), s = scope; s; s = s.parent) {\n s.refs[i] = origin;\n if (s === origin) break;\n }\n }\n };\n fixrefs(current_scope);\n\n return ret;\n });\n\n};\n\n/* -----[ mangle names ]----- */\n\nfunction ast_mangle(ast, options) {\n var w = ast_walker(), walk = w.walk, scope;\n options = options || {};\n\n function get_mangled(name, newMangle) {\n if (!options.toplevel && !scope.parent) return name; // don't mangle toplevel\n if (options.except && member(name, options.except))\n return name;\n return scope.get_mangled(name, newMangle);\n };\n\n function get_define(name) {\n if (options.defines) {\n // we always lookup a defined symbol for the current scope FIRST, so declared\n // vars trump a DEFINE symbol, but if no such var is found, then match a DEFINE value\n if (!scope.has(name)) {\n if (HOP(options.defines, name)) {\n return options.defines[name];\n }\n }\n return null;\n }\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\", extra;\n if (name) {\n if (is_defun) name = get_mangled(name);\n else {\n extra = {};\n if (!(scope.uses_eval || scope.uses_with))\n name = extra[name] = scope.next_mangled();\n else\n extra[name] = name;\n }\n }\n body = with_scope(body.scope, function(){\n args = MAP(args, function(name){ return get_mangled(name) });\n return MAP(body, walk);\n }, extra);\n return [ this[0], name, args, body ];\n };\n\n function with_scope(s, cont, extra) {\n var _scope = scope;\n scope = s;\n if (extra) for (var i in extra) if (HOP(extra, i)) {\n s.set_mangle(i, extra[i]);\n }\n for (var i in s.names) if (HOP(s.names, i)) {\n get_mangled(i, true);\n }\n var ret = cont();\n ret.scope = s;\n scope = _scope;\n return ret;\n };\n\n function _vardefs(defs) {\n return [ this[0], MAP(defs, function(d){\n return [ get_mangled(d[0]), walk(d[1]) ];\n }) ];\n };\n\n return w.with_walkers({\n \"function\": _lambda,\n \"defun\": function() {\n // move function declarations to the top when\n // they are not in some block.\n var ast = _lambda.apply(this, arguments);\n switch (w.parent()[0]) {\n case \"toplevel\":\n case \"function\":\n case \"defun\":\n return MAP.at_top(ast);\n }\n return ast;\n },\n \"label\": function(label, stat) { return [ this[0], get_mangled(label), walk(stat) ] },\n \"break\": function(label) { if (label) return [ this[0], get_mangled(label) ] },\n \"continue\": function(label) { if (label) return [ this[0], get_mangled(label) ] },\n \"var\": _vardefs,\n \"const\": _vardefs,\n \"name\": function(name) {\n return get_define(name) || [ this[0], get_mangled(name) ];\n },\n \"try\": function(t, c, f) {\n return [ this[0],\n MAP(t, walk),\n c != null ? [ get_mangled(c[0]), MAP(c[1], walk) ] : null,\n f != null ? MAP(f, walk) : null ];\n },\n \"toplevel\": function(body) {\n var self = this;\n return with_scope(self.scope, function(){\n return [ self[0], MAP(body, walk) ];\n });\n }\n }, function() {\n return walk(ast_add_scope(ast));\n });\n};\n\n/* -----[\n - compress foo[\"bar\"] into foo.bar,\n - remove block brackets {} where possible\n - join consecutive var declarations\n - various optimizations for IFs:\n - if (cond) foo(); else bar(); ==> cond?foo():bar();\n - if (cond) foo(); ==> cond&&foo();\n - if (foo) return bar(); else return baz(); ==> return foo?bar():baz(); // also for throw\n - if (foo) return bar(); else something(); ==> {if(foo)return bar();something()}\n ]----- */\n\nvar warn = function(){};\n\nfunction best_of(ast1, ast2) {\n return gen_code(ast1).length > gen_code(ast2[0] == \"stat\" ? ast2[1] : ast2).length ? ast2 : ast1;\n};\n\nfunction last_stat(b) {\n if (b[0] == \"block\" && b[1] && b[1].length > 0)\n return b[1][b[1].length - 1];\n return b;\n}\n\nfunction aborts(t) {\n if (t) switch (last_stat(t)[0]) {\n case \"return\":\n case \"break\":\n case \"continue\":\n case \"throw\":\n return true;\n }\n};\n\nfunction boolean_expr(expr) {\n return ( (expr[0] == \"unary-prefix\"\n && member(expr[1], [ \"!\", \"delete\" ])) ||\n\n (expr[0] == \"binary\"\n && member(expr[1], [ \"in\", \"instanceof\", \"==\", \"!=\", \"===\", \"!==\", \"<\", \"<=\", \">=\", \">\" ])) ||\n\n (expr[0] == \"binary\"\n && member(expr[1], [ \"&&\", \"||\" ])\n && boolean_expr(expr[2])\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"conditional\"\n && boolean_expr(expr[2])\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"assign\"\n && expr[1] === true\n && boolean_expr(expr[3])) ||\n\n (expr[0] == \"seq\"\n && boolean_expr(expr[expr.length - 1]))\n );\n};\n\nfunction make_conditional(c, t, e) {\n var make_real_conditional = function() {\n if (c[0] == \"unary-prefix\" && c[1] == \"!\") {\n return e ? [ \"conditional\", c[2], e, t ] : [ \"binary\", \"||\", c[2], t ];\n } else {\n return e ? [ \"conditional\", c, t, e ] : [ \"binary\", \"&&\", c, t ];\n }\n };\n // shortcut the conditional if the expression has a constant value\n return when_constant(c, function(ast, val){\n warn_unreachable(val ? e : t);\n return (val ? t : e);\n }, make_real_conditional);\n};\n\nfunction empty(b) {\n return !b || (b[0] == \"block\" && (!b[1] || b[1].length == 0));\n};\n\nfunction is_string(node) {\n return (node[0] == \"string\" ||\n node[0] == \"unary-prefix\" && node[1] == \"typeof\" ||\n node[0] == \"binary\" && node[1] == \"+\" &&\n (is_string(node[2]) || is_string(node[3])));\n};\n\nvar when_constant = (function(){\n\n var $NOT_CONSTANT = {};\n\n // this can only evaluate constant expressions. If it finds anything\n // not constant, it throws $NOT_CONSTANT.\n function evaluate(expr) {\n switch (expr[0]) {\n case \"string\":\n case \"num\":\n return expr[1];\n case \"name\":\n case \"atom\":\n switch (expr[1]) {\n case \"true\": return true;\n case \"false\": return false;\n }\n break;\n case \"unary-prefix\":\n switch (expr[1]) {\n case \"!\": return !evaluate(expr[2]);\n case \"typeof\": return typeof evaluate(expr[2]);\n case \"~\": return ~evaluate(expr[2]);\n case \"-\": return -evaluate(expr[2]);\n case \"+\": return +evaluate(expr[2]);\n }\n break;\n case \"binary\":\n var left = expr[2], right = expr[3];\n switch (expr[1]) {\n case \"&&\" : return evaluate(left) && evaluate(right);\n case \"||\" : return evaluate(left) || evaluate(right);\n case \"|\" : return evaluate(left) | evaluate(right);\n case \"&\" : return evaluate(left) & evaluate(right);\n case \"^\" : return evaluate(left) ^ evaluate(right);\n case \"+\" : return evaluate(left) + evaluate(right);\n case \"*\" : return evaluate(left) * evaluate(right);\n case \"/\" : return evaluate(left) / evaluate(right);\n case \"%\" : return evaluate(left) % evaluate(right);\n case \"-\" : return evaluate(left) - evaluate(right);\n case \"<<\" : return evaluate(left) << evaluate(right);\n case \">>\" : return evaluate(left) >> evaluate(right);\n case \">>>\" : return evaluate(left) >>> evaluate(right);\n case \"==\" : return evaluate(left) == evaluate(right);\n case \"===\" : return evaluate(left) === evaluate(right);\n case \"!=\" : return evaluate(left) != evaluate(right);\n case \"!==\" : return evaluate(left) !== evaluate(right);\n case \"<\" : return evaluate(left) < evaluate(right);\n case \"<=\" : return evaluate(left) <= evaluate(right);\n case \">\" : return evaluate(left) > evaluate(right);\n case \">=\" : return evaluate(left) >= evaluate(right);\n case \"in\" : return evaluate(left) in evaluate(right);\n case \"instanceof\" : return evaluate(left) instanceof evaluate(right);\n }\n }\n throw $NOT_CONSTANT;\n };\n\n return function(expr, yes, no) {\n try {\n var val = evaluate(expr), ast;\n switch (typeof val) {\n case \"string\": ast = [ \"string\", val ]; break;\n case \"number\": ast = [ \"num\", val ]; break;\n case \"boolean\": ast = [ \"name\", String(val) ]; break;\n default: throw new Error(\"Can't handle constant of type: \" + (typeof val));\n }\n return yes.call(expr, ast, val);\n } catch(ex) {\n if (ex === $NOT_CONSTANT) {\n if (expr[0] == \"binary\"\n && (expr[1] == \"===\" || expr[1] == \"!==\")\n && ((is_string(expr[2]) && is_string(expr[3]))\n || (boolean_expr(expr[2]) && boolean_expr(expr[3])))) {\n expr[1] = expr[1].substr(0, 2);\n }\n else if (no && expr[0] == \"binary\"\n && (expr[1] == \"||\" || expr[1] == \"&&\")) {\n // the whole expression is not constant but the lval may be...\n try {\n var lval = evaluate(expr[2]);\n expr = ((expr[1] == \"&&\" && (lval ? expr[3] : lval)) ||\n (expr[1] == \"||\" && (lval ? lval : expr[3])) ||\n expr);\n } catch(ex2) {\n // IGNORE... lval is not constant\n }\n }\n return no ? no.call(expr, expr) : null;\n }\n else throw ex;\n }\n };\n\n})();\n\nfunction warn_unreachable(ast) {\n if (!empty(ast))\n warn(\"Dropping unreachable code: \" + gen_code(ast, true));\n};\n\nfunction prepare_ifs(ast) {\n var w = ast_walker(), walk = w.walk;\n // In this first pass, we rewrite ifs which abort with no else with an\n // if-else. For example:\n //\n // if (x) {\n // blah();\n // return y;\n // }\n // foobar();\n //\n // is rewritten into:\n //\n // if (x) {\n // blah();\n // return y;\n // } else {\n // foobar();\n // }\n function redo_if(statements) {\n statements = MAP(statements, walk);\n\n for (var i = 0; i < statements.length; ++i) {\n var fi = statements[i];\n if (fi[0] != \"if\") continue;\n\n if (fi[3] && walk(fi[3])) continue;\n\n var t = walk(fi[2]);\n if (!aborts(t)) continue;\n\n var conditional = walk(fi[1]);\n\n var e_body = statements.slice(i + 1);\n var e = e_body.length == 1 ? e_body[0] : [ \"block\", e_body ];\n\n var ret = statements.slice(0, i).concat([ [\n fi[0], // \"if\"\n conditional, // conditional\n t, // then\n e // else\n ] ]);\n\n return redo_if(ret);\n }\n\n return statements;\n };\n\n function redo_if_lambda(name, args, body) {\n body = redo_if(body);\n return [ this[0], name, args, body ];\n };\n\n function redo_if_block(statements) {\n return [ this[0], statements != null ? redo_if(statements) : null ];\n };\n\n return w.with_walkers({\n \"defun\": redo_if_lambda,\n \"function\": redo_if_lambda,\n \"block\": redo_if_block,\n \"splice\": redo_if_block,\n \"toplevel\": function(statements) {\n return [ this[0], redo_if(statements) ];\n },\n \"try\": function(t, c, f) {\n return [\n this[0],\n redo_if(t),\n c != null ? [ c[0], redo_if(c[1]) ] : null,\n f != null ? redo_if(f) : null\n ];\n }\n }, function() {\n return walk(ast);\n });\n};\n\nfunction for_side_effects(ast, handler) {\n var w = ast_walker(), walk = w.walk;\n var $stop = {}, $restart = {};\n function stop() { throw $stop };\n function restart() { throw $restart };\n function found(){ return handler.call(this, this, w, stop, restart) };\n function unary(op) {\n if (op == \"++\" || op == \"--\")\n return found.apply(this, arguments);\n };\n return w.with_walkers({\n \"try\": found,\n \"throw\": found,\n \"return\": found,\n \"new\": found,\n \"switch\": found,\n \"break\": found,\n \"continue\": found,\n \"assign\": found,\n \"call\": found,\n \"if\": found,\n \"for\": found,\n \"for-in\": found,\n \"while\": found,\n \"do\": found,\n \"return\": found,\n \"unary-prefix\": unary,\n \"unary-postfix\": unary,\n \"defun\": found\n }, function(){\n while (true) try {\n walk(ast);\n break;\n } catch(ex) {\n if (ex === $stop) break;\n if (ex === $restart) continue;\n throw ex;\n }\n });\n};\n\nfunction ast_lift_variables(ast) {\n var w = ast_walker(), walk = w.walk, scope;\n function do_body(body, env) {\n var _scope = scope;\n scope = env;\n body = MAP(body, walk);\n var hash = {}, names = MAP(env.names, function(type, name){\n if (type != \"var\") return MAP.skip;\n if (!env.references(name)) return MAP.skip;\n hash[name] = true;\n return [ name ];\n });\n if (names.length > 0) {\n // looking for assignments to any of these variables.\n // we can save considerable space by moving the definitions\n // in the var declaration.\n for_side_effects([ \"block\", body ], function(ast, walker, stop, restart) {\n if (ast[0] == \"assign\"\n && ast[1] === true\n && ast[2][0] == \"name\"\n && HOP(hash, ast[2][1])) {\n // insert the definition into the var declaration\n for (var i = names.length; --i >= 0;) {\n if (names[i][0] == ast[2][1]) {\n if (names[i][1]) // this name already defined, we must stop\n stop();\n names[i][1] = ast[3]; // definition\n names.push(names.splice(i, 1)[0]);\n break;\n }\n }\n // remove this assignment from the AST.\n var p = walker.parent();\n if (p[0] == \"seq\") {\n var a = p[2];\n a.unshift(0, p.length);\n p.splice.apply(p, a);\n }\n else if (p[0] == \"stat\") {\n p.splice(0, p.length, \"block\"); // empty statement\n }\n else {\n stop();\n }\n restart();\n }\n stop();\n });\n body.unshift([ \"var\", names ]);\n }\n scope = _scope;\n return body;\n };\n function _vardefs(defs) {\n var ret = null;\n for (var i = defs.length; --i >= 0;) {\n var d = defs[i];\n if (!d[1]) continue;\n d = [ \"assign\", true, [ \"name\", d[0] ], d[1] ];\n if (ret == null) ret = d;\n else ret = [ \"seq\", d, ret ];\n }\n if (ret == null) {\n if (w.parent()[0] == \"for-in\")\n return [ \"name\", defs[0][0] ];\n return MAP.skip;\n }\n return [ \"stat\", ret ];\n };\n function _toplevel(body) {\n return [ this[0], do_body(body, this.scope) ];\n };\n return w.with_walkers({\n \"function\": function(name, args, body){\n for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)\n args.pop();\n if (!body.scope.references(name)) name = null;\n return [ this[0], name, args, do_body(body, body.scope) ];\n },\n \"defun\": function(name, args, body){\n if (!scope.references(name)) return MAP.skip;\n for (var i = args.length; --i >= 0 && !body.scope.references(args[i]);)\n args.pop();\n return [ this[0], name, args, do_body(body, body.scope) ];\n },\n \"var\": _vardefs,\n \"toplevel\": _toplevel\n }, function(){\n return walk(ast_add_scope(ast));\n });\n};\n\nfunction ast_squeeze(ast, options) {\n options = defaults(options, {\n make_seqs : true,\n dead_code : true,\n keep_comps : true,\n no_warnings : false\n });\n\n var w = ast_walker(), walk = w.walk, scope;\n\n function negate(c) {\n var not_c = [ \"unary-prefix\", \"!\", c ];\n switch (c[0]) {\n case \"unary-prefix\":\n return c[1] == \"!\" && boolean_expr(c[2]) ? c[2] : not_c;\n case \"seq\":\n c = slice(c);\n c[c.length - 1] = negate(c[c.length - 1]);\n return c;\n case \"conditional\":\n return best_of(not_c, [ \"conditional\", c[1], negate(c[2]), negate(c[3]) ]);\n case \"binary\":\n var op = c[1], left = c[2], right = c[3];\n if (!options.keep_comps) switch (op) {\n case \"<=\" : return [ \"binary\", \">\", left, right ];\n case \"<\" : return [ \"binary\", \">=\", left, right ];\n case \">=\" : return [ \"binary\", \"<\", left, right ];\n case \">\" : return [ \"binary\", \"<=\", left, right ];\n }\n switch (op) {\n case \"==\" : return [ \"binary\", \"!=\", left, right ];\n case \"!=\" : return [ \"binary\", \"==\", left, right ];\n case \"===\" : return [ \"binary\", \"!==\", left, right ];\n case \"!==\" : return [ \"binary\", \"===\", left, right ];\n case \"&&\" : return best_of(not_c, [ \"binary\", \"||\", negate(left), negate(right) ]);\n case \"||\" : return best_of(not_c, [ \"binary\", \"&&\", negate(left), negate(right) ]);\n }\n break;\n }\n return not_c;\n };\n\n function with_scope(s, cont) {\n var _scope = scope;\n scope = s;\n var ret = cont();\n ret.scope = s;\n scope = _scope;\n return ret;\n };\n\n function rmblock(block) {\n if (block != null && block[0] == \"block\" && block[1]) {\n if (block[1].length == 1)\n block = block[1][0];\n else if (block[1].length == 0)\n block = [ \"block\" ];\n }\n return block;\n };\n\n function _lambda(name, args, body) {\n var is_defun = this[0] == \"defun\";\n body = with_scope(body.scope, function(){\n var ret = tighten(body, \"lambda\");\n if (!is_defun && name && !scope.references(name))\n name = null;\n return ret;\n });\n return [ this[0], name, args, body ];\n };\n\n // this function does a few things:\n // 1. discard useless blocks\n // 2. join consecutive var declarations\n // 3. remove obviously dead code\n // 4. transform consecutive statements using the comma operator\n // 5. if block_type == \"lambda\" and it detects constructs like if(foo) return ... - rewrite like if (!foo) { ... }\n function tighten(statements, block_type) {\n statements = MAP(statements, walk);\n\n statements = statements.reduce(function(a, stat){\n if (stat[0] == \"block\") {\n if (stat[1]) {\n a.push.apply(a, stat[1]);\n }\n } else {\n a.push(stat);\n }\n return a;\n }, []);\n\n statements = (function(a, prev){\n statements.forEach(function(cur){\n if (prev && ((cur[0] == \"var\" && prev[0] == \"var\") ||\n (cur[0] == \"const\" && prev[0] == \"const\"))) {\n prev[1] = prev[1].concat(cur[1]);\n } else {\n a.push(cur);\n prev = cur;\n }\n });\n return a;\n })([]);\n\n if (options.dead_code) statements = (function(a, has_quit){\n statements.forEach(function(st){\n if (has_quit) {\n if (st[0] == \"function\" || st[0] == \"defun\") {\n a.push(st);\n }\n else if (st[0] == \"var\" || st[0] == \"const\") {\n if (!options.no_warnings)\n warn(\"Variables declared in unreachable code\");\n st[1] = MAP(st[1], function(def){\n if (def[1] && !options.no_warnings)\n warn_unreachable([ \"assign\", true, [ \"name\", def[0] ], def[1] ]);\n return [ def[0] ];\n });\n a.push(st);\n }\n else if (!options.no_warnings)\n warn_unreachable(st);\n }\n else {\n a.push(st);\n if (member(st[0], [ \"return\", \"throw\", \"break\", \"continue\" ]))\n has_quit = true;\n }\n });\n return a;\n })([]);\n\n if (options.make_seqs) statements = (function(a, prev) {\n statements.forEach(function(cur){\n if (prev && prev[0] == \"stat\" && cur[0] == \"stat\") {\n prev[1] = [ \"seq\", prev[1], cur[1] ];\n } else {\n a.push(cur);\n prev = cur;\n }\n });\n if (a.length >= 2\n && a[a.length-2][0] == \"stat\"\n && (a[a.length-1][0] == \"return\" || a[a.length-1][0] == \"throw\")\n && a[a.length-1][1])\n {\n a.splice(a.length - 2, 2,\n [ a[a.length-1][0],\n [ \"seq\", a[a.length-2][1], a[a.length-1][1] ]]);\n }\n return a;\n })([]);\n\n // this increases jQuery by 1K. Probably not such a good idea after all..\n // part of this is done in prepare_ifs anyway.\n // if (block_type == \"lambda\") statements = (function(i, a, stat){\n // while (i < statements.length) {\n // stat = statements[i++];\n // if (stat[0] == \"if\" && !stat[3]) {\n // if (stat[2][0] == \"return\" && stat[2][1] == null) {\n // a.push(make_if(negate(stat[1]), [ \"block\", statements.slice(i) ]));\n // break;\n // }\n // var last = last_stat(stat[2]);\n // if (last[0] == \"return\" && last[1] == null) {\n // a.push(make_if(stat[1], [ \"block\", stat[2][1].slice(0, -1) ], [ \"block\", statements.slice(i) ]));\n // break;\n // }\n // }\n // a.push(stat);\n // }\n // return a;\n // })(0, []);\n\n return statements;\n };\n\n function make_if(c, t, e) {\n return when_constant(c, function(ast, val){\n if (val) {\n warn_unreachable(e);\n return t;\n } else {\n warn_unreachable(t);\n return e;\n }\n }, function() {\n return make_real_if(c, t, e);\n });\n };\n\n function make_real_if(c, t, e) {\n c = walk(c);\n t = walk(t);\n e = walk(e);\n\n if (empty(t)) {\n c = negate(c);\n t = e;\n e = null;\n } else if (empty(e)) {\n e = null;\n } else {\n // if we have both else and then, maybe it makes sense to switch them?\n (function(){\n var a = gen_code(c);\n var n = negate(c);\n var b = gen_code(n);\n if (b.length < a.length) {\n var tmp = t;\n t = e;\n e = tmp;\n c = n;\n }\n })();\n }\n if (empty(e) && empty(t))\n return [ \"stat\", c ];\n var ret = [ \"if\", c, t, e ];\n if (t[0] == \"if\" && empty(t[3]) && empty(e)) {\n ret = best_of(ret, walk([ \"if\", [ \"binary\", \"&&\", c, t[1] ], t[2] ]));\n }\n else if (t[0] == \"stat\") {\n if (e) {\n if (e[0] == \"stat\") {\n ret = best_of(ret, [ \"stat\", make_conditional(c, t[1], e[1]) ]);\n }\n }\n else {\n ret = best_of(ret, [ \"stat\", make_conditional(c, t[1]) ]);\n }\n }\n else if (e && t[0] == e[0] && (t[0] == \"return\" || t[0] == \"throw\") && t[1] && e[1]) {\n ret = best_of(ret, [ t[0], make_conditional(c, t[1], e[1] ) ]);\n }\n else if (e && aborts(t)) {\n ret = [ [ \"if\", c, t ] ];\n if (e[0] == \"block\") {\n if (e[1]) ret = ret.concat(e[1]);\n }\n else {\n ret.push(e);\n }\n ret = walk([ \"block\", ret ]);\n }\n else if (t && aborts(e)) {\n ret = [ [ \"if\", negate(c), e ] ];\n if (t[0] == \"block\") {\n if (t[1]) ret = ret.concat(t[1]);\n } else {\n ret.push(t);\n }\n ret = walk([ \"block\", ret ]);\n }\n return ret;\n };\n\n function _do_while(cond, body) {\n return when_constant(cond, function(cond, val){\n if (!val) {\n warn_unreachable(body);\n return [ \"block\" ];\n } else {\n return [ \"for\", null, null, null, walk(body) ];\n }\n });\n };\n\n return w.with_walkers({\n \"sub\": function(expr, subscript) {\n if (subscript[0] == \"string\") {\n var name = subscript[1];\n if (is_identifier(name))\n return [ \"dot\", walk(expr), name ];\n else if (/^[1-9][0-9]*$/.test(name) || name === \"0\")\n return [ \"sub\", walk(expr), [ \"num\", parseInt(name, 10) ] ];\n }\n },\n \"if\": make_if,\n \"toplevel\": function(body) {\n return [ \"toplevel\", with_scope(this.scope, function(){\n return tighten(body);\n }) ];\n },\n \"switch\": function(expr, body) {\n var last = body.length - 1;\n return [ \"switch\", walk(expr), MAP(body, function(branch, i){\n var block = tighten(branch[1]);\n if (i == last && block.length > 0) {\n var node = block[block.length - 1];\n if (node[0] == \"break\" && !node[1])\n block.pop();\n }\n return [ branch[0] ? walk(branch[0]) : null, block ];\n }) ];\n },\n \"function\": _lambda,\n \"defun\": _lambda,\n \"block\": function(body) {\n if (body) return rmblock([ \"block\", tighten(body) ]);\n },\n \"binary\": function(op, left, right) {\n return when_constant([ \"binary\", op, walk(left), walk(right) ], function yes(c){\n return best_of(walk(c), this);\n }, function no() {\n return this;\n });\n },\n \"conditional\": function(c, t, e) {\n return make_conditional(walk(c), walk(t), walk(e));\n },\n \"try\": function(t, c, f) {\n return [\n \"try\",\n tighten(t),\n c != null ? [ c[0], tighten(c[1]) ] : null,\n f != null ? tighten(f) : null\n ];\n },\n \"unary-prefix\": function(op, expr) {\n expr = walk(expr);\n var ret = [ \"unary-prefix\", op, expr ];\n if (op == \"!\")\n ret = best_of(ret, negate(expr));\n return when_constant(ret, function(ast, val){\n return walk(ast); // it's either true or false, so minifies to !0 or !1\n }, function() { return ret });\n },\n \"name\": function(name) {\n switch (name) {\n case \"true\": return [ \"unary-prefix\", \"!\", [ \"num\", 0 ]];\n case \"false\": return [ \"unary-prefix\", \"!\", [ \"num\", 1 ]];\n }\n },\n \"while\": _do_while\n }, function() {\n for (var i = 0; i < 2; ++i) {\n ast = prepare_ifs(ast);\n ast = ast_add_scope(ast);\n ast = walk(ast);\n }\n return ast;\n });\n};\n\n/* -----[ re-generate code from the AST ]----- */\n\nvar DOT_CALL_NO_PARENS = jsp.array_to_hash([\n \"name\",\n \"array\",\n \"object\",\n \"string\",\n \"dot\",\n \"sub\",\n \"call\",\n \"regexp\"\n]);\n\nfunction make_string(str, ascii_only) {\n var dq = 0, sq = 0;\n str = str.replace(/[\\\\\\b\\f\\n\\r\\t\\x22\\x27\\u2028\\u2029]/g, function(s){\n switch (s) {\n case \"\\\\\": return \"\\\\\\\\\";\n case \"\\b\": return \"\\\\b\";\n case \"\\f\": return \"\\\\f\";\n case \"\\n\": return \"\\\\n\";\n case \"\\r\": return \"\\\\r\";\n case \"\\t\": return \"\\\\t\";\n case \"\\u2028\": return \"\\\\u2028\";\n case \"\\u2029\": return \"\\\\u2029\";\n case '\"': ++dq; return '\"';\n case \"'\": ++sq; return \"'\";\n }\n return s;\n });\n if (ascii_only) str = to_ascii(str);\n if (dq > sq) return \"'\" + str.replace(/\\x27/g, \"\\\\'\") + \"'\";\n else return '\"' + str.replace(/\\x22/g, '\\\\\"') + '\"';\n};\n\nfunction to_ascii(str) {\n return str.replace(/[\\u0080-\\uffff]/g, function(ch) {\n var code = ch.charCodeAt(0).toString(16);\n while (code.length < 4) code = \"0\" + code;\n return \"\\\\u\" + code;\n });\n};\n\nvar SPLICE_NEEDS_BRACKETS = jsp.array_to_hash([ \"if\", \"while\", \"do\", \"for\", \"for-in\", \"with\" ]);\n\nfunction gen_code(ast, options) {\n options = defaults(options, {\n indent_start : 0,\n indent_level : 4,\n quote_keys : false,\n space_colon : false,\n beautify : false,\n ascii_only : false,\n inline_script: false\n });\n var beautify = !!options.beautify;\n var indentation = 0,\n newline = beautify ? \"\\n\" : \"\",\n space = beautify ? \" \" : \"\";\n\n function encode_string(str) {\n var ret = make_string(str, options.ascii_only);\n if (options.inline_script)\n ret = ret.replace(/<\\x2fscript([>/\\t\\n\\f\\r ])/gi, \"<\\\\/script$1\");\n return ret;\n };\n\n function make_name(name) {\n name = name.toString();\n if (options.ascii_only)\n name = to_ascii(name);\n return name;\n };\n\n function indent(line) {\n if (line == null)\n line = \"\";\n if (beautify)\n line = repeat_string(\" \", options.indent_start + indentation * options.indent_level) + line;\n return line;\n };\n\n function with_indent(cont, incr) {\n if (incr == null) incr = 1;\n indentation += incr;\n try { return cont.apply(null, slice(arguments, 1)); }\n finally { indentation -= incr; }\n };\n\n function add_spaces(a) {\n if (beautify)\n return a.join(\" \");\n var b = [];\n for (var i = 0; i < a.length; ++i) {\n var next = a[i + 1];\n b.push(a[i]);\n if (next &&\n ((/[a-z0-9_\\x24]$/i.test(a[i].toString()) && /^[a-z0-9_\\x24]/i.test(next.toString())) ||\n (/[\\+\\-]$/.test(a[i].toString()) && /^[\\+\\-]/.test(next.toString())))) {\n b.push(\" \");\n }\n }\n return b.join(\"\");\n };\n\n function add_commas(a) {\n return a.join(\",\" + space);\n };\n\n function parenthesize(expr) {\n var gen = make(expr);\n for (var i = 1; i < arguments.length; ++i) {\n var el = arguments[i];\n if ((el instanceof Function && el(expr)) || expr[0] == el)\n return \"(\" + gen + \")\";\n }\n return gen;\n };\n\n function best_of(a) {\n if (a.length == 1) {\n return a[0];\n }\n if (a.length == 2) {\n var b = a[1];\n a = a[0];\n return a.length <= b.length ? a : b;\n }\n return best_of([ a[0], best_of(a.slice(1)) ]);\n };\n\n function needs_parens(expr) {\n if (expr[0] == \"function\" || expr[0] == \"object\") {\n // dot/call on a literal function requires the\n // function literal itself to be parenthesized\n // only if it's the first \"thing\" in a\n // statement. This means that the parent is\n // \"stat\", but it could also be a \"seq\" and\n // we're the first in this \"seq\" and the\n // parent is \"stat\", and so on. Messy stuff,\n // but it worths the trouble.\n var a = slice(w.stack()), self = a.pop(), p = a.pop();\n while (p) {\n if (p[0] == \"stat\") return true;\n if (((p[0] == \"seq\" || p[0] == \"call\" || p[0] == \"dot\" || p[0] == \"sub\" || p[0] == \"conditional\") && p[1] === self) ||\n ((p[0] == \"binary\" || p[0] == \"assign\" || p[0] == \"unary-postfix\") && p[2] === self)) {\n self = p;\n p = a.pop();\n } else {\n return false;\n }\n }\n }\n return !HOP(DOT_CALL_NO_PARENS, expr[0]);\n };\n\n function make_num(num) {\n var str = num.toString(10), a = [ str.replace(/^0\\./, \".\") ], m;\n if (Math.floor(num) === num) {\n if (num >= 0) {\n a.push(\"0x\" + num.toString(16).toLowerCase(), // probably pointless\n \"0\" + num.toString(8)); // same.\n } else {\n a.push(\"-0x\" + (-num).toString(16).toLowerCase(), // probably pointless\n \"-0\" + (-num).toString(8)); // same.\n }\n if ((m = /^(.*?)(0+)$/.exec(num))) {\n a.push(m[1] + \"e\" + m[2].length);\n }\n } else if ((m = /^0?\\.(0+)(.*)$/.exec(num))) {\n a.push(m[2] + \"e-\" + (m[1].length + m[2].length),\n str.substr(str.indexOf(\".\")));\n }\n return best_of(a);\n };\n\n var w = ast_walker();\n var make = w.walk;\n return w.with_walkers({\n \"string\": encode_string,\n \"num\": make_num,\n \"name\": make_name,\n \"toplevel\": function(statements) {\n return make_block_statements(statements)\n .join(newline + newline);\n },\n \"splice\": function(statements) {\n var parent = w.parent();\n if (HOP(SPLICE_NEEDS_BRACKETS, parent)) {\n // we need block brackets in this case\n return make_block.apply(this, arguments);\n } else {\n return MAP(make_block_statements(statements, true),\n function(line, i) {\n // the first line is already indented\n return i > 0 ? indent(line) : line;\n }).join(newline);\n }\n },\n \"block\": make_block,\n \"var\": function(defs) {\n return \"var \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n },\n \"const\": function(defs) {\n return \"const \" + add_commas(MAP(defs, make_1vardef)) + \";\";\n },\n \"try\": function(tr, ca, fi) {\n var out = [ \"try\", make_block(tr) ];\n if (ca) out.push(\"catch\", \"(\" + ca[0] + \")\", make_block(ca[1]));\n if (fi) out.push(\"finally\", make_block(fi));\n return add_spaces(out);\n },\n \"throw\": function(expr) {\n return add_spaces([ \"throw\", make(expr) ]) + \";\";\n },\n \"new\": function(ctor, args) {\n args = args.length > 0 ? \"(\" + add_commas(MAP(args, make)) + \")\" : \"\";\n return add_spaces([ \"new\", parenthesize(ctor, \"seq\", \"binary\", \"conditional\", \"assign\", function(expr){\n var w = ast_walker(), has_call = {};\n try {\n w.with_walkers({\n \"call\": function() { throw has_call },\n \"function\": function() { return this }\n }, function(){\n w.walk(expr);\n });\n } catch(ex) {\n if (ex === has_call)\n return true;\n throw ex;\n }\n }) + args ]);\n },\n \"switch\": function(expr, body) {\n return add_spaces([ \"switch\", \"(\" + make(expr) + \")\", make_switch_block(body) ]);\n },\n \"break\": function(label) {\n var out = \"break\";\n if (label != null)\n out += \" \" + make_name(label);\n return out + \";\";\n },\n \"continue\": function(label) {\n var out = \"continue\";\n if (label != null)\n out += \" \" + make_name(label);\n return out + \";\";\n },\n \"conditional\": function(co, th, el) {\n return add_spaces([ parenthesize(co, \"assign\", \"seq\", \"conditional\"), \"?\",\n parenthesize(th, \"seq\"), \":\",\n parenthesize(el, \"seq\") ]);\n },\n \"assign\": function(op, lvalue, rvalue) {\n if (op && op !== true) op += \"=\";\n else op = \"=\";\n return add_spaces([ make(lvalue), op, parenthesize(rvalue, \"seq\") ]);\n },\n \"dot\": function(expr) {\n var out = make(expr), i = 1;\n if (expr[0] == \"num\") {\n if (!/\\./.test(expr[1]))\n out += \".\";\n } else if (needs_parens(expr))\n out = \"(\" + out + \")\";\n while (i < arguments.length)\n out += \".\" + make_name(arguments[i++]);\n return out;\n },\n \"call\": function(func, args) {\n var f = make(func);\n if (needs_parens(func))\n f = \"(\" + f + \")\";\n return f + \"(\" + add_commas(MAP(args, function(expr){\n return parenthesize(expr, \"seq\");\n })) + \")\";\n },\n \"function\": make_function,\n \"defun\": make_function,\n \"if\": function(co, th, el) {\n var out = [ \"if\", \"(\" + make(co) + \")\", el ? make_then(th) : make(th) ];\n if (el) {\n out.push(\"else\", make(el));\n }\n return add_spaces(out);\n },\n \"for\": function(init, cond, step, block) {\n var out = [ \"for\" ];\n init = (init != null ? make(init) : \"\").replace(/;*\\s*$/, \";\" + space);\n cond = (cond != null ? make(cond) : \"\").replace(/;*\\s*$/, \";\" + space);\n step = (step != null ? make(step) : \"\").replace(/;*\\s*$/, \"\");\n var args = init + cond + step;\n if (args == \"; ; \") args = \";;\";\n out.push(\"(\" + args + \")\", make(block));\n return add_spaces(out);\n },\n \"for-in\": function(vvar, key, hash, block) {\n return add_spaces([ \"for\", \"(\" +\n (vvar ? make(vvar).replace(/;+$/, \"\") : make(key)),\n \"in\",\n make(hash) + \")\", make(block) ]);\n },\n \"while\": function(condition, block) {\n return add_spaces([ \"while\", \"(\" + make(condition) + \")\", make(block) ]);\n },\n \"do\": function(condition, block) {\n return add_spaces([ \"do\", make(block), \"while\", \"(\" + make(condition) + \")\" ]) + \";\";\n },\n \"return\": function(expr) {\n var out = [ \"return\" ];\n if (expr != null) out.push(make(expr));\n return add_spaces(out) + \";\";\n },\n \"binary\": function(operator, lvalue, rvalue) {\n var left = make(lvalue), right = make(rvalue);\n // XXX: I'm pretty sure other cases will bite here.\n // we need to be smarter.\n // adding parens all the time is the safest bet.\n if (member(lvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n lvalue[0] == \"binary\" && PRECEDENCE[operator] > PRECEDENCE[lvalue[1]] ||\n lvalue[0] == \"function\" && needs_parens(this)) {\n left = \"(\" + left + \")\";\n }\n if (member(rvalue[0], [ \"assign\", \"conditional\", \"seq\" ]) ||\n rvalue[0] == \"binary\" && PRECEDENCE[operator] >= PRECEDENCE[rvalue[1]] &&\n !(rvalue[1] == operator && member(operator, [ \"&&\", \"||\", \"*\" ]))) {\n right = \"(\" + right + \")\";\n }\n else if (!beautify && options.inline_script && (operator == \"<\" || operator == \"<<\")\n && rvalue[0] == \"regexp\" && /^script/i.test(rvalue[1])) {\n right = \" \" + right;\n }\n return add_spaces([ left, operator, right ]);\n },\n \"unary-prefix\": function(operator, expr) {\n var val = make(expr);\n if (!(expr[0] == \"num\" || (expr[0] == \"unary-prefix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n val = \"(\" + val + \")\";\n return operator + (jsp.is_alphanumeric_char(operator.charAt(0)) ? \" \" : \"\") + val;\n },\n \"unary-postfix\": function(operator, expr) {\n var val = make(expr);\n if (!(expr[0] == \"num\" || (expr[0] == \"unary-postfix\" && !HOP(OPERATORS, operator + expr[1])) || !needs_parens(expr)))\n val = \"(\" + val + \")\";\n return val + operator;\n },\n \"sub\": function(expr, subscript) {\n var hash = make(expr);\n if (needs_parens(expr))\n hash = \"(\" + hash + \")\";\n return hash + \"[\" + make(subscript) + \"]\";\n },\n \"object\": function(props) {\n if (props.length == 0)\n return \"{}\";\n return \"{\" + newline + with_indent(function(){\n return MAP(props, function(p){\n if (p.length == 3) {\n // getter/setter. The name is in p[0], the arg.list in p[1][2], the\n // body in p[1][3] and type (\"get\" / \"set\") in p[2].\n return indent(make_function(p[0], p[1][2], p[1][3], p[2]));\n }\n var key = p[0], val = parenthesize(p[1], \"seq\");\n if (options.quote_keys) {\n key = encode_string(key);\n } else if ((typeof key == \"number\" || !beautify && +key + \"\" == key)\n && parseFloat(key) >= 0) {\n key = make_num(+key);\n } else if (!is_identifier(key)) {\n key = encode_string(key);\n }\n return indent(add_spaces(beautify && options.space_colon\n ? [ key, \":\", val ]\n : [ key + \":\", val ]));\n }).join(\",\" + newline);\n }) + newline + indent(\"}\");\n },\n \"regexp\": function(rx, mods) {\n return \"/\" + rx + \"/\" + mods;\n },\n \"array\": function(elements) {\n if (elements.length == 0) return \"[]\";\n return add_spaces([ \"[\", add_commas(MAP(elements, function(el, i){\n if (!beautify && el[0] == \"atom\" && el[1] == \"undefined\") return i === elements.length - 1 ? \",\" : \"\";\n return parenthesize(el, \"seq\");\n })), \"]\" ]);\n },\n \"stat\": function(stmt) {\n return make(stmt).replace(/;*\\s*$/, \";\");\n },\n \"seq\": function() {\n return add_commas(MAP(slice(arguments), make));\n },\n \"label\": function(name, block) {\n return add_spaces([ make_name(name), \":\", make(block) ]);\n },\n \"with\": function(expr, block) {\n return add_spaces([ \"with\", \"(\" + make(expr) + \")\", make(block) ]);\n },\n \"atom\": function(name) {\n return make_name(name);\n }\n }, function(){ return make(ast) });\n\n // The squeezer replaces \"block\"-s that contain only a single\n // statement with the statement itself; technically, the AST\n // is correct, but this can create problems when we output an\n // IF having an ELSE clause where the THEN clause ends in an\n // IF *without* an ELSE block (then the outer ELSE would refer\n // to the inner IF). This function checks for this case and\n // adds the block brackets if needed.\n function make_then(th) {\n if (th[0] == \"do\") {\n // https://github.com/mishoo/UglifyJS/issues/#issue/57\n // IE croaks with \"syntax error\" on code like this:\n // if (foo) do ... while(cond); else ...\n // we need block brackets around do/while\n return make_block([ th ]);\n }\n var b = th;\n while (true) {\n var type = b[0];\n if (type == \"if\") {\n if (!b[3])\n // no else, we must add the block\n return make([ \"block\", [ th ]]);\n b = b[3];\n }\n else if (type == \"while\" || type == \"do\") b = b[2];\n else if (type == \"for\" || type == \"for-in\") b = b[4];\n else break;\n }\n return make(th);\n };\n\n function make_function(name, args, body, keyword) {\n var out = keyword || \"function\";\n if (name) {\n out += \" \" + make_name(name);\n }\n out += \"(\" + add_commas(MAP(args, make_name)) + \")\";\n return add_spaces([ out, make_block(body) ]);\n };\n\n function must_has_semicolon(node) {\n switch (node[0]) {\n case \"with\":\n case \"while\":\n return empty(node[2]); // `with' or `while' with empty body?\n case \"for\":\n case \"for-in\":\n return empty(node[4]); // `for' with empty body?\n case \"if\":\n if (empty(node[2]) && !node[3]) return true; // `if' with empty `then' and no `else'\n if (node[3]) {\n if (empty(node[3])) return true; // `else' present but empty\n return must_has_semicolon(node[3]); // dive into the `else' branch\n }\n return must_has_semicolon(node[2]); // dive into the `then' branch\n }\n };\n\n function make_block_statements(statements, noindent) {\n for (var a = [], last = statements.length - 1, i = 0; i <= last; ++i) {\n var stat = statements[i];\n var code = make(stat);\n if (code != \";\") {\n if (!beautify && i == last && !must_has_semicolon(stat)) {\n code = code.replace(/;+\\s*$/, \"\");\n }\n a.push(code);\n }\n }\n return noindent ? a : MAP(a, indent);\n };\n\n function make_switch_block(body) {\n var n = body.length;\n if (n == 0) return \"{}\";\n return \"{\" + newline + MAP(body, function(branch, i){\n var has_body = branch[1].length > 0, code = with_indent(function(){\n return indent(branch[0]\n ? add_spaces([ \"case\", make(branch[0]) + \":\" ])\n : \"default:\");\n }, 0.5) + (has_body ? newline + with_indent(function(){\n return make_block_statements(branch[1]).join(newline);\n }) : \"\");\n if (!beautify && has_body && i < n - 1)\n code += \";\";\n return code;\n }).join(newline) + newline + indent(\"}\");\n };\n\n function make_block(statements) {\n if (!statements) return \";\";\n if (statements.length == 0) return \"{}\";\n return \"{\" + newline + with_indent(function(){\n return make_block_statements(statements).join(newline);\n }) + newline + indent(\"}\");\n };\n\n function make_1vardef(def) {\n var name = def[0], val = def[1];\n if (val != null)\n name = add_spaces([ make_name(name), \"=\", parenthesize(val, \"seq\") ]);\n return name;\n };\n\n};\n\nfunction split_lines(code, max_line_length) {\n var splits = [ 0 ];\n jsp.parse(function(){\n var next_token = jsp.tokenizer(code);\n var last_split = 0;\n var prev_token;\n function current_length(tok) {\n return tok.pos - last_split;\n };\n function split_here(tok) {\n last_split = tok.pos;\n splits.push(last_split);\n };\n function custom(){\n var tok = next_token.apply(this, arguments);\n out: {\n if (prev_token) {\n if (prev_token.type == \"keyword\") break out;\n }\n if (current_length(tok) > max_line_length) {\n switch (tok.type) {\n case \"keyword\":\n case \"atom\":\n case \"name\":\n case \"punc\":\n split_here(tok);\n break out;\n }\n }\n }\n prev_token = tok;\n return tok;\n };\n custom.context = function() {\n return next_token.context.apply(this, arguments);\n };\n return custom;\n }());\n return splits.map(function(pos, i){\n return code.substring(pos, splits[i + 1] || code.length);\n }).join(\"\\n\");\n};\n\n/* -----[ Utilities ]----- */\n\nfunction repeat_string(str, i) {\n if (i <= 0) return \"\";\n if (i == 1) return str;\n var d = repeat_string(str, i >> 1);\n d += d;\n if (i & 1) d += str;\n return d;\n};\n\nfunction defaults(args, defs) {\n var ret = {};\n if (args === true)\n args = {};\n for (var i in defs) if (HOP(defs, i)) {\n ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];\n }\n return ret;\n};\n\nfunction is_identifier(name) {\n return /^[a-z_$][a-z0-9_$]*$/i.test(name)\n && name != \"this\"\n && !HOP(jsp.KEYWORDS_ATOM, name)\n && !HOP(jsp.RESERVED_WORDS, name)\n && !HOP(jsp.KEYWORDS, name);\n};\n\nfunction HOP(obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n};\n\n// some utilities\n\nvar MAP;\n\n(function(){\n MAP = function(a, f, o) {\n var ret = [], top = [], i;\n function doit() {\n var val = f.call(o, a[i], i);\n if (val instanceof AtTop) {\n val = val.v;\n if (val instanceof Splice) {\n top.push.apply(top, val.v);\n } else {\n top.push(val);\n }\n }\n else if (val != skip) {\n if (val instanceof Splice) {\n ret.push.apply(ret, val.v);\n } else {\n ret.push(val);\n }\n }\n };\n if (a instanceof Array) for (i = 0; i < a.length; ++i) doit();\n else for (i in a) if (HOP(a, i)) doit();\n return top.concat(ret);\n };\n MAP.at_top = function(val) { return new AtTop(val) };\n MAP.splice = function(val) { return new Splice(val) };\n var skip = MAP.skip = {};\n function AtTop(val) { this.v = val };\n function Splice(val) { this.v = val };\n})();\n\n/* -----[ Exports ]----- */\n\nexports.ast_walker = ast_walker;\nexports.ast_mangle = ast_mangle;\nexports.ast_squeeze = ast_squeeze;\nexports.ast_lift_variables = ast_lift_variables;\nexports.gen_code = gen_code;\nexports.ast_add_scope = ast_add_scope;\nexports.set_logger = function(logger) { warn = logger };\nexports.make_string = make_string;\nexports.split_lines = split_lines;\nexports.MAP = MAP;\n\n// keep this last!\nexports.ast_squeeze_more = require(\"./squeeze-more\").ast_squeeze_more;\n\n});");spade.register("uglify-js/squeeze-more", "(function(require, exports, __module, ARGV, ENV, __filename){var jsp = require(\"./parse-js\"),\n pro = require(\"./process\"),\n slice = jsp.slice,\n member = jsp.member,\n curry = jsp.curry,\n MAP = pro.MAP,\n PRECEDENCE = jsp.PRECEDENCE,\n OPERATORS = jsp.OPERATORS;\n\nfunction ast_squeeze_more(ast) {\n var w = pro.ast_walker(), walk = w.walk, scope;\n function with_scope(s, cont) {\n var save = scope, ret;\n scope = s;\n ret = cont();\n scope = save;\n return ret;\n };\n function _lambda(name, args, body) {\n return [ this[0], name, args, with_scope(body.scope, curry(MAP, body, walk)) ];\n };\n return w.with_walkers({\n \"toplevel\": function(body) {\n return [ this[0], with_scope(this.scope, curry(MAP, body, walk)) ];\n },\n \"function\": _lambda,\n \"defun\": _lambda,\n \"new\": function(ctor, args) {\n if (ctor[0] == \"name\" && ctor[1] == \"Array\" && !scope.has(\"Array\")) {\n if (args.length != 1) {\n return [ \"array\", args ];\n } else {\n return walk([ \"call\", [ \"name\", \"Array\" ], args ]);\n }\n }\n },\n \"call\": function(expr, args) {\n if (expr[0] == \"dot\" && expr[2] == \"toString\" && args.length == 0) {\n // foo.toString() ==> foo+\"\"\n return [ \"binary\", \"+\", expr[1], [ \"string\", \"\" ]];\n }\n if (expr[0] == \"name\" && expr[1] == \"Array\" && args.length != 1 && !scope.has(\"Array\")) {\n return [ \"array\", args ];\n }\n }\n }, function() {\n return walk(pro.ast_add_scope(ast));\n });\n};\n\nexports.ast_squeeze_more = ast_squeeze_more;\n\n});");// BPM PLUGIN: uglify-js/plugins/minifier
(function(exports) {
/*globals exports spade */
exports.minify = function(orig_code, pkg) {
var jsp = spade.require("uglify-js/parse-js");
var pro = spade.require("uglify-js/process");
var ast = jsp.parse(orig_code); // parse code and get the initial AST
ast = pro.ast_mangle(ast); // get a new AST with mangled names
ast = pro.ast_squeeze(ast); // get an AST with compression optimizations
return pro.gen_code(ast); // compressed code here
};
})(BPM_PLUGIN);
; // Safety
CTX = {"package":{"name":"uglify-js","author":"Mihai Bazon","summary":"AST-powered minifier for JavaScript","description":"Minify JavaScript applications. Includes plugin support for bpm.","version":"1.0.7","repository":{"type":"git","url":"git@github.com:mishoo/UglifyJS.git"},"homepage":"http://github.com/getbpm/UglifyJS","bpm:provides":{"minifier":"uglify-js/plugins/minifier"},"directories":{"lib":"lib","plugins":"plugins"},"dependencies":{"spade":"~> 1.0.0"}},"moduleId":null,"settings":{"files":[],"minifier":"uglify-js"}};
CTX.minify = function(body){ return body; };
DATA = "\n";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment