1 | Function.prototype.$asyncbind = function $asyncbind(self, catcher) {
|
2 | "use strict";
|
3 |
|
4 | if (!Function.prototype.$asyncbind) {
|
5 | Object.defineProperty(Function.prototype, "$asyncbind", {
|
6 | value: $asyncbind,
|
7 | enumerable: false,
|
8 | configurable: true,
|
9 | writable: true
|
10 | });
|
11 | }
|
12 |
|
13 | if (!$asyncbind.trampoline) {
|
14 | $asyncbind.trampoline = function trampoline(t, x, s, e, u) {
|
15 | return function b(q) {
|
16 | while (q) {
|
17 | if (q.then) {
|
18 | q = q.then(b, e);
|
19 | return u ? undefined : q;
|
20 | }
|
21 |
|
22 | try {
|
23 | if (q.pop) {
|
24 | if (q.length) return q.pop() ? x.call(t) : q;
|
25 | q = s;
|
26 | } else q = q.call(t);
|
27 | } catch (r) {
|
28 | return e(r);
|
29 | }
|
30 | }
|
31 | };
|
32 | };
|
33 | }
|
34 |
|
35 | if (!$asyncbind.LazyThenable) {
|
36 | $asyncbind.LazyThenable = function () {
|
37 | function isThenable(obj) {
|
38 | return obj && obj instanceof Object && typeof obj.then === "function";
|
39 | }
|
40 |
|
41 | function resolution(p, r, how) {
|
42 | try {
|
43 | var x = how ? how(r) : r;
|
44 | if (p === x) return p.reject(new TypeError("Promise resolution loop"));
|
45 |
|
46 | if (isThenable(x)) {
|
47 | x.then(function (y) {
|
48 | resolution(p, y);
|
49 | }, function (e) {
|
50 | p.reject(e);
|
51 | });
|
52 | } else {
|
53 | p.resolve(x);
|
54 | }
|
55 | } catch (ex) {
|
56 | p.reject(ex);
|
57 | }
|
58 | }
|
59 |
|
60 | function Chained() {}
|
61 |
|
62 | ;
|
63 | Chained.prototype = {
|
64 | resolve: _unchained,
|
65 | reject: _unchained,
|
66 | then: thenChain
|
67 | };
|
68 |
|
69 | function _unchained(v) {}
|
70 |
|
71 | function thenChain(res, rej) {
|
72 | this.resolve = res;
|
73 | this.reject = rej;
|
74 | }
|
75 |
|
76 | function then(res, rej) {
|
77 | var chain = new Chained();
|
78 |
|
79 | try {
|
80 | this._resolver(function (value) {
|
81 | return isThenable(value) ? value.then(res, rej) : resolution(chain, value, res);
|
82 | }, function (ex) {
|
83 | resolution(chain, ex, rej);
|
84 | });
|
85 | } catch (ex) {
|
86 | resolution(chain, ex, rej);
|
87 | }
|
88 |
|
89 | return chain;
|
90 | }
|
91 |
|
92 | function Thenable(resolver) {
|
93 | this._resolver = resolver;
|
94 | this.then = then;
|
95 | }
|
96 |
|
97 | ;
|
98 |
|
99 | Thenable.resolve = function (v) {
|
100 | return Thenable.isThenable(v) ? v : {
|
101 | then: function then(resolve) {
|
102 | return resolve(v);
|
103 | }
|
104 | };
|
105 | };
|
106 |
|
107 | Thenable.isThenable = isThenable;
|
108 | return Thenable;
|
109 | }();
|
110 |
|
111 | $asyncbind.EagerThenable = $asyncbind.Thenable = ($asyncbind.EagerThenableFactory = function (tick) {
|
112 | tick = tick || typeof process === "object" && process.nextTick || typeof setImmediate === "function" && setImmediate || function (f) {
|
113 | setTimeout(f, 0);
|
114 | };
|
115 |
|
116 | var soon = function () {
|
117 | var fq = [],
|
118 | fqStart = 0,
|
119 | bufferSize = 1024;
|
120 |
|
121 | function callQueue() {
|
122 | while (fq.length - fqStart) {
|
123 | try {
|
124 | fq[fqStart]();
|
125 | } catch (ex) {}
|
126 |
|
127 | fq[fqStart++] = undefined;
|
128 |
|
129 | if (fqStart === bufferSize) {
|
130 | fq.splice(0, bufferSize);
|
131 | fqStart = 0;
|
132 | }
|
133 | }
|
134 | }
|
135 |
|
136 | return function (fn) {
|
137 | fq.push(fn);
|
138 | if (fq.length - fqStart === 1) tick(callQueue);
|
139 | };
|
140 | }();
|
141 |
|
142 | function Zousan(func) {
|
143 | if (func) {
|
144 | var me = this;
|
145 | func(function (arg) {
|
146 | me.resolve(arg);
|
147 | }, function (arg) {
|
148 | me.reject(arg);
|
149 | });
|
150 | }
|
151 | }
|
152 |
|
153 | Zousan.prototype = {
|
154 | resolve: function resolve(value) {
|
155 | if (this.state !== undefined) return;
|
156 | if (value === this) return this.reject(new TypeError("Attempt to resolve promise with self"));
|
157 | var me = this;
|
158 |
|
159 | if (value && (typeof value === "function" || typeof value === "object")) {
|
160 | try {
|
161 | var first = 0;
|
162 | var then = value.then;
|
163 |
|
164 | if (typeof then === "function") {
|
165 | then.call(value, function (ra) {
|
166 | if (!first++) {
|
167 | me.resolve(ra);
|
168 | }
|
169 | }, function (rr) {
|
170 | if (!first++) {
|
171 | me.reject(rr);
|
172 | }
|
173 | });
|
174 | return;
|
175 | }
|
176 | } catch (e) {
|
177 | if (!first) this.reject(e);
|
178 | return;
|
179 | }
|
180 | }
|
181 |
|
182 | this.state = STATE_FULFILLED;
|
183 | this.v = value;
|
184 | if (me.c) soon(function () {
|
185 | for (var n = 0, l = me.c.length; n < l; n++) STATE_FULFILLED(me.c[n], value);
|
186 | });
|
187 | },
|
188 | reject: function reject(reason) {
|
189 | if (this.state !== undefined) return;
|
190 | this.state = STATE_REJECTED;
|
191 | this.v = reason;
|
192 | var clients = this.c;
|
193 | if (clients) soon(function () {
|
194 | for (var n = 0, l = clients.length; n < l; n++) STATE_REJECTED(clients[n], reason);
|
195 | });
|
196 | },
|
197 | then: function then(onF, onR) {
|
198 | var p = new Zousan();
|
199 | var client = {
|
200 | y: onF,
|
201 | n: onR,
|
202 | p: p
|
203 | };
|
204 |
|
205 | if (this.state === undefined) {
|
206 | if (this.c) this.c.push(client);else this.c = [client];
|
207 | } else {
|
208 | var s = this.state,
|
209 | a = this.v;
|
210 | soon(function () {
|
211 | s(client, a);
|
212 | });
|
213 | }
|
214 |
|
215 | return p;
|
216 | }
|
217 | };
|
218 |
|
219 | function STATE_FULFILLED(c, arg) {
|
220 | if (typeof c.y === "function") {
|
221 | try {
|
222 | var yret = c.y.call(undefined, arg);
|
223 | c.p.resolve(yret);
|
224 | } catch (err) {
|
225 | c.p.reject(err);
|
226 | }
|
227 | } else c.p.resolve(arg);
|
228 | }
|
229 |
|
230 | function STATE_REJECTED(c, reason) {
|
231 | if (typeof c.n === "function") {
|
232 | try {
|
233 | var yret = c.n.call(undefined, reason);
|
234 | c.p.resolve(yret);
|
235 | } catch (err) {
|
236 | c.p.reject(err);
|
237 | }
|
238 | } else c.p.reject(reason);
|
239 | }
|
240 |
|
241 | Zousan.resolve = function (val) {
|
242 | if (val && val instanceof Zousan) return val;
|
243 | var z = new Zousan();
|
244 | z.resolve(val);
|
245 | return z;
|
246 | };
|
247 |
|
248 | Zousan.reject = function (err) {
|
249 | if (err && err instanceof Zousan) return err;
|
250 | var z = new Zousan();
|
251 | z.reject(err);
|
252 | return z;
|
253 | };
|
254 |
|
255 | Zousan.version = "2.3.3-nodent";
|
256 | return Zousan;
|
257 | })();
|
258 | }
|
259 |
|
260 | var resolver = this;
|
261 |
|
262 | switch (catcher) {
|
263 | case true:
|
264 | return new $asyncbind.Thenable(boundThen);
|
265 |
|
266 | case 0:
|
267 | return new $asyncbind.LazyThenable(boundThen);
|
268 |
|
269 | case undefined:
|
270 | boundThen.then = boundThen;
|
271 | return boundThen;
|
272 |
|
273 | default:
|
274 | return function () {
|
275 | try {
|
276 | return resolver.apply(self, arguments);
|
277 | } catch (ex) {
|
278 | return catcher(ex);
|
279 | }
|
280 | };
|
281 | }
|
282 |
|
283 | function boundThen() {
|
284 | return resolver.apply(self, arguments);
|
285 | }
|
286 | };
|
287 |
|
288 | const os = require("os");
|
289 |
|
290 | const fs = require("fs");
|
291 |
|
292 | const path = require("path");
|
293 |
|
294 | const ARSON = require("arson");
|
295 |
|
296 | const _require = require("child_process"),
|
297 | fork = _require.fork;
|
298 |
|
299 | const dargs = require("dargs");
|
300 |
|
301 | const Observable = require("zen-observable");
|
302 |
|
303 | const MemoryFilesystem = require("memory-fs");
|
304 |
|
305 | const crypto = require("crypto");
|
306 |
|
307 | const debug = require("util").debuglog("PATTERNPLATE");
|
308 |
|
309 | const resolvePkg = require("resolve-pkg");
|
310 |
|
311 | const OPTS = {
|
312 | stdio: ["pipe", "pipe", "pipe", "ipc"]
|
313 | };
|
314 |
|
315 | module.exports.createCompiler = function createCompiler({
|
316 | config,
|
317 | cwd,
|
318 | target = ""
|
319 | }) {
|
320 | return new Promise(function ($return, $error) {
|
321 | let worker;
|
322 |
|
323 | const send = payload => {
|
324 | if (!worker || !worker.send || !worker.connected) {
|
325 | return;
|
326 | }
|
327 |
|
328 | worker.send(ARSON.stringify(payload));
|
329 | };
|
330 |
|
331 | let watching = false;
|
332 | const queue = [];
|
333 | let listeners = [];
|
334 |
|
335 | const next = message => listeners.forEach(listener => listener.next(message));
|
336 |
|
337 | const start = () => {
|
338 | const workerPath = path.join(__dirname, "compiler-worker.js");
|
339 | debug(`starting compiler worker at ${workerPath}`);
|
340 | const cp = fork(workerPath, dargs({
|
341 | cwd,
|
342 | target,
|
343 | config: ARSON.stringify(config)
|
344 | }), OPTS);
|
345 | let stderr = ``;
|
346 | let stdout = ``;
|
347 | cp.stdout.pipe(process.stdout);
|
348 | cp.stderr.pipe(process.stderr);
|
349 | cp.once("close", code => {
|
350 | if (code !== 0) {
|
351 | queue.unshift({
|
352 | type: "exception",
|
353 | payload: {
|
354 | code,
|
355 | stdout,
|
356 | stderr: [`Could not start compiler worker for "${target}"`, stderr].join("\n")
|
357 | }
|
358 | });
|
359 | next(queue);
|
360 | }
|
361 | });
|
362 | return cp;
|
363 | };
|
364 |
|
365 | worker = start();
|
366 | setInterval(() => send({
|
367 | type: "heartbeat"
|
368 | }), 500);
|
369 |
|
370 | const onMessage = envelope => {
|
371 | const _ARSON$parse = ARSON.parse(envelope),
|
372 | type = _ARSON$parse.type,
|
373 | target = _ARSON$parse.target,
|
374 | payload = _ARSON$parse.payload;
|
375 |
|
376 | switch (type) {
|
377 | case "ready":
|
378 | return send({
|
379 | type: "start"
|
380 | });
|
381 |
|
382 | case "done":
|
383 | {
|
384 | debug({
|
385 | type,
|
386 | target
|
387 | });
|
388 | const fs = new MemoryFilesystem(payload);
|
389 | queue.unshift({
|
390 | type,
|
391 | target,
|
392 | payload: {
|
393 | fs
|
394 | }
|
395 | });
|
396 | return next(queue);
|
397 | }
|
398 |
|
399 | case "start":
|
400 | debug({
|
401 | type,
|
402 | target
|
403 | });
|
404 | queue.unshift({
|
405 | type,
|
406 | target,
|
407 | payload
|
408 | });
|
409 | return next(queue);
|
410 |
|
411 | case "error":
|
412 | if (Array.isArray(payload)) {
|
413 | return payload.forEach(p => console.error(p.message));
|
414 | }
|
415 |
|
416 | return console.error(payload.message);
|
417 |
|
418 | case "shutdown":
|
419 | debug({
|
420 | type,
|
421 | target
|
422 | });
|
423 | send({
|
424 | type: "stop"
|
425 | });
|
426 | worker = start();
|
427 | worker.on("message", onMessage);
|
428 |
|
429 | if (watching) {
|
430 | send({
|
431 | type: "watch"
|
432 | });
|
433 | }
|
434 |
|
435 | }
|
436 | };
|
437 |
|
438 | worker.on("message", onMessage);
|
439 | const observable = new Observable(observer => {
|
440 | if (!watching) {
|
441 | watching = true;
|
442 | send({
|
443 | type: "watch"
|
444 | });
|
445 | }
|
446 |
|
447 | listeners.push(observer);
|
448 | return () => {
|
449 | listeners = listeners.filter(listener => listener !== observer);
|
450 | };
|
451 | });
|
452 | observable.queue = queue;
|
453 |
|
454 | observable.stop = () => {
|
455 | send({
|
456 | type: "stop"
|
457 | });
|
458 | };
|
459 |
|
460 | return $return(observable);
|
461 | }.$asyncbind(this));
|
462 | };
|
463 |
|
\ | No newline at end of file |