-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathworker-boot.js
167 lines (115 loc) · 4.17 KB
/
worker-boot.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
// This code is run first in the shared web worker environment.
(function () {
var global = self;
var WebWorker = {};
global.WebWorker = WebWorker;
WebWorker.id = (''+Math.random()).substr(2);
// List of ports from browser windows connecting to us.
WebWorker.ports = [];
// List of the windowId of each window connecting to us, in the same
// order as the ports list.
WebWorker.windowIds = [];
// There's no console log in the shared web worker environment, so
// we'll have Meteor._debug call the log function here.
// Store any startup errors or debug messages until we have a
// connection from a window to pass the log messages to. Make
// global because sometimes it can be helpful to be able to view in
// the browser debugger if startup errors prevent getting to the
// point of listening to window connections.
WebWorker.logs = [];
// Log a debug message. Pass on to connected windows if we have any
// yet, otherwise store in `logs` until we have a connection.
WebWorker.log = function (msg) {
if (WebWorker.ports.length > 0) {
for (var i = 0; i < WebWorker.ports.length; ++i) {
WebWorker.ports[i].postMessage({msg: 'log', log: [msg]});
}
}
else {
WebWorker.logs.push(msg);
}
};
// Handle uncaught exceptions.
// https://developer.mozilla.org/en-US/docs/Web/API/window.onerror
global.onerror = function(errorMessage, url, lineNumber) {
WebWorker.log("error: " + errorMessage + " " + url + ":" + lineNumber);
};
// Call `fn`, and log any uncaught exceptions thrown.
// var catcherr = function (fn) {
// try {
// return fn();
// }
// catch (error) {
// log("error: " + (error != null ? error.stack : ''));
// }
// };
// Handlers for messages from windows.
// msg -> handler
var messageHandlers = {};
WebWorker.addMessageHandler = function (msg, callback) {
messageHandlers[msg] = callback;
};
// Not dynamically including the Meteor runtime config in this
// JavaScript source allows it to be served statically. Instead,
// connecting windows send a "boot" message with the config, and we
// delay loading the package code until we get the config.
var booted = false;
WebWorker.addMessageHandler('boot', function (port, data) {
var i = WebWorker.ports.indexOf(port);
if (i !== -1)
WebWorker.windowIds[i] = data.windowId;
if (booted)
return;
global.__meteor_runtime_config__ = data.__meteor_runtime_config__;
// We will at least hear about syntax errors now because of the
// onerror handler above, but there doesn't seem to be a way to
// get the line number of the syntax error (the lineNumber
// reported is the this importScripts line here, not the line of
// the syntax error).
importScripts(
__meteor_runtime_config__.offlineDataWorker.urls['worker-packages.js']
);
booted = true;
Package.meteor.Meteor._start();
});
// Incoming message from a window.
var onmessage = function (port, event) {
var data = event.data;
if (WebWorker.ports.indexOf(port) === -1) {
WebWorker.log(
'Message ' + data.msg + ' received from "dead" window: ' +
data.windowId
);
return;
}
var handler = messageHandlers[data.msg];
if (handler) {
handler(port, data);
}
else {
WebWorker.log("Error: Unknown message type: " + data.msg);
}
};
global.onconnect = function (event) {
var port = event.ports[0];
if (WebWorker.logs.length > 0) {
port.postMessage({log: WebWorker.logs});
WebWorker.logs = [];
}
port.onmessage = function (event) {
onmessage(port, event);
};
WebWorker.ports.push(port);
};
// Weirdly, shared web workers have no way of detecting when the
// windows they're communicating with have closed. (!) We make
// do by pinging windows to see if they're still alive, and
// `windowIsDead` here gets called when we don't get a response.
WebWorker.windowIsDead = function (windowId) {
var i = WebWorker.windowIds.indexOf(windowId);
if (i !== -1) {
WebWorker.ports.splice(i, 1);
WebWorker.windowIds.splice(i, 1);
}
};
})();