Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

background-worker

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

background-worker - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

2

karma.conf.js

@@ -12,3 +12,3 @@ // Karma configuration

// frameworks to use
frameworks: [ 'mocha', 'expect', 'browserify', 'sinon' ],
frameworks: [ 'mocha', 'expect', 'browserify' ],

@@ -15,0 +15,0 @@ browserify: {

{
"name": "background-worker",
"version": "0.0.2",
"version": "0.0.3",
"description": "Execute tasks on Web Workers without seperate files.",

@@ -23,4 +23,3 @@ "main": "index.js",

"dependencies": {
"bluebird": "^2.3.11",
"underscore": "^1.7.0"
"bluebird": "^2.3.11"
},

@@ -27,0 +26,0 @@ "devDependencies": {

@@ -5,1 +5,5 @@ background-worker

Execute tasks on web Workers without seperate files.
*Partially made, with <3 at:*
[![Foo](http://wtw.no/gfx/wtw-logo2.png)](https://github.com/wtw-software/)

@@ -1,3 +0,4 @@

var _ = require( 'underscore' ),
Promise = require( 'bluebird' ),
"use strict";
var Promise = require( 'bluebird' ),
inherits = require( 'util' ) .inherits,

@@ -19,11 +20,15 @@ EventEmitter = require( 'events' ).EventEmitter

this.worker = null
this.iframe = null
this._isStarted = false
this.importScripts = spec.importScripts || []
this.messagehandlers = {}
this.definitions = []
this.messageId = 0
this.domain = location.protocol + "//" + location.host
this.definitions = spec.definitions || []
this.domain = spec.domain || (location.protocol + "//" + location.host)
this._spec = spec
this._worker = null
this._iframe = null
this._messageId = 0
this._messagehandlers = {}
this._state = BackgroundWorker.CREATED
if( typeof spec === 'function' )
this.define('default', spec )
}

@@ -43,62 +48,186 @@

/*
* Start the worker
* State Created
* @static
*/
BackgroundWorker.CREATED = {}
/*
* State Running
* @static
*/
BackgroundWorker.RUNNING = {}
/*
* State Idle
* @static
*/
BackgroundWorker.IDLE = {}
/*
* State Terminated
* @static
*/
BackgroundWorker.TERMINATED = {}
/*
* Define a command on the worker
* @public
* @function
*/
BackgroundWorker.prototype.start = function() {
if( this._isStarted )
BackgroundWorker.prototype.define = function( key, val ) {
this.definitions.push({ key: key, val: val })
}
/*
* Run a given function defined in the BackgroundWorker
* @public
* @function
* @param {string} command - command to run
* @param {array} args - arguemnts to apply to command
* @returns {Promise}
*/
BackgroundWorker.prototype.run = function( command, args ) {
var self, messageId, message, handler, task, worker
self = this
if( typeof command !== 'string' ) {
command = 'default'
args = Array.prototype.slice.call( self )
}
if( self._state === BackgroundWorker.TERMINATED ) {
throw new Error( 'Cannot call run on a Terminated BackgroundWorker' )
}
if( !self._isStarted ) {
start( self )
}
stateChange( self, BackgroundWorker.RUNNING )
messageId = getUniqueMessageId( self )
message = { command: command, args: args, messageId: messageId }
handler = {}
task = new Promise(function(resolve, reject) {
function setIdleThen(cb) {
return function(){
stateChange( self, BackgroundWorker.IDLE )
cb.apply( self, arguments )
}
}
handler.resolve = setIdleThen( resolve )
handler.reject = setIdleThen( reject )
})
self._messagehandlers[ messageId ] = handler
if( BackgroundWorker.hasWorkerSupport() ) {
self._worker.postMessage( JSON.stringify(message) )
}
else {
self._iframe.contentWindow.postMessage( JSON.stringify(message), self.domain )
}
return task
}
/*
* Terminate the worker
* @public
* @function
*/
BackgroundWorker.prototype.terminate = function() {
var self
self = this
if( BackgroundWorker.hasWorkerSupport() ) {
if( self._worker )
self._worker.terminate()
}
else if( self._iframe ){
self._iframe.remove()
}
stateChange( self, BackgroundWorker.TERMINATED )
}
/*
* Global reference
* @private
*/
var global = typeof global !== 'undefined' ? global : window
/*
* Start the worker
* @private
* @function
*/
function start( self ) {
if( self._isStarted ) {
throw new Error( 'cannot start allready started BackgroundWorker' )
}
this._isStarted = true
self._isStarted = true
if( BackgroundWorker.hasWorkerSupport() ) {
this.setupWebWorker()
setupWebWorker( self )
}
else {
this.setupIframe()
setupIframe( self )
}
return this
stateChange( self, BackgroundWorker.IDLE )
return self
}
/*
* Setup a Worker
* @public
* @function
* Setup a Worker
* @private
* @function
*/
BackgroundWorker.prototype.setupWebWorker = function() {
this.blob = new Blob([
this.getWorkerSourcecode()
function setupWebWorker( self ) {
self.blob = new Blob([
getWorkerSourcecode( self )
], { type: "text/javascript" })
this.worker = new Worker( window.URL.createObjectURL(this.blob) )
self._worker = new Worker( window.URL.createObjectURL(self.blob) )
this.worker.onmessage = _.bind( this.workerOnMessageHandler, this )
this.worker.onerror = _.bind( this.workerOnErrorHandler, this )
self._worker.onmessage = function( event ) {
return workerOnMessageHandler( self, event )
}
self._worker.onerror = function( event ) {
return workerOnErrorHandler( self, event )
}
}
/*
* Setup a Iframe
* @public
* @function
* Setup a Iframe
* @private
* @function
*/
BackgroundWorker.prototype.setupIframe = function() {
function setupIframe( self ) {
var script, src
this.iframe = document.createElement( 'iframe' )
self._iframe = document.createElement( 'iframe' )
script = document.createElement( 'script' )
if( !this.iframe.style ) this.iframe.style = {}
this.iframe.style.display = 'none';
if( !self._iframe.style ) self._iframe.style = {}
self._iframe.style.display = 'none';
src = ""
src += "var domain = '" + this.domain + "';\n"
src += "var importScripts = " + JSON.stringify(this.importScripts) + ";\n"
src += "var domain = '" + self.domain + "';\n"
src += "var importScripts = " + JSON.stringify(self.importScripts) + ";\n"
src += "var definitions = {};\n"
_.forEach(this.definitions, function( definition ) {
src += " definitions['" + definition.key + "'] = " + definition.val + ";\n"
})
for( var i = 0; i < self.definitions.length; i++ ) {
src += " definitions['" + self.definitions[i].key + "'] = " + self.definitions[i].val + ";\n"
}
src += ";(" + function(){

@@ -130,3 +259,3 @@

if( data.result )
return
return
try {

@@ -149,7 +278,7 @@ var result = definitions[data.command].apply(this, data.args);

window.document.body.appendChild( this.iframe )
window.document.body.appendChild( self._iframe )
this.iframe.contentWindow.addEventListener( 'message', _.bind( this.iframeOnMessageHandler, this ) )
self._iframe.contentWindow.addEventListener( 'message', function( event ){ return iframeOnMessageHandler( self, event ) } )
this.iframe.contentDocument.body.appendChild( script )
self._iframe.contentDocument.body.appendChild( script )

@@ -159,69 +288,28 @@ }

/*
* Terminate the worker
* @public
* @function
* Get a uniqie messageid to identify a worker message transaction
* @private
* @function
* @returns {int}
*/
BackgroundWorker.prototype.terminate = function() {
if( BackgroundWorker.hasWorkerSupport() ) {
if( !this.worker )
throw new Error('BackgroundWorker has no worker to terminate')
return this.worker.terminate()
}
else if( this.iframe ){
this.iframe.remove()
}
function getUniqueMessageId( self ) {
return self._messageId++
}
/*
* Get a uniqie messageid to identify a worker message transaction
* @public
* @function
* @returns {int}
* Change state of BackgroundWorker and trigger event if it differs from old
* @private
* @function
*/
BackgroundWorker.prototype.getUniqueMessageId = function() {
return this.messageId++
}
function stateChange( self, newstate ) {
var oldstate
/*
* Define a command on the worker
* @public
* @function
*/
BackgroundWorker.prototype.define = function( key, val ) {
this.definitions.push({ key: key, val: val })
}
oldstate = self._state
self._state = newstate
/*
* Run a given function defined in the BackgroundWorker
* @public
* @function
* @param {string} command - command to run
* @param {array} args - arguemnts to apply to command
* @param {function} calback
* @returns {AsyncInterface}
*/
BackgroundWorker.prototype.run = function( command, args, callback ) {
var messageId, message, handler, task, worker
messageId = this.getUniqueMessageId()
message = { command: command, args: args, messageId: messageId }
handler = {}
task = new Promise(function(resolve, reject) {
handler.resolve = resolve
handler.reject = reject
})
this.messagehandlers[ messageId ] = handler
if( BackgroundWorker.hasWorkerSupport() ) {
this.worker.postMessage( JSON.stringify(message) )
if( oldstate !== newstate ) {
self.emit( 'statechange:' + newstate )
return true
}
else {
this.iframe.contentWindow.postMessage( JSON.stringify(message), this.domain )
}
return task
return false
}

@@ -235,3 +323,3 @@

*/
BackgroundWorker.prototype.workerOnMessageHandler = function( event ) {
function workerOnMessageHandler( self, event ) {
var data, messagehandler

@@ -241,6 +329,6 @@

messagehandler = this.messagehandlers[ data.messageId ]
messagehandler = self._messagehandlers[ data.messageId ]
if( data.exception )
return messagehandler.reject( this.createExceptionFromMessage( data.exception ) )
return messagehandler.reject( createExceptionFromMessage( self, data.exception ) )

@@ -256,3 +344,3 @@ messagehandler.resolve( data.result )

*/
BackgroundWorker.prototype.iframeOnMessageHandler = function( event ) {
function iframeOnMessageHandler( self, event ) {
var data, messagehandler

@@ -264,6 +352,6 @@

messagehandler = this.messagehandlers[ data.messageId ]
messagehandler = self._messagehandlers[ data.messageId ]
if( data.exception )
return messagehandler.reject( this.createExceptionFromMessage( data.exception ) )
return messagehandler.reject( createExceptionFromMessage( self, data.exception ) )

@@ -277,3 +365,3 @@ messagehandler.resolve( data.result )

* Create a exception by an obect describing it
* @public
* @private
* @function

@@ -285,7 +373,7 @@ * @param {object} exception

*/
BackgroundWorker.prototype.createExceptionFromMessage = function( exception ) {
function createExceptionFromMessage( self, exception ) {
var type, message
try {
type = typeof eval( exception.type ) == 'function' ? eval( exception.type ) : Error
type = typeof global[exception.type] == 'function' ? global[exception.type] : Error
}

@@ -303,7 +391,7 @@ catch( exception ) {

* Handle worker error
* @public
* @private
* @function
* @event
*/
BackgroundWorker.prototype.workerOnErrorHandler = function( event ) {
function workerOnErrorHandler( self, event ) {
var message, error, errorType, errorMessage

@@ -317,4 +405,4 @@

try {
errorType = typeof eval(error[1]) == 'function' ? eval(error[1]) : Error
errorMessage = typeof eval(error[1]) == 'function' ? error[2] : message
errorType = typeof global[error[1]] == 'function' ? global[error[1]] : Error
errorMessage = typeof global[error[1]] == 'function' ? error[2] : message
}

@@ -328,3 +416,3 @@ catch( exception ) {

this.emit( 'exception', error )
self.emit( 'exception', error )
}

@@ -334,7 +422,7 @@

* Get the sourcecode for this worker
* @public
* @private
* @function
* @returns {string}
*/
BackgroundWorker.prototype.getWorkerSourcecode = function() {
function getWorkerSourcecode( self ) {
var src

@@ -344,10 +432,11 @@

if( this.importScripts.length )
src += "importScripts( '" + this.importScripts.join("','") + "' );\n"
if( self.importScripts.length ) {
src += "importScripts( '" + self.importScripts.join("','") + "' );\n"
}
src += " var definitions = {};"
_.forEach(this.definitions, function( definition ) {
src += " definitions['" + definition.key + "'] = " + definition.val + ";"
})
for( var i = 0; i < self.definitions.length; i++ ) {
src += " definitions['" + self.definitions[i].key + "'] = " + self.definitions[i].val + ";\n"
}

@@ -354,0 +443,0 @@ src += "self.onmessage = function( event ) { " +

@@ -6,18 +6,9 @@ var BackgroundWorker = require( '../../' )

describe( 'BackgroundWorker#start', function() {
describe( 'WebWorker', function() {
it( 'should throw exepction if tried to start when allready started', function() {
var worker
TestSharedAPI()
worker = new BackgroundWorker()
worker.start()
expect(function(){ worker.start() })
.to.throwException()
})
})
describe( 'Running in Iframe', function( done ) {
describe( 'Iframe', function() {

@@ -33,3 +24,13 @@ before(function() {

it('Should run', function( done ) {
TestSharedAPI()
})
})
function TestSharedAPI(){
describe( 'BackgroundWorker#run', function(){
it('should run predefined functions', function( done ){
var worker

@@ -39,9 +40,34 @@

worker.define('job', function(){ return 'ran' }.toString())
worker.define('add', function( a, b ){ return a + b })
worker.define('sub', function( a, b ){ return a - b })
worker.start()
Promise.all([
worker.run('add', [1, 2]),
worker.run('sub', [5, 4])
]).then(function( results ) {
expect(results[0]).to.equal( 3 )
expect(results[1]).to.equal( 1 )
done()
})
})
worker.run('job').then(function( res ) {
expect(res).to.equal('ran')
done()
it('should run first argument as default function if first argument is a function to constructor', function( done ) {
var worker
worker = new BackgroundWorker(function() {
return "default"
})
worker.define('other', function(){
return "other"
})
worker.run().then(function( result ) {
expect( result ).to.equal( "default" )
worker.run('other').then(function( result ) {
expect( result ).to.equal( "other" )
done()
})
})
})

@@ -51,2 +77,42 @@

describe('BackgroundWorker#terminate', function() {
it('should not throw exception of trying to run a terminated worker', function() {
var worker
worker = new BackgroundWorker()
worker.terminate()
expect(function(){
worker.run()
}).to.throwException(function (e) {
expect(e.message.toLowerCase().match('terminated')).to.be.ok()
});
})
})
describe( 'Exceptions', function() {
it('should throw correct typeof exception', function( done ) {
var worker
worker = new BackgroundWorker()
worker.define('TypeError', function(){ throw new TypeError() })
worker.define('SyntaxError', function(){ throw new SyntaxError() })
worker.run('SyntaxError').catch(function( error ) {
expect( error ).to.be.a(SyntaxError)
worker.run('TypeError').catch(function( error ) {
expect( error ).to.be.a(TypeError)
done()
})
})
})
})
it('should import scripts', function( done ) {

@@ -61,7 +127,3 @@ var worker

worker.start()
console.log('RUN')
worker.run('func').then(function( res ) {
console.log('RAN')
expect(res).to.equal('imported')

@@ -71,5 +133,2 @@ done()

})
})
})
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc