@lmjs/core 1.0.7 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bundle.js +264 -0
- package/build/plugins-registry.js +216 -0
- package/dist/lumenjs-core-with-plugins.js +59258 -0
- package/dist/lumenjs-core.js +50 -0
- package/dist/lumenjs-plugins.css +2822 -0
- package/package.json +59 -28
- package/src/_re.js +2709 -0
- package/src/dom-shim.js +640 -0
- package/src/index-bootstrap.js +53 -0
- package/src/lstnrs.js +1409 -0
- package/src/walk.js +837 -0
- package/src/workers/css.js +1 -0
- package/src/workers/cssRaw.js +1173 -0
- package/src/workers/esp.js +1 -0
- package/src/workers/espRaw.js +78 -0
- package/src/workers/up.js +1 -0
- package/src/workers/upRaw.js +491 -0
- package/src/workers/work.js +1 -0
- package/src/workers/workRaw.js +1097 -0
- package/src/ws.js +1162 -0
- package/vendor/astring.js +3 -0
- package/vendor/bootstrap2-less-stubs/mixins.less +16 -0
- package/vendor/bootstrap2-less-stubs/variables.less +13 -0
- package/vendor/md5.js +1 -0
- package/vendor/reconnecting-websocket.js +4143 -0
- package/vendor/webworker-helper.js +1 -0
- package/LICENSE +0 -201
- package/README.md +0 -3
- package/index.js +0 -14
|
@@ -0,0 +1,1097 @@
|
|
|
1
|
+
//https://github.com/tanzeelkazi/web-worker
|
|
2
|
+
/*eslint no-native-reassign:0 */
|
|
3
|
+
(function ($) {
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The WebWorker module.
|
|
8
|
+
* @module WebWorker
|
|
9
|
+
*/
|
|
10
|
+
var WebWorker = null,
|
|
11
|
+
_WebWorker = null,
|
|
12
|
+
NativeWorker = null,
|
|
13
|
+
|
|
14
|
+
context = null,
|
|
15
|
+
className = null,
|
|
16
|
+
|
|
17
|
+
defaultContext = window,
|
|
18
|
+
defaultClassName = 'WebWorker',
|
|
19
|
+
|
|
20
|
+
State = null,
|
|
21
|
+
|
|
22
|
+
Action = null,
|
|
23
|
+
|
|
24
|
+
Event = null,
|
|
25
|
+
eventPrefix = 'webworker:',
|
|
26
|
+
|
|
27
|
+
EventMap = null,
|
|
28
|
+
|
|
29
|
+
Error = null,
|
|
30
|
+
|
|
31
|
+
slice = null,
|
|
32
|
+
|
|
33
|
+
key = null;
|
|
34
|
+
|
|
35
|
+
context = context || defaultContext;
|
|
36
|
+
className = className || defaultClassName;
|
|
37
|
+
|
|
38
|
+
WebWorker = context[className] || null;
|
|
39
|
+
|
|
40
|
+
if (WebWorker !== null) {
|
|
41
|
+
_WebWorker = WebWorker;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
slice = Array.prototype.slice;
|
|
45
|
+
NativeWorker = window.Worker;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The main WebWorker class.
|
|
49
|
+
* @class WebWorker
|
|
50
|
+
* @constructor
|
|
51
|
+
* @param {Object|String} opts
|
|
52
|
+
* The options to be passed into the constructor.
|
|
53
|
+
* <br />
|
|
54
|
+
* If you pass a `String`, the code will first search
|
|
55
|
+
* for an element selector with the worker script.
|
|
56
|
+
* If it does not find the element it will then use
|
|
57
|
+
* it as a URL to the actual worker script.
|
|
58
|
+
*/
|
|
59
|
+
WebWorker = function () {
|
|
60
|
+
this._constructor.apply(this, arguments);
|
|
61
|
+
return;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A jQuery object created from the webworker instance.
|
|
66
|
+
* @property _$
|
|
67
|
+
* @private
|
|
68
|
+
* @type {jQuery}
|
|
69
|
+
* @default $(this)
|
|
70
|
+
* @readOnly
|
|
71
|
+
*/
|
|
72
|
+
WebWorker.prototype._$ = null;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The callback stack for the
|
|
76
|
+
* {{#crossLink "WebWorker/loading:method"}}{{/crossLink}},
|
|
77
|
+
* {{#crossLink "WebWorker/loaded:method"}}{{/crossLink}},
|
|
78
|
+
* {{#crossLink "WebWorker/starting:method"}}{{/crossLink}},
|
|
79
|
+
* {{#crossLink "WebWorker/started:method"}}{{/crossLink}},
|
|
80
|
+
* {{#crossLink "WebWorker/terminating:method"}}{{/crossLink}},
|
|
81
|
+
* and
|
|
82
|
+
* {{#crossLink "WebWorker/terminated:method"}}{{/crossLink}}
|
|
83
|
+
* hooks.
|
|
84
|
+
* @property _callbackStack
|
|
85
|
+
* @type {Object}
|
|
86
|
+
* @private
|
|
87
|
+
* @default null
|
|
88
|
+
*/
|
|
89
|
+
WebWorker.prototype._callbackStack = null;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Stores the last error generated by the worker instance.
|
|
93
|
+
* @property _lastError
|
|
94
|
+
* @type {String}
|
|
95
|
+
* @private
|
|
96
|
+
* @default null
|
|
97
|
+
*/
|
|
98
|
+
WebWorker.prototype._lastError = null;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Stores the log information for this worker instance. The log is not
|
|
102
|
+
* initialized unless explicity invoked by the
|
|
103
|
+
* {{#crossLink "WebWorker/log:method"}}{{/crossLink}} or
|
|
104
|
+
* {{#crossLink "WebWorker/getLog:method"}}{{/crossLink}} methods
|
|
105
|
+
* which internally call {{#crossLink "WebWorker/_initLog:method"}}{{/crossLink}}
|
|
106
|
+
* to initialize this property.
|
|
107
|
+
* @property _log
|
|
108
|
+
* @type {Array}
|
|
109
|
+
* @private
|
|
110
|
+
* @default null
|
|
111
|
+
*/
|
|
112
|
+
WebWorker.prototype._log = null;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* The native browser worker object. This is generated once the worker is loaded.
|
|
116
|
+
* @property _nativeWorker
|
|
117
|
+
* @type {Object}
|
|
118
|
+
* @private
|
|
119
|
+
* @default null
|
|
120
|
+
*/
|
|
121
|
+
WebWorker.prototype._nativeWorker = null;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* The current state of the worker. This value is updated internally by the worker.
|
|
125
|
+
* Valid values for this property are defined in {{#crossLink "WebWorker/State:property"}}{{/crossLink}}.
|
|
126
|
+
* @property _state
|
|
127
|
+
* @type {Number}
|
|
128
|
+
* @private
|
|
129
|
+
* @default null
|
|
130
|
+
*/
|
|
131
|
+
WebWorker.prototype._state = null;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The `Blob` URL generated for the worker.
|
|
135
|
+
* @property _workerBlobUrl
|
|
136
|
+
* @type {String}
|
|
137
|
+
* @private
|
|
138
|
+
* @default null
|
|
139
|
+
*/
|
|
140
|
+
WebWorker.prototype._workerBlobUrl = null;
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The worker script contents (cached for further use).
|
|
144
|
+
* @property _workerScript
|
|
145
|
+
* @type {String}
|
|
146
|
+
* @private
|
|
147
|
+
* @default null
|
|
148
|
+
*/
|
|
149
|
+
WebWorker.prototype._workerScript = null;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* The worker URL (if provided)
|
|
153
|
+
* @property _workerUrl
|
|
154
|
+
* @type {String}
|
|
155
|
+
* @private
|
|
156
|
+
* @default null
|
|
157
|
+
*/
|
|
158
|
+
WebWorker.prototype._workerUrl = null;
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The main constructor calls this method. This method
|
|
163
|
+
* was moved out of the main constructor to keep the
|
|
164
|
+
* code clean.
|
|
165
|
+
* @method _constructor
|
|
166
|
+
* @param {Object} opts* Arguments to the main constructor
|
|
167
|
+
* @private
|
|
168
|
+
*/
|
|
169
|
+
WebWorker.prototype._constructor = function (opts) {
|
|
170
|
+
var $scriptElement = null,
|
|
171
|
+
scriptContents = null,
|
|
172
|
+
workerUrl = null;
|
|
173
|
+
|
|
174
|
+
Object.defineProperty(this, '_$', {
|
|
175
|
+
"configurable": false,
|
|
176
|
+
"enumerable": true,
|
|
177
|
+
"value": $(this),
|
|
178
|
+
"writable": false
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
opts = opts || null;
|
|
182
|
+
|
|
183
|
+
if (opts === null) {
|
|
184
|
+
this.throwError(Error.INVALID_ARGUMENTS, null, true);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (typeof opts === 'string') {
|
|
188
|
+
let strtr = "";
|
|
189
|
+
opts = $.trim(opts);
|
|
190
|
+
|
|
191
|
+
try {
|
|
192
|
+
if (window.hasOwnProperty(opts) && typeof window[opts] === "string") {
|
|
193
|
+
strtr = window[opts];
|
|
194
|
+
this._workerScript = strtr;
|
|
195
|
+
} else {
|
|
196
|
+
$scriptElement = $(opts);
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
// Cannot be resolved as a selector
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
if ($scriptElement !== null && $scriptElement.length > 0) {
|
|
204
|
+
// Matching script element found
|
|
205
|
+
// Cache its contents
|
|
206
|
+
scriptContents = $scriptElement.text();
|
|
207
|
+
this._workerScript = scriptContents;
|
|
208
|
+
} else if (strtr == "") {
|
|
209
|
+
workerUrl = opts;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this._workerUrl = workerUrl;
|
|
214
|
+
|
|
215
|
+
this._callbackStack = {
|
|
216
|
+
"error": [],
|
|
217
|
+
"loading": [],
|
|
218
|
+
"loaded": [],
|
|
219
|
+
"starting": [],
|
|
220
|
+
"started": [],
|
|
221
|
+
"terminating": [],
|
|
222
|
+
"terminated": []
|
|
223
|
+
};
|
|
224
|
+
|
|
225
|
+
this._assignEventHandlers();
|
|
226
|
+
|
|
227
|
+
this._state = State.INITIALIZED;
|
|
228
|
+
|
|
229
|
+
this.trigger(Event.INITIALIZED);
|
|
230
|
+
|
|
231
|
+
return;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Initializes the log array when invoked.
|
|
236
|
+
* @method _initLog
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
WebWorker.prototype._initLog = function () {
|
|
240
|
+
this._log = [];
|
|
241
|
+
return this._log;
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Returns the worker URL if one was provided during object instantiation.
|
|
246
|
+
* @method getUrl
|
|
247
|
+
* @return {String} The worker URL, `null` otherwise.
|
|
248
|
+
*/
|
|
249
|
+
WebWorker.prototype.getUrl = function () {
|
|
250
|
+
return this._workerUrl;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Returns the worker blob URL if one has been generated.
|
|
255
|
+
* @method getBlobUrl
|
|
256
|
+
* @return {String} The worker blob URL, `null` otherwise.
|
|
257
|
+
*/
|
|
258
|
+
WebWorker.prototype.getBlobUrl = function () {
|
|
259
|
+
return this._workerBlobUrl;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Returns the worker blob URL if one has been generated.
|
|
264
|
+
* @method getBlobUrl
|
|
265
|
+
* @return {Array} The log array of the worker.
|
|
266
|
+
*/
|
|
267
|
+
WebWorker.prototype.getLog = function () {
|
|
268
|
+
var log;
|
|
269
|
+
log = this._log || this._initLog();
|
|
270
|
+
return log;
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Returns the native browser worker instance if one has been generated.
|
|
275
|
+
* @method getNativeWorker
|
|
276
|
+
* @return {Object} The native worker instance, `null` otherwise.
|
|
277
|
+
*/
|
|
278
|
+
WebWorker.prototype.getNativeWorker = function () {
|
|
279
|
+
return this._nativeWorker;
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Returns the current state of the worker as an integer.
|
|
284
|
+
* Refer to {{#crossLink "WebWorker/State:property"}}{{/crossLink}} for state values.
|
|
285
|
+
* @method getState
|
|
286
|
+
* @return {Number} An integer representing the current state of the worker.
|
|
287
|
+
*/
|
|
288
|
+
WebWorker.prototype.getState = function () {
|
|
289
|
+
return this._state;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Returns whether the worker script is loading.
|
|
294
|
+
* @method isLoading
|
|
295
|
+
* @return {Boolean} Returns `true` if the worker script is loading, `false` otherwise.
|
|
296
|
+
*/
|
|
297
|
+
WebWorker.prototype.isLoading = function () {
|
|
298
|
+
return this.getState() === State.LOADING;
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Returns whether the worker script is loaded.
|
|
303
|
+
* @method isLoaded
|
|
304
|
+
* @return {Boolean} Returns `true` if the worker script is loaded, `false` otherwise.
|
|
305
|
+
*/
|
|
306
|
+
WebWorker.prototype.isLoaded = function () {
|
|
307
|
+
var state = this.getState();
|
|
308
|
+
return state >= State.LOADED && !this.isTerminated();
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Returns whether the worker script is starting.
|
|
313
|
+
* @method isStarting
|
|
314
|
+
* @return {Boolean} Returns `true` if the worker script is starting, `false` otherwise.
|
|
315
|
+
*/
|
|
316
|
+
WebWorker.prototype.isStarting = function () {
|
|
317
|
+
return this.getState() === State.STARTING;
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Returns whether the worker script is started.
|
|
322
|
+
* @method isStarted
|
|
323
|
+
* @return {Boolean} Returns `true` if the worker script is started, `false` otherwise.
|
|
324
|
+
*/
|
|
325
|
+
WebWorker.prototype.isStarted = function () {
|
|
326
|
+
var state = this.getState();
|
|
327
|
+
return state >= State.STARTED && !this.isTerminated();
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Returns whether the worker script is terminating.
|
|
332
|
+
* @method isTerminating
|
|
333
|
+
* @return {Boolean} Returns `true` if the worker script is terminating, `false` otherwise.
|
|
334
|
+
*/
|
|
335
|
+
WebWorker.prototype.isTerminating = function () {
|
|
336
|
+
return this.getState() === State.TERMINATING;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Returns whether the worker script is terminated.
|
|
341
|
+
* @method isTerminated
|
|
342
|
+
* @return {Boolean} Returns `true` if the worker script is terminated, `false` otherwise.
|
|
343
|
+
*/
|
|
344
|
+
WebWorker.prototype.isTerminated = function () {
|
|
345
|
+
return this.getState() === State.TERMINATED;
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Triggers the instance to load the worker script and generate a native browser worker.
|
|
350
|
+
* @method load
|
|
351
|
+
* @chainable
|
|
352
|
+
*/
|
|
353
|
+
WebWorker.prototype.load = function () {
|
|
354
|
+
var self = this,
|
|
355
|
+
workerUrl = null,
|
|
356
|
+
onScriptLoaded = null;
|
|
357
|
+
|
|
358
|
+
if (self.isLoading() || self.isLoaded()) {
|
|
359
|
+
return self;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Trigger event
|
|
363
|
+
self.trigger(Event.WORKER_LOADING);
|
|
364
|
+
|
|
365
|
+
workerUrl = self.getUrl() || null;
|
|
366
|
+
onScriptLoaded = function () {
|
|
367
|
+
var blob = null,
|
|
368
|
+
scriptContents = null;
|
|
369
|
+
|
|
370
|
+
scriptContents = self._workerScript;
|
|
371
|
+
scriptContents = WebWorker._workerScriptWrapper.replace(/\{\{main-function\}\}/g, scriptContents);
|
|
372
|
+
|
|
373
|
+
blob = new window.Blob([scriptContents], {
|
|
374
|
+
"type": "text/javascript"
|
|
375
|
+
});
|
|
376
|
+
self._workerBlobUrl = window.URL.createObjectURL(blob);
|
|
377
|
+
|
|
378
|
+
self._createWorker();
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
if (workerUrl === null) {
|
|
382
|
+
// Script already available
|
|
383
|
+
onScriptLoaded();
|
|
384
|
+
} else {
|
|
385
|
+
// Ajax request
|
|
386
|
+
$.ajax({
|
|
387
|
+
"async": true,
|
|
388
|
+
"url": workerUrl,
|
|
389
|
+
"dataType": 'text',
|
|
390
|
+
"crossDomain": true,
|
|
391
|
+
"success": function (responseText) {
|
|
392
|
+
self._workerScript = responseText;
|
|
393
|
+
onScriptLoaded();
|
|
394
|
+
},
|
|
395
|
+
"error": function () {
|
|
396
|
+
self.throwError(Error.WORKER_DID_NOT_LOAD, arguments);
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return self;
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Concatenates log messages to internal log array.
|
|
406
|
+
* @method log
|
|
407
|
+
* @param {Mixed} data The data that you wish to be logged.
|
|
408
|
+
* @chainable
|
|
409
|
+
*/
|
|
410
|
+
WebWorker.prototype.log = function (data) {
|
|
411
|
+
var log;
|
|
412
|
+
|
|
413
|
+
log = this._log || this._initLog();
|
|
414
|
+
log.push(data);
|
|
415
|
+
|
|
416
|
+
return this;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Generates the native browser worker and attaches the message parser to it.
|
|
421
|
+
* @method _createWorker
|
|
422
|
+
* @private
|
|
423
|
+
* @chainable
|
|
424
|
+
*/
|
|
425
|
+
WebWorker.prototype._createWorker = function () {
|
|
426
|
+
this._nativeWorker = new NativeWorker(this.getBlobUrl());
|
|
427
|
+
this._attachMessageParser();
|
|
428
|
+
return this;
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Assigns the basic internal event handlers to the worker instance.
|
|
433
|
+
* @method _assignEventHandlers
|
|
434
|
+
* @private
|
|
435
|
+
* @chainable
|
|
436
|
+
*/
|
|
437
|
+
WebWorker.prototype._assignEventHandlers = function () {
|
|
438
|
+
function getCallbackStackExecutor(stackId) {
|
|
439
|
+
return function () {
|
|
440
|
+
var callbackStack = this._callbackStack[stackId],
|
|
441
|
+
stateId,
|
|
442
|
+
curCallback;
|
|
443
|
+
|
|
444
|
+
stateId = stackId.toUpperCase();
|
|
445
|
+
|
|
446
|
+
if (stateId in State) {
|
|
447
|
+
// Set the current state of the worker
|
|
448
|
+
// as long as it's a valid state.
|
|
449
|
+
this._state = State[stateId];
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/* eslint no-cond-assign:0 */
|
|
453
|
+
while (curCallback = callbackStack.pop()) {
|
|
454
|
+
curCallback.apply(this, arguments);
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
this.on(Event.ERROR, getCallbackStackExecutor('error'));
|
|
460
|
+
this.on(Event.WORKER_LOADING, getCallbackStackExecutor('loading'));
|
|
461
|
+
this.on(Event.WORKER_LOADED, getCallbackStackExecutor('loaded'));
|
|
462
|
+
this.on(Event.WORKER_STARTING, getCallbackStackExecutor('starting'));
|
|
463
|
+
this.on(Event.WORKER_STARTED, getCallbackStackExecutor('started'));
|
|
464
|
+
this.on(Event.WORKER_TERMINATING, getCallbackStackExecutor('terminating'));
|
|
465
|
+
this.on(Event.WORKER_TERMINATED, getCallbackStackExecutor('terminated'));
|
|
466
|
+
|
|
467
|
+
return this;
|
|
468
|
+
};
|
|
469
|
+
|
|
470
|
+
function getCallbackStackUpdater(stackId) {
|
|
471
|
+
return function (callback) {
|
|
472
|
+
var callbackStack = this._callbackStack[stackId];
|
|
473
|
+
|
|
474
|
+
if (typeof callback === 'function') {
|
|
475
|
+
callbackStack.push(callback);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return this;
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Hook for the error event.
|
|
484
|
+
* @method error
|
|
485
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
486
|
+
* @chainable
|
|
487
|
+
*/
|
|
488
|
+
WebWorker.prototype.error = getCallbackStackUpdater('error');
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Hook for the loading event.
|
|
492
|
+
* @method loading
|
|
493
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
494
|
+
* @chainable
|
|
495
|
+
*/
|
|
496
|
+
WebWorker.prototype.loading = getCallbackStackUpdater('loading');
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Hook for the loaded event.
|
|
500
|
+
* @method loaded
|
|
501
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
502
|
+
* @chainable
|
|
503
|
+
*/
|
|
504
|
+
WebWorker.prototype.loaded = getCallbackStackUpdater('loaded');
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Hook for the starting event.
|
|
508
|
+
* @method starting
|
|
509
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
510
|
+
* @chainable
|
|
511
|
+
*/
|
|
512
|
+
WebWorker.prototype.starting = getCallbackStackUpdater('starting');
|
|
513
|
+
|
|
514
|
+
/**
|
|
515
|
+
* Hook for the started event.
|
|
516
|
+
* @method started
|
|
517
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
518
|
+
* @chainable
|
|
519
|
+
*/
|
|
520
|
+
WebWorker.prototype.started = getCallbackStackUpdater('started');
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Hook for the terminating event.
|
|
524
|
+
* @method terminating
|
|
525
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
526
|
+
* @chainable
|
|
527
|
+
*/
|
|
528
|
+
WebWorker.prototype.terminating = getCallbackStackUpdater('terminating');
|
|
529
|
+
|
|
530
|
+
/**
|
|
531
|
+
* Hook for the terminated event.
|
|
532
|
+
* @method terminated
|
|
533
|
+
* @param {Function} callback The callback function that get's called when the event get's triggered.
|
|
534
|
+
* @chainable
|
|
535
|
+
*/
|
|
536
|
+
WebWorker.prototype.terminated = getCallbackStackUpdater('terminated');
|
|
537
|
+
|
|
538
|
+
/**
|
|
539
|
+
* Start the worker (if it has loaded). Any arguments passed to this method
|
|
540
|
+
* will be passed internally to the worker script.
|
|
541
|
+
* <br />
|
|
542
|
+
* Note that you should start the worker only AFTER it has loaded. If you call this
|
|
543
|
+
* method before the worker has loaded it will fail silently.
|
|
544
|
+
* @method start
|
|
545
|
+
* @param {Mixed} args* Arguments to be passed internally to the worker
|
|
546
|
+
* script.<br />
|
|
547
|
+
* Please ensure that arguments are basic
|
|
548
|
+
* objects that can be cloned by the browser
|
|
549
|
+
* for `postMessage` interface.
|
|
550
|
+
* @chainable
|
|
551
|
+
*/
|
|
552
|
+
WebWorker.prototype.start = function () {
|
|
553
|
+
var args = null;
|
|
554
|
+
|
|
555
|
+
if (this.isStarting() || this.isStarted()) {
|
|
556
|
+
return this;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
args = slice.call(arguments);
|
|
560
|
+
|
|
561
|
+
if (!this.isLoaded()) {
|
|
562
|
+
this.on(Event.WORKER_LOADED, function () {
|
|
563
|
+
this.start.apply(this, args);
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
this.load();
|
|
567
|
+
return this;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
this.trigger(Event.WORKER_STARTING);
|
|
571
|
+
|
|
572
|
+
this.sendMessage(Action.START, args);
|
|
573
|
+
|
|
574
|
+
return this;
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* This method acts as the main communications interface with the worker and is used internally.
|
|
579
|
+
* <br /><br />
|
|
580
|
+
* **You are recommended to use the trigger interface _ONLY_ as it is the most reliable mode of
|
|
581
|
+
* communication between the instance and the actual worker.**
|
|
582
|
+
* <br /><br />
|
|
583
|
+
* If you do understand the risks, you are welcome to use this method (a reason why it is
|
|
584
|
+
* left public instead of private).
|
|
585
|
+
* <br /><br />
|
|
586
|
+
* It's basic usage is very simple. Specify the `action`, which is the
|
|
587
|
+
* method name to call _inside_ the worker script, and the arguments to pass in. The worker
|
|
588
|
+
* does the rest of the heavy lifting.
|
|
589
|
+
* <br /><br />
|
|
590
|
+
* Note: This method is NOT synchronous and will not warn you of any errors.
|
|
591
|
+
* @method sendMessage
|
|
592
|
+
* @param {String} action The name of the method within the worker script to call.
|
|
593
|
+
* @param {Array} args The array of arguments to pass to the worker. Ensure that this data
|
|
594
|
+
* can be cloned by the browser for the `postMessage` interface.
|
|
595
|
+
* @chainable
|
|
596
|
+
*/
|
|
597
|
+
WebWorker.prototype.sendMessage = function (action, args) {
|
|
598
|
+
var nativeWorker = null,
|
|
599
|
+
message = null;
|
|
600
|
+
|
|
601
|
+
action = action || null;
|
|
602
|
+
args = args || null;
|
|
603
|
+
|
|
604
|
+
if (action === null) {
|
|
605
|
+
return this;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
message = {
|
|
609
|
+
"__isWebWorkerMsg": true
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
message.action = action;
|
|
613
|
+
message.args = args;
|
|
614
|
+
|
|
615
|
+
nativeWorker = this.getNativeWorker();
|
|
616
|
+
|
|
617
|
+
if (nativeWorker) {
|
|
618
|
+
nativeWorker.postMessage(message);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
return this;
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* Attaches the message parser to the native worker. This allows the worker to hook into
|
|
626
|
+
* `postMessage` API and set up a communications protocol between the instance and the
|
|
627
|
+
* native browser worker.
|
|
628
|
+
* @method _attachMessageParser
|
|
629
|
+
* @private
|
|
630
|
+
* @chainable
|
|
631
|
+
*/
|
|
632
|
+
WebWorker.prototype._attachMessageParser = function () {
|
|
633
|
+
var $nativeWorker = null;
|
|
634
|
+
|
|
635
|
+
$nativeWorker = $(this.getNativeWorker());
|
|
636
|
+
|
|
637
|
+
$nativeWorker.on('message', $.proxy(function (event) {
|
|
638
|
+
var originalEvent = event.originalEvent || event,
|
|
639
|
+
msg = originalEvent.data,
|
|
640
|
+
action = null,
|
|
641
|
+
args = null;
|
|
642
|
+
|
|
643
|
+
if (typeof msg === 'object'
|
|
644
|
+
&& '__isWebWorkerMsg' in msg
|
|
645
|
+
&& msg.__isWebWorkerMsg) {
|
|
646
|
+
action = msg.action;
|
|
647
|
+
args = msg.args;
|
|
648
|
+
|
|
649
|
+
this[action].apply(this, args);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
return;
|
|
653
|
+
}, this));
|
|
654
|
+
|
|
655
|
+
$nativeWorker.on('error', $.proxy(this.throwError, this));
|
|
656
|
+
|
|
657
|
+
return this;
|
|
658
|
+
};
|
|
659
|
+
|
|
660
|
+
/**
|
|
661
|
+
* This method triggers the worker to terminate. Terminating is ASYNCHRONOUS. This method
|
|
662
|
+
* sets the ball rolling. It sends the message to the worker which may have a
|
|
663
|
+
* `terminateHandler` that can do some cleanup operations before control is passed back
|
|
664
|
+
* to the instance and the final terminate (`terminateNow`) is executed.
|
|
665
|
+
* @method terminate
|
|
666
|
+
* @chainable
|
|
667
|
+
*/
|
|
668
|
+
WebWorker.prototype.terminate = function () {
|
|
669
|
+
var nativeWorker = this.getNativeWorker() || null;
|
|
670
|
+
|
|
671
|
+
if (nativeWorker) {
|
|
672
|
+
this.trigger(Event.WORKER_TERMINATING);
|
|
673
|
+
this.sendMessage(Action.TERMINATE, slice.call(arguments));
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return this;
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
/**
|
|
680
|
+
* Terminates the worker _immediately_.
|
|
681
|
+
* <br />
|
|
682
|
+
* This method can be used to terminate the worker
|
|
683
|
+
* _immediately_, instead of waiting for the asynchronous terminate cycle to complete.
|
|
684
|
+
* <br />
|
|
685
|
+
* It is also called internally once the asynchronous `terminate` cycle
|
|
686
|
+
* passes control back to the instance to execute the final terminate.
|
|
687
|
+
* @method terminateNow
|
|
688
|
+
* @chainable
|
|
689
|
+
*/
|
|
690
|
+
WebWorker.prototype.terminateNow = function () {
|
|
691
|
+
var nativeWorker = null;
|
|
692
|
+
|
|
693
|
+
if (!this.isTerminating()) {
|
|
694
|
+
this.trigger(Event.WORKER_TERMINATING);
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
nativeWorker = this.getNativeWorker() || null;
|
|
698
|
+
|
|
699
|
+
if (nativeWorker) {
|
|
700
|
+
nativeWorker.terminate();
|
|
701
|
+
this._nativeWorker = null;
|
|
702
|
+
this.trigger(Event.WORKER_TERMINATED);
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
return this;
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Used to bind event listeners to the worker. Internally it uses the jQuery `.on` method.
|
|
710
|
+
* @method on
|
|
711
|
+
* @param {Mixed} args* Lookup the jQuery `.on` API for argument list.
|
|
712
|
+
* @chainable
|
|
713
|
+
*/
|
|
714
|
+
WebWorker.prototype.on = function () {
|
|
715
|
+
var $worker = this._$;
|
|
716
|
+
$worker.on.apply($worker, arguments);
|
|
717
|
+
return this;
|
|
718
|
+
};
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Used to bind event listeners to the worker for single execution. Internally it uses the jQuery `.one` method.
|
|
722
|
+
* @method one
|
|
723
|
+
* @param {Mixed} args* Lookup the jQuery `.one` API for argument list.
|
|
724
|
+
* @chainable
|
|
725
|
+
*/
|
|
726
|
+
WebWorker.prototype.one = function () {
|
|
727
|
+
var $worker = this._$;
|
|
728
|
+
$worker.one.apply($worker, arguments);
|
|
729
|
+
return this;
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
/**
|
|
733
|
+
* Used to unbind event listeners from the worker. Internally it uses the jQuery `.off` method.
|
|
734
|
+
* @method off
|
|
735
|
+
* @param {Mixed} args* Lookup the jQuery `.off` API for argument list.
|
|
736
|
+
* @chainable
|
|
737
|
+
*/
|
|
738
|
+
WebWorker.prototype.off = function () {
|
|
739
|
+
var $worker = this._$;
|
|
740
|
+
|
|
741
|
+
$worker.off.apply($worker, arguments);
|
|
742
|
+
this._assignEventHandlers();
|
|
743
|
+
|
|
744
|
+
return this;
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Used to trigger events on the worker. Internally it uses a combination of the jQuery `.trigger` method
|
|
749
|
+
* and a custom trigger for triggering events on the native worker script.
|
|
750
|
+
* <br /><br />
|
|
751
|
+
* If an event type is recognized as an internal event type, the trigger is executed on the base instance
|
|
752
|
+
* using jQuery. Otherwise the `.sendMessage` API is used to pass the trigger to the worker script.
|
|
753
|
+
* @method trigger
|
|
754
|
+
* @param {Object} event This can be a string `eventType` or an object `event`. Please ensure that if using
|
|
755
|
+
* object events, that they are clonable by the browser for the `postMessage` API.
|
|
756
|
+
* @chainable
|
|
757
|
+
*/
|
|
758
|
+
WebWorker.prototype.trigger = function (event) {
|
|
759
|
+
var passedEventString = false,
|
|
760
|
+
eventType = null,
|
|
761
|
+
eventArgs = null;
|
|
762
|
+
|
|
763
|
+
if (typeof event === 'object') {
|
|
764
|
+
eventType = event.type || null;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
if (typeof event === 'string') {
|
|
768
|
+
eventType = event || null;
|
|
769
|
+
passedEventString = true;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
if (eventType === null) {
|
|
773
|
+
return this;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (eventType in EventMap) {
|
|
777
|
+
if (passedEventString) {
|
|
778
|
+
event = new $.Event(eventType);
|
|
779
|
+
}
|
|
780
|
+
event.worker = this;
|
|
781
|
+
eventArgs = [event];
|
|
782
|
+
if (arguments.length > 1) {
|
|
783
|
+
eventArgs = eventArgs.concat(slice.call(arguments, 1));
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
this._triggerSelf.apply(this, eventArgs);
|
|
787
|
+
return this;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
if (passedEventString) {
|
|
791
|
+
event = {
|
|
792
|
+
"type": eventType,
|
|
793
|
+
"data": arguments[1] ? arguments[1] : {}
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
eventArgs = [event];
|
|
797
|
+
|
|
798
|
+
this.sendMessage(Action.TRIGGER_SELF, eventArgs);
|
|
799
|
+
|
|
800
|
+
return this;
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
/**
|
|
804
|
+
* You may want to trigger an event on the base worker instance irrespective of it's event type. Use this
|
|
805
|
+
* method to achieve the same.
|
|
806
|
+
* @method triggerSelf
|
|
807
|
+
* @param {Object} event This can be a string `eventType` or an object `event`.
|
|
808
|
+
* @chainable
|
|
809
|
+
*/
|
|
810
|
+
WebWorker.prototype.triggerSelf = function (event) {
|
|
811
|
+
var eventType = null,
|
|
812
|
+
eventArgs = null;
|
|
813
|
+
|
|
814
|
+
event = event || null;
|
|
815
|
+
|
|
816
|
+
if (event === null) {
|
|
817
|
+
return this;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
if (typeof event === 'string') {
|
|
821
|
+
eventType = event;
|
|
822
|
+
event = new $.Event(eventType);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
event.originalEvent = event.originalEvent || event;
|
|
826
|
+
event.worker = this;
|
|
827
|
+
eventArgs = [event];
|
|
828
|
+
if (arguments.length > 1) {
|
|
829
|
+
eventArgs = eventArgs.concat(slice.call(arguments, 1));
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
this._triggerSelf.apply(this, eventArgs);
|
|
833
|
+
|
|
834
|
+
return this;
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Internal method to trigger events on the base worker instance.
|
|
839
|
+
* @method _triggerSelf
|
|
840
|
+
* @private
|
|
841
|
+
* @param {Mixed} args* Arguments to `trigger`.
|
|
842
|
+
* @chainable
|
|
843
|
+
*/
|
|
844
|
+
WebWorker.prototype._triggerSelf = function () {
|
|
845
|
+
var $worker = null;
|
|
846
|
+
|
|
847
|
+
$worker = this._$;
|
|
848
|
+
$worker.trigger.apply($worker, arguments);
|
|
849
|
+
|
|
850
|
+
return this;
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
/**
|
|
854
|
+
* Throw error on the worker instance. This internally triggers the `error` event.
|
|
855
|
+
* Optionally you can also make this method throw an exception.
|
|
856
|
+
* <br />
|
|
857
|
+
* This method also internally updates the `lastError` value on the instance
|
|
858
|
+
* and static properties.
|
|
859
|
+
* @method throwError
|
|
860
|
+
* @param {String} error Error string that describes the error.
|
|
861
|
+
* @param {Mixed} [data] Data that is to be associated with the error event.
|
|
862
|
+
* @param {Boolean} [throwException] Set to `true` if you want to throw an exception in addition to the error event.
|
|
863
|
+
* @chainable
|
|
864
|
+
*/
|
|
865
|
+
WebWorker.prototype.throwError = function (error, data, throwException) {
|
|
866
|
+
var errorData = null;
|
|
867
|
+
|
|
868
|
+
error = error || Error.UNKNOWN;
|
|
869
|
+
|
|
870
|
+
if (typeof error === 'object') {
|
|
871
|
+
error = error.originalEvent || error;
|
|
872
|
+
errorData = error.data || null;
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
errorData = typeof data === 'undefined' ? errorData : data;
|
|
876
|
+
throwException = throwException || false;
|
|
877
|
+
|
|
878
|
+
this._lastError = error;
|
|
879
|
+
WebWorker._lastError = error;
|
|
880
|
+
|
|
881
|
+
if ('_triggerError' in this) {
|
|
882
|
+
this._triggerError(error, data, throwException);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
if (throwException) {
|
|
886
|
+
throw new window.Error(error);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
return this;
|
|
890
|
+
};
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Internal method used to trigger the `error` event on the instance.
|
|
894
|
+
* @method _triggerError
|
|
895
|
+
* @private
|
|
896
|
+
* @param {String} error Error string that describes the error.
|
|
897
|
+
* @param {Mixed} [data] Data that is to be associated with the error event.
|
|
898
|
+
* @param {Boolean} [throwException] Set to `true` if you want to throw an exception in addition to the error event.
|
|
899
|
+
* @chainable
|
|
900
|
+
*/
|
|
901
|
+
WebWorker.prototype._triggerError = function (error, data, throwException) {
|
|
902
|
+
var errorEvent = null;
|
|
903
|
+
|
|
904
|
+
errorEvent = new $.Event(Event.ERROR);
|
|
905
|
+
errorEvent.message = this.getLastError();
|
|
906
|
+
errorEvent.errorData = data;
|
|
907
|
+
errorEvent.throwsException = !!throwException;
|
|
908
|
+
|
|
909
|
+
this.trigger(errorEvent);
|
|
910
|
+
return this;
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
/**
|
|
914
|
+
* Returns the last error that was trigger on this worker instance.
|
|
915
|
+
* @method getLastError
|
|
916
|
+
* @return {String} The last error message that was thrown on this worker instance.
|
|
917
|
+
*/
|
|
918
|
+
WebWorker.prototype.getLastError = function () {
|
|
919
|
+
return this._lastError;
|
|
920
|
+
};
|
|
921
|
+
|
|
922
|
+
|
|
923
|
+
// Static
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
* The last error encountered across all WebWorker instances.
|
|
927
|
+
* @property _lastError
|
|
928
|
+
* @private
|
|
929
|
+
* @static
|
|
930
|
+
* @type {String}
|
|
931
|
+
*/
|
|
932
|
+
WebWorker._lastError = null;
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* List of possible states the worker instance can be in. The worker instance
|
|
936
|
+
* can only be in one of these states at any given time.
|
|
937
|
+
* @property {Object} State
|
|
938
|
+
* @property {Number} State.INITIALIZED 0
|
|
939
|
+
* @property {Number} State.LOADING 1
|
|
940
|
+
* @property {Number} State.LOADED 2
|
|
941
|
+
* @property {Number} State.STARTING 3
|
|
942
|
+
* @property {Number} State.STARTED 4
|
|
943
|
+
* @property {Number} State.TERMINATING 5
|
|
944
|
+
* @property {Number} State.TERMINATED 6
|
|
945
|
+
*
|
|
946
|
+
* @static
|
|
947
|
+
*/
|
|
948
|
+
State = {
|
|
949
|
+
"INITIALIZED": 0,
|
|
950
|
+
"LOADING": 1,
|
|
951
|
+
"LOADED": 2,
|
|
952
|
+
"STARTING": 3,
|
|
953
|
+
"STARTED": 4,
|
|
954
|
+
"TERMINATING": 5,
|
|
955
|
+
"TERMINATED": 6
|
|
956
|
+
};
|
|
957
|
+
WebWorker.State = State;
|
|
958
|
+
|
|
959
|
+
/**
|
|
960
|
+
* List of pre-defined actions for the WebWorker instance.
|
|
961
|
+
*
|
|
962
|
+
* @property {Object} Action
|
|
963
|
+
* @property {String} Action.START 'start'
|
|
964
|
+
* @property {String} Action.TERMINATE 'terminate'
|
|
965
|
+
* @property {String} Action.TERMINATE_NOW 'terminateNow'
|
|
966
|
+
* @property {String} Action.TRIGGER 'trigger'
|
|
967
|
+
* @property {String} Action.TRIGGER_SELF 'triggerSelf'
|
|
968
|
+
*
|
|
969
|
+
* @static
|
|
970
|
+
*/
|
|
971
|
+
Action = {
|
|
972
|
+
"LOG": 'log',
|
|
973
|
+
"START": 'start',
|
|
974
|
+
"TERMINATE": 'terminate',
|
|
975
|
+
"TERMINATE_NOW": 'terminateNow',
|
|
976
|
+
"TRIGGER": 'trigger',
|
|
977
|
+
"TRIGGER_SELF": 'triggerSelf'
|
|
978
|
+
};
|
|
979
|
+
WebWorker.Action = Action;
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* List of pre-defined events for the WebWorker instance.
|
|
983
|
+
*
|
|
984
|
+
* @property {Object} Event
|
|
985
|
+
* @property {String} Event.INITIALIZED 'webworker:initialized'
|
|
986
|
+
* @property {String} Event.ERROR 'webworker:error'
|
|
987
|
+
* @property {String} Event.WORKER_LOADING 'webworker:worker-loading'
|
|
988
|
+
* @property {String} Event.WORKER_LOADED 'webworker:worker-loaded'
|
|
989
|
+
* @property {String} Event.WORKER_STARTING 'webworker:worker-starting'
|
|
990
|
+
* @property {String} Event.WORKER_STARTED 'webworker:worker-started'
|
|
991
|
+
* @property {String} Event.WORKER_TERMINATING 'webworker:worker-terminating'
|
|
992
|
+
* @property {String} Event.WORKER_TERMINATED 'webworker:worker-terminated'
|
|
993
|
+
*
|
|
994
|
+
* @static
|
|
995
|
+
*/
|
|
996
|
+
Event = {
|
|
997
|
+
"INITIALIZED": 'initialized',
|
|
998
|
+
"ERROR": 'error',
|
|
999
|
+
|
|
1000
|
+
"WORKER_LOADING": 'worker-loading',
|
|
1001
|
+
"WORKER_LOADED": 'worker-loaded',
|
|
1002
|
+
|
|
1003
|
+
"WORKER_STARTING": 'worker-starting',
|
|
1004
|
+
"WORKER_STARTED": 'worker-started',
|
|
1005
|
+
|
|
1006
|
+
"WORKER_TERMINATING": 'worker-terminating',
|
|
1007
|
+
"WORKER_TERMINATED": 'worker-terminated'
|
|
1008
|
+
};
|
|
1009
|
+
WebWorker.Event = Event;
|
|
1010
|
+
|
|
1011
|
+
/**
|
|
1012
|
+
* Reverse mapping of pre-defined events for faster lookup.
|
|
1013
|
+
* @property EventMap
|
|
1014
|
+
* @static
|
|
1015
|
+
* @type {Object}
|
|
1016
|
+
*/
|
|
1017
|
+
EventMap = {};
|
|
1018
|
+
WebWorker.EventMap = EventMap;
|
|
1019
|
+
|
|
1020
|
+
// Add eventPrefix to all event types
|
|
1021
|
+
for (key in Event) {
|
|
1022
|
+
Event[key] = eventPrefix + Event[key];
|
|
1023
|
+
EventMap[Event[key]] = key;
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
/**
|
|
1027
|
+
* Pre-defined list of errors for the WebWorker instance.
|
|
1028
|
+
*
|
|
1029
|
+
* @property {Object} Error
|
|
1030
|
+
* @property {String} Error.UNKNOWN "An unknown error occured."
|
|
1031
|
+
* @property {String} Error.INVALID_ARGUMENTS "Invalid arguments were supplied to this method."
|
|
1032
|
+
* @property {String} Error.WORKER_DID_NOT_LOAD "Unable to load worker."
|
|
1033
|
+
*
|
|
1034
|
+
* @static
|
|
1035
|
+
*/
|
|
1036
|
+
Error = {
|
|
1037
|
+
"UNKNOWN": "An unknown error occured.",
|
|
1038
|
+
"INVALID_ARGUMENTS": "Invalid arguments were supplied to this method.",
|
|
1039
|
+
"WORKER_DID_NOT_LOAD": "Unable to load worker."
|
|
1040
|
+
};
|
|
1041
|
+
WebWorker.Error = Error;
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* This is the worker script wrapper that is internally used by the base class
|
|
1045
|
+
* to establish communication from within the worker.
|
|
1046
|
+
* @property _workerScriptWrapper
|
|
1047
|
+
* @type {String}
|
|
1048
|
+
* @private
|
|
1049
|
+
*/
|
|
1050
|
+
WebWorker._workerScriptWrapper = 'var e=null,t=null,n=null,r={};e={{state-data}};t={{action-data}};n={{event-data}};self._callbackStack=null;self._listeners=r;self._isTerminating=false;self._state=null;self.State=e;self.Action=t;self.Event=n;self._assignEventHandlers=function(){function t(t){return function(){var n=self._callbackStack[t],r,i;r=t.toUpperCase();if(r in e){self._state=e[r]}while(i=n.pop()){i.apply(self,arguments)}}}self.on(n.WORKER_TERMINATING,t("terminating"));return self};self.getState=function(){return this._state};self.isInitialized=function(){var e=self.getState();return e!==null&&e>=0};self.isTerminating=function(){return self.getState()===e.TERMINATING};self._main=function(){var startArgs=arguments;{{main-function}};return self};self._init=function(){self._callbackStack={terminating:[]};self._assignEventHandlers();self._state=e.INITIALIZED;self.trigger(n.WORKER_LOADED);return self};self.start=function(){if(!self.isInitialized()){return self}self.triggerSelf(n.WORKER_STARTING);self._main.apply(self,arguments);self.triggerSelf(n.WORKER_STARTED);self.trigger(n.WORKER_STARTED);return self};self.log=function(e){self.sendMessage(t.LOG,[e]);return self};self.on=function(e,t){e+="";t=t||null;if(typeof t!=="function"){return self}if(!(e in r)){r[e]=[]}r[e].push(t);return self};self.one=function(e,t){var n=null;n=function(){t.apply(this,arguments);self.off(e,n);return};self.on(e,n);return};self.off=function(e,t){var n=null;e=e||null;t=t||null;if(e===null&&t===null){for(n in r){delete r[n]}self._assignEventHandlers();return self}self._removeListenerFromEventType(e,t);return self};self._removeListenerFromEventType=function(e,t){var n=r[e],i=0;t=t||null;if(t===null){r[e]=[];return self}for(;i<n.length;i++){if(n[i]===t){n.splice(i,1);i--}}return self};self.terminating=function(e){var t=self._callbackStack.terminating;if(typeof e==="function"){t.push(e)}return self};self.trigger=function(e,n){var r=null;e=e||null;if(e===null){return self}if(typeof e==="string"){r=e||null;e={type:r}}else if(typeof e==="object"){r=e.type||null;n=e.data}if(r===null){return self}e.data=n;self.sendMessage(t.TRIGGER_SELF,[e]);return self};self.triggerSelf=function(e,t){var n=null,i=null,s=null,o=null,u=0;e=e||null;if(e===null){return this}if(typeof e==="string"){n=e||null;e={type:e}}else if(typeof e==="object"){n=e.type||null;t=e.data}if(n===null){return this}e.data=t;i=r[n]||null;if(i===null){return this}s=i.length;for(u=0;u<s;u++){o=i[u];o.apply(this,[e]);if(s!==i.length){u--;s=i.length}}return this};self.sendMessage=function(e,t){var n=null;e=e||null;t=t||[];if(e===null){return self}n={__isWebWorkerMsg:true};n.action=e;n.args=t;self.postMessage(n);return self};self.terminate=function(e){e=!!e;if(!self.isTerminating()){self._setTerminatingStatus();self.triggerSelf(n.WORKER_TERMINATING);self.trigger(n.WORKER_TERMINATING)}self.sendMessage(t.TERMINATE_NOW,[]);if(e){self._nativeClose()}return self};self.terminateNow=function(){return self.terminate(true)};self._setTerminatingStatus=function(){self._state=e.TERMINATING;return self};self._nativeClose=self.close;self.close=self.terminate;self.addEventListener("message",function(e){var t=e.originalEvent||e,n=t.data,r=null,i=null;if(typeof n==="object"&&"__isWebWorkerMsg"in n&&n.__isWebWorkerMsg){r=n.action;i=n.args;self[r].apply(self,i)}},false);self._init()';
|
|
1051
|
+
|
|
1052
|
+
WebWorker._workerScriptWrapper = WebWorker._workerScriptWrapper.replace(/\{\{state-data\}\}/g, JSON.stringify(State))
|
|
1053
|
+
.replace(/\{\{action-data\}\}/g, JSON.stringify(Action))
|
|
1054
|
+
.replace(/\{\{event-data\}\}/g, JSON.stringify(Event));
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
/**
|
|
1058
|
+
* Retrieves the last error thrown by any WebWorker instance.
|
|
1059
|
+
* @method getLastError
|
|
1060
|
+
* @static
|
|
1061
|
+
* @return {String} The last error string thrown by any WebWorker instance.
|
|
1062
|
+
*/
|
|
1063
|
+
WebWorker.getLastError = WebWorker.prototype.getLastError;
|
|
1064
|
+
|
|
1065
|
+
/**
|
|
1066
|
+
* A jQuery-like method to assign the WebWorker class under a different context and className.
|
|
1067
|
+
* You may either provide the context and class name as params
|
|
1068
|
+
* OR use the return value to set it
|
|
1069
|
+
* OR both.
|
|
1070
|
+
* @method noConflict
|
|
1071
|
+
* @static
|
|
1072
|
+
* @param {Object} context The context to which the WebWorker instance needs to be associated.
|
|
1073
|
+
* @param {String} className The class name with which the WebWorker instance will be identified.
|
|
1074
|
+
* @return {String} The last error string thrown by any WebWorker instance.
|
|
1075
|
+
*/
|
|
1076
|
+
WebWorker.noConflict = function (context, className) {
|
|
1077
|
+
context = context || null;
|
|
1078
|
+
className = className || null;
|
|
1079
|
+
|
|
1080
|
+
if (defaultContext[defaultClassName] === WebWorker) {
|
|
1081
|
+
delete defaultContext[defaultClassName];
|
|
1082
|
+
if (_WebWorker) {
|
|
1083
|
+
defaultContext[defaultClassName] = _WebWorker;
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
if (context && className) {
|
|
1088
|
+
context[className] = WebWorker;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
return WebWorker;
|
|
1092
|
+
};
|
|
1093
|
+
|
|
1094
|
+
context[className] = WebWorker;
|
|
1095
|
+
|
|
1096
|
+
return;
|
|
1097
|
+
})(jQuery);
|