all repos — NoPaste @ 29b774f090102303e43cf939b38ac2083e62d9f1

Resurrected - The PussTheCat.org fork of NoPaste

scripts/lzma.js (view raw)

  1//! © 2015 Nathan Rugg <nmrugg@gmail.com> | MIT
  2/// See LICENSE for more details.
  3
  4// jshint bitwise:true, curly:true, eqeqeq:true, forin:true, immed:true, latedef:true, newcap:true, noarg:true, noempty:true, nonew:true, onevar:true, plusplus:true, quotmark:double, undef:true, unused:strict, browser: true, node: true
  5
  6/// Does the environment support web workers?  If not, let's load the worker manually (without polluting the global scope).
  7if (typeof Worker === "undefined" || (typeof location !== "undefined" && location.protocol === "file:")) {
  8    /// Is this Node.js?
  9    if (typeof global !== "undefined" && typeof require !== "undefined") {
 10        this.LZMA = function (lzma_path) {
 11            return require(lzma_path || "./lzma_worker.js").LZMA;
 12        };
 13    /// Is this a browser?
 14    } else if (typeof window !== "undefined" && window.document) {
 15        (function () {
 16            var that = this,
 17                global_var,
 18                req = function req(path) {
 19                    var script_tag  = document.createElement("script");
 20                    script_tag.type ="text/javascript";
 21                    script_tag.src  = path;
 22                    script_tag.onload = function () {
 23                        /// Make sure this LZMA variable doesn't get overwritten by the worker's.
 24                        that.LZMA = non_worker_lzma;
 25                    };
 26                    document.getElementsByTagName("head")[0].appendChild(script_tag);
 27                };
 28            
 29            /// Determine the global variable (it's called "window" in browsers, "global" in Node.js).
 30            if (typeof window !== "undefined") {
 31                global_var = window;
 32            } else if (global) {
 33                global_var = global;
 34            }
 35            
 36            function non_worker_lzma(path) {
 37                var fake_lzma;
 38                
 39                req(path);
 40                
 41                fake_lzma = {
 42                    compress: function compress(mixed, mode, on_finish, on_progress) {
 43                        if (global_var.LZMA_WORKER) {
 44                            global_var.LZMA_WORKER.compress(mixed, mode, on_finish, on_progress);
 45                        } else {
 46                            /// Wait
 47                            setTimeout(function ()
 48                            {
 49                                fake_lzma.compress(mixed, mode, on_finish, on_progress);
 50                            }, 50);
 51                        }
 52                    },
 53                    decompress: function decompress(byte_arr, on_finish, on_progress) {
 54                        if (global_var.LZMA_WORKER) {
 55                            global_var.LZMA_WORKER.decompress(byte_arr, on_finish, on_progress);
 56                        } else {
 57                            /// Wait
 58                            setTimeout(function ()
 59                            {
 60                                fake_lzma.decompress(byte_arr, on_finish, on_progress);
 61                            }, 50);
 62                        }
 63                    },
 64                    worker: function worker () {
 65                        return null;
 66                    }
 67                };
 68                
 69                return fake_lzma;
 70            }
 71            
 72            that.LZMA = non_worker_lzma;
 73        }());
 74    } else {
 75        /// It doesn't seem to be either Node.js or a browser.
 76        console.error("Can't load the worker. Sorry.");
 77    }
 78} else {
 79    /// Let's use Web Workers.
 80    ///NOTE: The "this" keyword is the global context ("window" variable) if loaded via a <script> tag
 81    ///      or the function context if loaded as a module (e.g., in Node.js).
 82    this.LZMA = function (lzma_path) {
 83        var action_compress   = 1,
 84            action_decompress = 2,
 85            action_progress   = 3,
 86            
 87            callback_obj = {},
 88            
 89            ///NOTE: Node.js needs something like "./" or "../" at the beginning.
 90            lzma_worker = new Worker(lzma_path || "./lzma_worker-min.js");
 91        
 92        lzma_worker.onmessage = function onmessage(e) {
 93            if (e.data.action === action_progress) {
 94                if (callback_obj[e.data.cbn] && typeof callback_obj[e.data.cbn].on_progress === "function") {
 95                    callback_obj[e.data.cbn].on_progress(e.data.result);
 96                }
 97            } else {
 98                if (callback_obj[e.data.cbn] && typeof callback_obj[e.data.cbn].on_finish === "function") {
 99                    callback_obj[e.data.cbn].on_finish(e.data.result, e.data.error);
100                    
101                    /// Since the (de)compression is complete, the callbacks are no longer needed.
102                    delete callback_obj[e.data.cbn];
103                }
104            }
105        };
106        
107        /// Very simple error handling.
108        lzma_worker.onerror = function(event) {
109            var err = new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
110            
111            for (var cbn in callback_obj) {
112                callback_obj[cbn].on_finish(null, err);
113            }
114            
115            console.error('Uncaught error in lzma_worker', err);
116        };
117        
118        return (function () {
119            
120            function send_to_worker(action, data, mode, on_finish, on_progress) {
121                var cbn;
122                
123                do {
124                    cbn = Math.floor(Math.random() * (10000000));
125                } while(typeof callback_obj[cbn] !== "undefined");
126                
127                callback_obj[cbn] = {
128                    on_finish:   on_finish,
129                    on_progress: on_progress
130                };
131                
132                lzma_worker.postMessage({
133                    action: action, /// action_compress = 1, action_decompress = 2, action_progress = 3
134                    cbn:    cbn,    /// callback number
135                    data:   data,
136                    mode:   mode
137                });
138            }
139            
140            return {
141                compress: function compress(mixed, mode, on_finish, on_progress) {
142                    send_to_worker(action_compress, mixed, mode, on_finish, on_progress);
143                },
144                decompress: function decompress(byte_arr, on_finish, on_progress) {
145                    send_to_worker(action_decompress, byte_arr, false, on_finish, on_progress);
146                },
147                worker: function worker() {
148                    return lzma_worker;
149                }
150            };
151        }());
152    };
153}