thread.js
/*! thread.js - v0.1.16 - MIT License - https://github.com/h2non/thread.js */
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.thread=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var _ = require('./utils')
var workerSrc = require('./worker')
var eventMethod = window.addEventListener ? 'addEventListener' : 'attachEvent'
var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message'
var addEventListener = window[eventMethod]
var removeEventListener = window[window.removeEventListener ? 'removeEventListener' : 'detachEvent']
module.exports = FakeWorker
function FakeWorker(id) {
this.id = id
this._terminated = false
this.listeners = {}
this._create()
this._setupListeners()
this._initialize()
}
FakeWorker.prototype._create = function () {
var iframe = this.iframe = document.createElement('iframe')
if (!iframe.style) iframe.style = {}
iframe.style.display = 'none'
iframe.id = 'thread-' + this.id
document.body.appendChild(iframe)
}
FakeWorker.prototype._subscribeListeners = function (type) {
var listeners = this.listeners
if (eventMethod === 'attachEvent') type = 'on' + type
function eventHandler(e) {
if (e.data && e.data.owner === 'thread.js') {
if (listeners[type]) {
_.each(listeners[type], function (fn) {
if (_.isFn(fn)) fn(e)
})
}
}
}
this._eventHandler = eventHandler
addEventListener(type, eventHandler)
}
FakeWorker.prototype._setupListeners = function () {
this._subscribeListeners('message')
this._subscribeListeners('error')
}
FakeWorker.prototype._unsubscribeListeners = function () {
removeEventListener('error', this._eventHandler)
removeEventListener('message', this._eventHandler)
}
FakeWorker.prototype._getWindow = function () {
var win = null
if (!this._terminated) {
win = this.iframe.contentWindow
var wEval = win.eval
if (!wEval && win.execScript) {
// win.eval() magically appears when this is called in IE
win.execScript('null')
wEval = win.eval
}
}
return win
}
FakeWorker.prototype._initialize = function (msg) {
var win = this._getWindow()
if (win) win.eval.call(win, _.getSource(workerSrc))
}
FakeWorker.prototype.addEventListener = function (type, fn) {
var pool = this.listeners[type] = this.listeners[type] || []
if (_.isFn(fn)) pool.push(fn)
}
FakeWorker.prototype.removeEventListener = function (type, fn) {
var index, pool = this.listeners[type]
if (pool) {
if (_.isFn(fn)) {
pool.splice(0, pool.length)
} else {
index = pool.indexOf(fn)
if (index >= 0) pool.splice(index, 1)
}
}
}
FakeWorker.prototype.postMessage = function (msg) {
var win = this._getWindow()
if (win) {
msg.origin = _.getLocation()
win.postMessage(msg, msg.origin)
}
}
FakeWorker.prototype.terminate = function () {
this.listeners = {}
this._terminated = true
this._unsubscribeListeners()
document.body.removeChild(this.iframe)
}
},{"./utils":7,"./worker":8}],2:[function(require,module,exports){
var store = require('./store')
var Thread = require('./thread')
module.exports = ThreadFactory
window.thread = window.thread || ThreadFactory
function ThreadFactory(options) {
return new Thread(options)
}
ThreadFactory.VERSION = '0.1.16'
ThreadFactory.create = ThreadFactory
ThreadFactory.Task = Thread.Task
ThreadFactory.Thread = Thread
ThreadFactory.total = store.all
ThreadFactory.total = store.total
ThreadFactory.running = store.running
ThreadFactory.idle = store.idle
ThreadFactory.flush = store.flush
ThreadFactory.killAll = ThreadFactory.terminateAll = store.killAll
ThreadFactory.killIdle = ThreadFactory.terminateIdle = store.killIdle
},{"./store":4,"./thread":6}],3:[function(require,module,exports){
var _ = require('./utils')
module.exports = threadPool
function threadPool(poolSize, thread) {
var threads = [ thread ]
thread._run = thread.run
thread._terminate = thread.terminate
// decorate the thread public interface
thread.run = thread.exec = function () {
return selectThread(thread, threads, poolSize, arguments)(0)
}
thread.terminate = thread.kill = function () {
_.each(threads, function (thread) {
if (thread._terminate) {
thread._terminate()
} else {
thread.terminate()
}
})
threads.splice(0)
}
thread.threadPool = threads
thread.isPool = true
return thread
}
function createThread(threads) {
var mainThread = threads[0]
var thread = new mainThread.constructor(mainThread.options)
threads.push(thread)
return thread
}
function runTaskInThread(thread, threads, args) {
var run = thread === threads[0] ? '_run' : 'run'
return thread[run].apply(thread, args)
}
function selectThread(thread, threads, poolSize, args) {
return function newRound(busyThreads) {
var task, thread = findBestAvailableThread(threads, busyThreads)
if (thread) {
task = runTaskInThread(thread, threads, args)
} else {
if (threads.length < poolSize) {
task = runTaskInThread(createThread(threads), threads, args)
} else {
task = newRound(busyThreads + 1)
}
}
return task
}
}
function findBestAvailableThread(threads, offset) {
var thread, pending
for (var i = 0, l = threads.length; i < l; i += 1) {
thread = threads[i]
pending = thread.pending()
if (pending === 0 || pending < offset) {
if (thread.terminated) {
threads.splice(i, 1)
l -= 1; i -= 1
} else {
return thread
}
}
}
}
},{"./utils":7}],4:[function(require,module,exports){
var _ = require('./utils')
var buf = []
var store = module.exports = {}
store.push = function (thread) {
buf.push(thread)
}
store.all = function () {
return buf.slice()
}
store.remove = function (thread) {
var index = buf.indexOf(thread)
if (index >= 0) buf.splice(index, 1)
}
store.flush = function () {
buf.splice(0)
}
store.total = function () {
return buf.length
}
function getByStatus(type) {
var typeBuf = []
_.each(buf, function (thread) {
if (thread[type]()) typeBuf.push(thread)
})
return typeBuf
}
store.running = function () {
return getByStatus('running')
}
store.idle = function () {
return getByStatus('idle')
}
store.killAll = function () {
var arr = buf.slice()
_.each(arr, function (thread) {
thread.kill()
})
}
store.killIdle = function () {
_.each(store.idle(), function (thread) {
thread.kill()
})
}
},{"./utils":7}],5:[function(require,module,exports){
var _ = require('./utils')
module.exports = Task
function Task(thread, env) {
this.id = _.uuid()
this.thread = thread
this.worker = thread.worker
this.env = env || {}
this.time = this.memoized = null
this.listeners = { error: [], success: [], end: [] }
}
Task.intervalCheckTime = 200
Task.prototype.bind = Task.prototype.set = function (env) {
_.extend(this.env, env)
return this
}
Task.prototype.run = Task.prototype.exec = function (fn, env, args) {
var thread = this.thread
if (!thread || thread._terminated) {
throw new Error('cannot execute the task. The thread was terminated')
}
if (!_.isFn(fn)) {
throw new TypeError('first argument must be a function')
}
if (_.isArr(arguments[1])) args = arguments[1]
if (_.isObj(arguments[2])) env = arguments[2]
env = _.serializeMap(_.extend({}, this.env, env))
this.memoized = null
this.time = _.now()
if (thread.maxTaskDelay >= Task.intervalCheckTime) {
checkInterval(this, thread.maxTaskDelay)
}
if (thread._tasks.indexOf(this) === -1) {
thread._tasks.push(this)
}
this['finally'](cleanTask(thread, this))
addWorkerMessageListener(this)
sendMessage(this, env, fn, args)
return this
}
Task.prototype.then = Task.prototype.success = function (fn, errorFn) {
if (_.isFn(fn)) pushStateHandler(this, 'success', fn)
if (_.isFn(errorFn)) this['catch'](errorFn)
return this
}
Task.prototype['catch'] = Task.prototype.error = function (fn) {
if (_.isFn(fn)) pushStateHandler(this, 'error', fn)
return this
}
Task.prototype['finally'] = Task.prototype.finish = function (fn) {
if (_.isFn(fn)) {
if (this.memoized)
fn.call(null, getValue(this.memoized))
else
this.listeners.end.push(fn)
}
return this
}
Task.prototype.flush = function () {
this.memoized = this.thread = null
this.worker = this.env = this.listeners = null
}
Task.prototype.flushed = function () {
return !this.thread && !this.worker
}
Task.create = function (thread) {
return new Task(thread)
}
function sendMessage(task, env, fn, args) {
task.worker.postMessage({
id: task.id,
type: 'run',
env: env,
src: fn.toString(),
args: args
})
}
function checkInterval(task, maxDelay) {
var now = _.now()
task._timer = setInterval(function () {
if (task.memoized) {
clearTimer.call(task)
} else {
checkTaskDelay.call(task, now, maxDelay)
}
}, Task.intervalCheckTime)
}
function addWorkerMessageListener(task) {
task.worker.addEventListener('message', onMessage(task))
}
function pushStateHandler(task, type, fn) {
if (task.memoized) {
if (task.memoized.type === ('run:' + type))
fn.call(null, getValue(task.memoized))
} else {
task.listeners[type].push(fn)
}
}
function dispathEvent(task, value, type) {
if (typeof task._timer === 'number') clearTimer.call(task)
dispatcher(task, value)(task.listeners[type])
}
function dispatcher(self, value) {
return function recur(pool) {
var fn = null
if (_.isArr(pool)) {
fn = pool.shift()
if (fn) {
fn.call(null, value)
if (pool.length) recur(pool)
}
}
}
}
function createError(data) {
var err = new Error(data.error)
err.name = data.errorName
err.stack = data.errorStack
return err
}
function cleanTask(thread, task) {
return function () {
var index = thread._tasks.indexOf(task)
thread._latestTask = _.now()
if (index >= 0) thread._tasks.splice(index, 1)
}
}
function checkTaskDelay(time, maxDelay) {
var error = null
if ((_.now() - time) > maxDelay) {
error = new Error('maximum task execution time exceeded')
this.memoized = { type: 'run:error', error: error }
dispathEvent(this, error, 'error')
dispathEvent(this, error, 'end')
clearTimer.call(this)
}
}
function clearTimer() {
clearInterval(this._timer)
this._timer = null
}
function isValidEvent(type) {
return type === 'run:error' || type === 'run:success'
}
function onMessage(task) {
return function handler(ev) {
var data = ev.data
if (data && data.id === task.id && isValidEvent(data.type)) {
task.worker.removeEventListener('message', handler)
task.memoized = data
triggerMessage(task, data)
}
}
}
function triggerMessage(task, data) {
var value = getValue(data)
dispathEvent(task, value, data.type.split(':')[1])
dispathEvent(task, value, 'end')
}
function getValue(data) {
return data.type === 'run:error'
? createError(data)
: data.value
}
},{"./utils":7}],6:[function(require,module,exports){
var _ = require('./utils')
var workerSrc = require('./worker')
var Task = require('./task')
var FakeWorker = require('./fake-worker')
var pool = require('./pool')
var store = require('./store')
var Worker = window.Worker
var URL = window.URL || window.webkitURL
var hasWorkers = _.isFn(Worker) || (Worker && typeof Worker === 'object') || false
var isIE = (/MSIE (10|11)/).test(window.navigator.userAgent)
var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder
module.exports = Thread
function Thread(options) {
this.id = _.uuid()
this.terminated = false
this.options = {}
this._tasks = []
this._latestTask = 0
setOptions(this, options)
createThread(this)
}
Thread.prototype.isPool = false
Thread.prototype.maxTaskDelay = 0
Thread.prototype.idleTime = 30 * 1000
Thread.prototype.defaults = {
// customizable Worker external source to prevent security error in IE 10 & 11 :S
evalPath: 'lib/eval.js',
// enable/disable error exception throwing
silent: false
}
Thread.prototype.constructor = Thread
Thread.prototype.run = Thread.prototype.exec = function (fn, env, args) {
var task
if (_.isArr(env)) {
args = env
env = arguments[2]
}
if (fn && fn instanceof Task) {
task = fn
} else {
if (!_.isFn(fn)) throw new TypeError('first argument must be a function')
task = new Task(this)
}
this._tasks.push(task)
_.defer(function () { task.run(fn, env, args) })
return task
}
Thread.prototype.require = Thread.prototype['import'] = function (name, fn) {
if (_.isFn(name)) {
fn = name
name = _.fnName(fn)
if (!name) throw new Error('function must be named')
this.send({ type: 'require:fn', src: fn.toString(), name: _.fnName(fn) })
} else if (typeof name === 'string') {
if (_.isFn(fn)) {
this.send({ type: 'require:fn', src: fn.toString(), name: name })
} else {
if (_.isArr(this.options.require)) this.options.require.push(name)
this.send({ type: 'require:file', src: name })
}
} else if (_.isArr(name)) {
if (_.isArr(this.options.require)) this.options.require = this.options.require.concat(name)
this.send({ type: 'require:file', src: name })
} else if (_.isObj(name)) {
this.send({ type: 'require:map', src: _.serializeMap(name) })
}
return this
}
Thread.prototype.bind = Thread.prototype.set = function (env) {
this.send({ type: 'env', data: _.serializeMap(env) })
return this
}
Thread.prototype.flush = function () {
this.send({ type: 'flush' })
this.options.env = {}
return this
}
Thread.prototype.flushTasks = function () {
_.each(this.tasks, function (task) {
task.flush()
})
this._tasks.splice(0)
return this
}
Thread.prototype.send = function (msg) {
if (this.worker) {
this.worker.postMessage(msg)
}
}
Thread.prototype.pool = function (num) {
return pool(num || 2, this)
}
Thread.prototype.terminate = Thread.prototype.kill = function () {
if (!this.terminated) {
this.options = {}
this.flushTasks().flush()
this.terminated = true
this.worker.terminate()
store.remove(this)
}
return this
}
Thread.prototype.start = Thread.prototype.init = function (options) {
if (this.terminated) {
this._setOptions(options)
this._create()
this.terminated = false
}
return this
}
Thread.prototype.pending = function () {
return this._tasks.length
}
Thread.prototype.running = function () {
return this._tasks.length > 0
}
Thread.prototype.idle = Thread.prototype.sleep = function () {
return !this.running() && !this.terminated
&& (this._latestTask === 0
|| (_.now() - this._latestTask) > this.idleTime)
}
Thread.prototype.on = Thread.prototype.addEventListener = function (type, fn) {
if (this.worker) this.worker.addEventListener(type, fn)
return this
}
Thread.prototype.off = Thread.prototype.removeEventListener = function (type, fn) {
if (this.worker && _.isFn(fn)) {
this.worker.removeEventListener(type, fn)
}
return this
}
Thread.prototype.toString = function () {
return '[object Thread]'
}
Thread.Task = Task
function setOptions(thread, options) {
thread.options.namespace = 'env'
thread.options.require = []
thread.options.env = {}
_.extend(thread.options, thread.defaults, options)
}
function createThread(thread) {
var src = _.getSource(workerSrc)
if (hasWorkers && URL) {
if (isIE) {
thread.worker = new Worker(thread.options.evalPath)
thread.worker.postMessage(src)
} else {
thread.worker = new Worker(createBlob(src))
}
} else {
thread.worker = new FakeWorker(thread.id)
}
if (!thread.options.silent) {
thread.worker.addEventListener('error', function (e) { throw e })
}
thread.send({
type: 'start',
env: _.serializeMap(thread.options.env),
namespace: thread.options.namespace,
origin: _.getLocation()
})
thread.require(thread.options.require)
store.push(thread)
}
function createBlob(src) {
var blob = null
try {
blob = new Blob([src], { type: 'text/javascript' })
} catch (e) {
blob = new BlobBuilder()
blob.append(src)
blob = blob.getBlob()
}
return URL.createObjectURL(blob)
}
},{"./fake-worker":1,"./pool":3,"./store":4,"./task":5,"./utils":7,"./worker":8}],7:[function(require,module,exports){
var _ = exports
var toStr = Object.prototype.toString
var slice = Array.prototype.slice
var hasOwn = Object.prototype.hasOwnProperty
var isArrayNative = Array.isArray
exports.now = function () {
return new Date().getTime()
}
exports.isFn = function (obj) {
return typeof obj === 'function'
}
exports.isObj = function (o) {
return (o && toStr.call(o) === '[object Object]') || false
}
exports.isArr = function (o) {
return o && (isArrayNative ? isArrayNative(o) : toStr.call(o) === '[object Array]') || false
}
exports.toArr = function (args) {
return slice.call(args)
}
exports.defer = function (fn) {
setTimeout(fn, 1)
}
exports.each = function (obj, fn) {
var i, l
if (_.isArr(obj))
for (i = 0, l = obj.length; i < l; i += 1) fn(obj[i], i)
else if (_.isObj(obj))
for (i in obj) if (hasOwn.call(obj, i)) fn(obj[i], i)
}
exports.extend = function (target) {
var args = _.toArr(arguments).slice(1)
_.each(args, function (obj) {
if (_.isObj(obj)) {
_.each(obj, function (value, key) {
target[key] = value
})
}
})
return target
}
exports.getSource = function (fn) {
return '(' + fn.toString() + ').call(this)'
}
exports.fnName = function (fn) {
return fn.name || (fn = /\W*function\s+([\w\$]+)\(/.exec(fn.toString()) ? fn[1] : '')
}
exports.serializeMap = function (obj) {
if (_.isObj(obj)) {
_.each(obj, function (fn, key) {
if (_.isFn(fn)) {
obj['$$fn$$' + key] = fn.toString()
obj[key] = undefined
}
})
}
return obj
}
exports.uuid = function () {
var uuid = '', i, random
for (i = 0; i < 32; i++) {
random = Math.random() * 16 | 0;
if (i === 8 || i === 12 || i === 16 || i === 20) uuid += '-'
uuid += (i === 12 ? 4 : (i === 16 ? (random & 3 | 8) : random)).toString(16)
}
return uuid
}
exports.getLocation = function () {
return location.origin
|| location.protocol + "//" + location.hostname + (location.port ? ':' + location.port : '')
}
},{}],8:[function(require,module,exports){
module.exports = worker
function worker() {
var self = this
function $$evalExpr(expr) {
var fn = null
eval('fn = ' + expr)
return fn
}
(function isolated() {
'use strict'
var namespace = 'env'
var isWorker = typeof document === 'undefined'
var toStr = Object.prototype.toString
var slice = Array.prototype.slice
var eventMethod = self.addEventListener ? 'addEventListener' : 'attachEvent'
var messageEvent = eventMethod === 'attachEvent' ? 'onmessage' : 'message'
var importFn = isWorker ? importScripts : appendScripts
var ready = false
var fnRegex = /^\$\$fn\$\$/
var urlProtocolRegex = /^http[s]?/
var isArrayNative = Array.isArray
var queue, origin, scriptsLoad, intervalId = null
self.addEventListener = self[eventMethod]
if (typeof window === 'undefined') {
self.window = self
}
function isObj(o) {
return o && toStr.call(o) === '[object Object]'
}
function isArr(o) {
return o && (isArrayNative ? isArrayNative(o) : toStr.call(o) === '[object Array]') || false
}
function mapFields(obj) {
for (var key in obj) if (obj.hasOwnProperty(key)) {
if (fnRegex.test(key)) {
obj[key.replace('$$fn$$', '')] = $$evalExpr(obj[key])
obj[key] = undefined
} else {
obj[key] = obj[key]
}
}
return obj
}
function extend(origin, target) {
var i, l, key, args = slice.call(arguments).slice(1)
for (i = 0, l = args.length; i < l; i += 1) {
target = args[i]
if (isObj(target)) {
target = mapFields(target)
for (key in target) if (target[key] !== undefined) {
origin[key] = target[key]
}
}
}
return origin
}
function each(obj, fn) {
var i, l
if (isArr(obj)) {
if (obj.forEach) {
obj.forEach(fn)
} else {
for (i = 0, l = obj.length; i < l; i += 1) {
fn(obj[i], i)
}
}
} else if (isObj(obj)) {
for (i in obj) if (obj.hasOwnProperty(i)) {
fn(obj[i], i)
}
}
}
function waitToDocumentReady() {
if (document.readyState === 'complete') {
ready = true
} else {
document.onreadystatechange = function () {
if (document.readyState === 'complete') {
ready = true
}
}
}
}
function appendScript(src) {
var head = document.getElementsByTagName('head')[0]
var script = document.createElement('script')
script.type = 'text/javascript'
script.src = src
scriptsLoad.push(script)
script.onload = script.onreadystatechange = function () {
if (!this.readyState || this.readyState === 'loaded' || this.readyState === 'complete') {
scriptsLoad.splice(scriptsLoad.indexOf(script), 1)
}
script.onload = script.onreadystatechange = null
}
head.appendChild(script)
}
function appendScripts() {
var i, l, args = slice.call(arguments)
for (i = 0, l = args.length; i < l; i += 1) {
if (args[i]) appendScript(args[i])
}
}
function scriptsLoadTimer() {
intervalId = setInterval(function () {
if (ready && !scriptsLoad.length) {
clearInterval(intervalId)
each(queue, function (fn) { fn() })
queue = []
intervalId = null
}
}, 50)
}
function loadScripts(src) {
if (isArr(src)) {
importFn.apply(self, src.map(makePathFullUrl))
} else {
importFn(makePathFullUrl(src))
}
if (!isWorker && !intervalId) {
scriptsLoadTimer()
}
}
function makePathFullUrl(path) {
if (urlProtocolRegex.test(path) === false) {
path = origin + path
}
return path
}
function require(src) {
if (isArr(src) || typeof src === 'string') {
loadScripts(src)
} else if (isObj(src)) {
each(src, function (value, name) {
requireFn(name, value)
})
}
}
function requireFn(name, fn) {
if (fnRegex.test(name)) {
name = name.replace('$$fn$$', '')
fn = $$evalExpr(fn)
}
eval('self[namespace][name] = ' + fn)
}
function postMessage(msg) {
if (isWorker) {
self.postMessage(msg)
} else {
msg.owner = 'thread.js'
self.parent.postMessage(msg, origin)
}
}
function sendError(msg, err) {
postMessage({
type: 'run:error',
id: msg.id,
error: err.message || err,
errorName: err.name || null,
errorStack: err.stack || null
})
}
function sendSuccess(msg, val) {
postMessage({
type: 'run:success',
id: msg.id,
value: val
})
}
function done(msg) {
return function(err, value) {
if (err) {
sendError(msg, err)
} else {
sendSuccess(msg, value)
}
}
}
function process(msg) {
var result = null
var args = msg.args || []
var fn = $$evalExpr(msg.src)
var ctx = isObj(msg.env) ? mapFields(msg.env) : self[namespace]
if (fn.length === (args.length + 1)) {
args.push(done(msg))
fn.apply(ctx, args)
} else {
result = fn.apply(ctx, args)
if (result instanceof Error) {
sendError(msg, result)
} else {
sendSuccess(msg, result)
}
}
}
function run(msg) {
function doJob() {
try {
process(msg)
} catch (e) {
sendError(msg, e)
}
}
if (!isWorker && (!ready || scriptsLoad.length)) {
queue.push(doJob)
} else {
doJob()
}
}
function start(e) {
if (e.require) { require(e.require) }
if (e.origin) { origin = e.origin }
namespace = e.namespace || namespace
self[namespace] = mapFields(e.env || {})
}
function flush() {
self[namespace] = {}
}
function extendEnv(data) {
extend(self[namespace || namespace], data.env)
}
function onMessage(ev) {
var data = ev.data
if (data.origin) {
origin = data.origin
}
switch (data.type) {
case 'start': start(data); break
case 'run': run(data); break
case 'env': extendEnv(data); break
case 'require:fn': requireFn(data.name, data.src); break
case 'require:file':
case 'require:map': require(data.src); break
case 'flush': flush(); break
}
}
if (!isWorker) {
scriptsLoad = []
queue = []
waitToDocumentReady()
}
self.addEventListener(messageEvent, onMessage)
self.addEventListener('error', function (err) { throw err })
})()
}
},{}]},{},[2])(2)
});