-
Notifications
You must be signed in to change notification settings - Fork 1
/
lzma.js
131 lines (109 loc) · 5.37 KB
/
lzma.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/// This code is licensed under the MIT License. See LICENSE for more details.
/// Does the environment support web workers? If not, let's fake it.
///NOTE: Since web workers don't work when a page is loaded from the local system, we have to fake it there too. (Take that security measures!)
if (!Worker || (location && location.protocol === "file:")) {
///NOTE: IE8 and IE9 needs onmessage to be created first, IE7- do not care.
///NOTE: Because IE9 implements part of the Web Worker's spec, postMessage() must be overwritten.
/*@cc_on
var onmessage = function () {};
var postMessage = function () {};
@*/
/// If this were a regular function statement, IE9 would run it first and therefore make the Worker variable truthy because of hoisting.
var Worker = function(script) {
var global_var,
return_object = {};
/// Determine the global variable (it's called "window" in browsers, "global" in Node.js).
if (typeof window !== "undefined") {
global_var = window;
} else if (global) {
global_var = global;
}
/// Is the environment is browser?
/// If not, create a require() function, if it doesn't have one.
if (global_var.document && !global_var.require) {
global_var.require = function (path) {
var script_tag = document.createElement("script");
script_tag.type ="text/javascript";
script_tag.src = path;
document.getElementsByTagName("head")[0].appendChild(script_tag);
};
}
/// Dummy onmessage() function.
return_object.onmessage = function () {};
/// This is the function that the main script calls to post a message to the "worker."
return_object.postMessage = function (message) {
/// Has the worker script loaded yet?
if (global_var.onmessage) {
/// Call the global onmessage() created by the "worker."
///NOTE: Wrap the message in an object.
global_var.onmessage({data: message});
} else {
/// Since the script has not yet loaded, wait a moment, and then retry.
setTimeout(function () {
return_object.postMessage(message);
}, 50);
}
};
/// Create a global postMessage() function for the "worker" to call.
global_var.postMessage = function (e) {
///NOTE: Wrap the message in an object.
///TODO: Add more properties.
return_object.onmessage({data: e, type: "message"});
};
require(script);
return return_object;
};
}
///NOTE: The "this" keyword is the global context ("window" variable) if loaded via a <script> tag
/// or the function context if loaded as a module (e.g., in Node.js).
this.LZMA = function (lzma_path) {
var action_compress = 1,
action_decompress = 2,
action_progress = 3,
callback_obj = {},
///NOTE: Node.js needs something like "./" or "../" at the beginning.
lzma_worker = new Worker((typeof lzma_path === "undefined" ? "./lzma_worker.js" : lzma_path));
lzma_worker.onmessage = function (e) {
if (e.data.action === action_progress) {
if (callback_obj[e.data.callback_num] && typeof callback_obj[e.data.callback_num].on_progress === "function") {
callback_obj[e.data.callback_num].on_progress(e.data.result);
}
} else {
if (callback_obj[e.data.callback_num] && typeof callback_obj[e.data.callback_num].on_finish === "function") {
callback_obj[e.data.callback_num].on_finish(e.data.result);
/// Since the (de)compression is complete, the callbacks are no longer needed.
delete callback_obj[e.data.callback_num];
}
}
};
/// Very simple error handling.
lzma_worker.onerror = function(event) {
throw new Error(event.message + " (" + event.filename + ":" + event.lineno + ")");
};
return (function () {
function send_to_worker(action, data, mode, on_finish, on_progress) {
var callback_num;
do {
callback_num = Math.floor(Math.random() * (10000000));
} while(typeof callback_obj[callback_num] !== "undefined");
callback_obj[callback_num] = {
on_finish: on_finish,
on_progress: on_progress
};
lzma_worker.postMessage({
action: action,
callback_num: callback_num,
data: data,
mode: mode
});
}
return {
compress: function (string, mode, on_finish, on_progress) {
send_to_worker(action_compress, String(string), mode, on_finish, on_progress);
},
decompress: function (byte_arr, on_finish, on_progress) {
send_to_worker(action_decompress, byte_arr, false, on_finish, on_progress);
}
};
}());
};