This repository has been archived by the owner on Mar 30, 2022. It is now read-only.
/
webworker-child.js
163 lines (136 loc) · 4.62 KB
/
webworker-child.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
// Launcher script for WebWorkers.
//
// Sets up context and runs a worker script. This is not intended to be
// invoked directly. Rather, it is invoked automatically when constructing a
// new Worker() object.
//
// usage: node worker.js <sock> <script>
//
// The <sock> parameter is the filesystem path to a UNIX domain socket
// that is listening for connections. The <script> parameter is the
// path to the JavaScript source to be executed as the body of the
// worker.
var assert = require('assert');
var fs = require('fs');
var net = require('net');
var path = require('path');
var script = process.binding('evals');
var sys = require('sys');
var wwutil = require('./webworker-util');
var writeError = process.binding('stdio').writeError;
// Catch exceptions
//
// This implements the Runtime Script Errors section fo the Web Workers API
// specification at
//
// http://www.whatwg.org/specs/web-workers/current-work/#runtime-script-errors
//
// XXX: There are all sorts of pieces of the error handling spec that are not
// being done correctly. Pick a clause, any clause.
var inErrorHandler = false;
var exceptionHandler = function(e) {
if (!inErrorHandler && workerCtx.onerror) {
inErrorHandler = true;
workerCtx.onerror(e);
inErrorHandler = false;
return;
}
// Don't bother setting inErrorHandler here, as we're already delivering
// the event to the master anyway
ms.send([wwutil.MSGTYPE_ERROR, {
'message' : wwutil.getErrorMessage(e),
'filename' : wwutil.getErrorFilename(e),
'lineno' : wwutil.getErrorLine(e)
}]);
};
// Message handling function for messages from the master
var handleMessage = function(msg, fd) {
if (!wwutil.isValidMessage(msg)) {
wwutil.debug(1, 'Received invalid message: ' + sys.inspect(msg));
return;
}
switch(msg[0]) {
case wwutil.MSGTYPE_NOOP:
break;
case wwutil.MSGTYPE_CLOSE:
// Conform to the Web Workers API for termination
workerCtx.closing = true;
// Close down the event sources that we know about
s.destroy();
// Request that the worker perform any application-level shutdown
if (workerCtx.onclose) {
workerCtx.onclose();
}
break;
case wwutil.MSGTYPE_USER:
// XXX: I have no idea what the event object here should really look
// like. I do know that it needs a 'data' elements, though.
if (workerCtx.onmessage) {
e = { data : msg[1] };
if (fd) {
e.fd = fd;
}
workerCtx.onmessage(e);
}
break;
default:
wwutil.debug(1, 'Received unexpected message: ' + sys.inspect(msg));
break;
}
};
if (process.argv.length < 4) {
throw new Error('usage: node worker.js <sock> <script>');
}
var sockPath = process.argv[2];
var scriptLoc = new wwutil.WorkerLocation(process.argv[3]);
// Connect to the parent process
var s = net.createConnection(sockPath);
var ms = new wwutil.MsgStream(s);
// Once we connect successfully, set up the rest of the world
s.addListener('connect', function() {
// When we receive a message from the master, react and possibly
// dispatch it to the worker context
ms.addListener('msg', handleMessage);
// Register for uncaught events for delivery to workerCtx.onerror
process.addListener('uncaughtException', exceptionHandler);
// Execute the worker
scriptObj.runInNewContext(workerCtx);
});
// Construt the Script object to host the worker's code
var scriptObj = undefined;
switch (scriptLoc.protocol) {
case 'file':
scriptObj = new script.Script(
fs.readFileSync(scriptLoc.pathname),
scriptLoc.href
);
break;
default:
writeError('Cannot load script from unknown protocol \'' +
scriptLoc.protocol);
process.exit(1);
}
// Set up the context for the worker instance
var workerCtx = {};
// Context elements required for node.js
//
// XXX: There must be a better way to do this.
workerCtx.global = workerCtx;
workerCtx.process = process;
workerCtx.require = require;
workerCtx.__filename = scriptLoc.pathname;
workerCtx.__dirname = path.dirname(scriptLoc.pathname);
workerCtx.setTimeout = setTimeout;
workerCtx.clearTimeout = clearTimeout;
workerCtx.setInterval = setInterval;
workerCtx.clearInterval = clearInterval;
// Context elements required by the WebWorkers API spec
workerCtx.postMessage = function(msg, fd) {
ms.send([wwutil.MSGTYPE_USER, msg], fd);
};
workerCtx.self = workerCtx;
workerCtx.location = scriptLoc;
workerCtx.closing = false;
workerCtx.close = function() {
process.exit(0);
};