Template:Heidelberg/zipjs/ZWORKER

/* jshint worker:true */ (function main(global) {

 "use strict";
 if (global.zWorkerInitialized)
   throw new Error('z-worker.js should be run only once');
 global.zWorkerInitialized = true;
 addEventListener("message", function(event) {
   var message = event.data, type = message.type, sn = message.sn;
   var handler = handlers[type];
   if (handler) {
     try {
       handler(message);
     } catch (e) {
       onError(type, sn, e);
     }
   }
   // for debug
   // postMessage({type: 'echo', originalType: type, sn: sn});
 });
 var handlers = {
   importScripts : doImportScripts,
   newTask : newTask,
   append : processData,
   flush : processData,
 };
 // deflater/inflater tasks indexed by serial numbers
 var tasks = {};
 function doImportScripts(msg) {
   if (msg.scripts && msg.scripts.length > 0)
     importScripts.apply(undefined, msg.scripts);
   postMessage({type : 'importScripts'});
 }
 function newTask(msg) {
   var CodecClass = global[msg.codecClass];
   var sn = msg.sn;
   if (tasks[sn])
     throw Error('duplicated sn');
   tasks[sn] = {
     codec : new CodecClass(msg.options),
     crcInput : msg.crcType === 'input',
     crcOutput : msg.crcType === 'output',
     crc : new Crc32(),
   };
   postMessage({type : 'newTask', sn : sn});
 }
 // performance may not be supported
 var now = global.performance ? global.performance.now.bind(global.performance)
                              : Date.now;
 function processData(msg) {
   var sn = msg.sn, type = msg.type, input = msg.data;
   var task = tasks[sn];
   // allow creating codec on first append
   if (!task && msg.codecClass) {
     newTask(msg);
     task = tasks[sn];
   }
   var isAppend = type === 'append';
   var start = now();
   var output;
   if (isAppend) {
     try {
       output = task.codec.append(input, function onprogress(loaded) {
         postMessage({type : 'progress', sn : sn, loaded : loaded});
       });
     } catch (e) {
       delete tasks[sn];
       throw e;
     }
   } else {
     delete tasks[sn];
     output = task.codec.flush();
   }
   var codecTime = now() - start;
   start = now();
   if (input && task.crcInput)
     task.crc.append(input);
   if (output && task.crcOutput)
     task.crc.append(output);
   var crcTime = now() - start;
   var rmsg = {type : type, sn : sn, codecTime : codecTime, crcTime : crcTime};
   var transferables = [];
   if (output) {
     rmsg.data = output;
     transferables.push(output.buffer);
   }
   if (!isAppend && (task.crcInput || task.crcOutput))
     rmsg.crc = task.crc.get();
   // posting a message with transferables will fail on IE10
   try {
     postMessage(rmsg, transferables);
   } catch (ex) {
     postMessage(rmsg); // retry without transferables
   }
 }
 function onError(type, sn, e) {
   var msg = {type : type, sn : sn, error : formatError(e)};
   postMessage(msg);
 }
 function formatError(e) { return {message : e.message, stack : e.stack}; }
 // Crc32 code copied from file zip.js
 function Crc32() { this.crc = -1; }
 Crc32.prototype.append = function append(data) {
   var crc = this.crc | 0, table = this.table;
   for (var offset = 0, len = data.length | 0; offset < len; offset++)
     crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
   this.crc = crc;
 };
 Crc32.prototype.get = function get() { return ~this.crc; };
 Crc32.prototype.table = (function() {
   var i, j, t, table = []; // Uint32Array is actually slower than []
   for (i = 0; i < 256; i++) {
     t = i;
     for (j = 0; j < 8; j++)
       if (t & 1)
         t = (t >>> 1) ^ 0xEDB88320;
       else
         t = t >>> 1;
     table[i] = t;
   }
   return table;
 })();
 // "no-op" codec
 function NOOP() {}
 global.NOOP = NOOP;
 NOOP.prototype.append = function append(bytes, onprogress) { return bytes; };
 NOOP.prototype.flush = function flush() {};

})(this);