UNPKG

14.4 kBJavaScriptView Raw
1(function(
2 // Reliable reference to the global object (i.e. window in browsers).
3 global,
4
5 // Dummy constructor that we use as the .constructor property for
6 // functions that return Generator objects.
7 GeneratorFunction,
8
9 // Undefined value, more compressible than void 0.
10 undefined
11) {
12 var hasOwn = Object.prototype.hasOwnProperty;
13
14 if (global.wrapGenerator) {
15 return;
16 }
17
18 function wrapGenerator(innerFn, self, tryList) {
19 return new Generator(innerFn, self || null, tryList || []);
20 }
21
22 global.wrapGenerator = wrapGenerator;
23 if (typeof exports !== "undefined") {
24 exports.wrapGenerator = wrapGenerator;
25 }
26
27 var GenStateSuspendedStart = "suspendedStart";
28 var GenStateSuspendedYield = "suspendedYield";
29 var GenStateExecuting = "executing";
30 var GenStateCompleted = "completed";
31
32 // Returning this object from the innerFn has the same effect as
33 // breaking out of the dispatch switch statement.
34 var ContinueSentinel = {};
35
36 wrapGenerator.mark = function(genFun) {
37 genFun.constructor = GeneratorFunction;
38 return genFun;
39 };
40
41 // Ensure isGeneratorFunction works when Function#name not supported.
42 if (GeneratorFunction.name !== "GeneratorFunction") {
43 GeneratorFunction.name = "GeneratorFunction";
44 }
45
46 wrapGenerator.isGeneratorFunction = function(genFun) {
47 var ctor = genFun && genFun.constructor;
48 return ctor ? GeneratorFunction.name === ctor.name : false;
49 };
50
51 function Generator(innerFn, self, tryList) {
52 var generator = this;
53 var context = new Context(tryList);
54 var state = GenStateSuspendedStart;
55
56 function invoke(method, arg) {
57 if (state === GenStateExecuting) {
58 throw new Error("Generator is already running");
59 }
60
61 if (state === GenStateCompleted) {
62 throw new Error("Generator has already finished");
63 }
64
65 while (true) {
66 var delegate = context.delegate;
67 if (delegate) {
68 try {
69 var info = delegate.generator[method](arg);
70
71 // Delegate generator ran and handled its own exceptions so
72 // regardless of what the method was, we continue as if it is
73 // "next" with an undefined arg.
74 method = "next";
75 arg = undefined;
76
77 } catch (uncaught) {
78 context.delegate = null;
79
80 // Like returning generator.throw(uncaught), but without the
81 // overhead of an extra function call.
82 method = "throw";
83 arg = uncaught;
84
85 continue;
86 }
87
88 if (info.done) {
89 context[delegate.resultName] = info.value;
90 context.next = delegate.nextLoc;
91 } else {
92 state = GenStateSuspendedYield;
93 return info;
94 }
95
96 context.delegate = null;
97 }
98
99 if (method === "next") {
100 if (state === GenStateSuspendedStart &&
101 typeof arg !== "undefined") {
102 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume
103 throw new TypeError(
104 "attempt to send " + JSON.stringify(arg) + " to newborn generator"
105 );
106 }
107
108 if (state === GenStateSuspendedYield) {
109 context.sent = arg;
110 } else {
111 delete context.sent;
112 }
113
114 } else if (method === "throw") {
115 if (state === GenStateSuspendedStart) {
116 state = GenStateCompleted;
117 throw arg;
118 }
119
120 if (context.dispatchException(arg)) {
121 // If the dispatched exception was caught by a catch block,
122 // then let that catch block handle the exception normally.
123 method = "next";
124 arg = undefined;
125 }
126 }
127
128 state = GenStateExecuting;
129
130 try {
131 var value = innerFn.call(self, context);
132
133 // If an exception is thrown from innerFn, we leave state ===
134 // GenStateExecuting and loop back for another invocation.
135 state = context.done
136 ? GenStateCompleted
137 : GenStateSuspendedYield;
138
139 var info = {
140 value: value,
141 done: context.done
142 };
143
144 if (value === ContinueSentinel) {
145 if (context.delegate && method === "next") {
146 // Deliberately forget the last sent value so that we don't
147 // accidentally pass it on to the delegate.
148 arg = undefined;
149 }
150 } else {
151 return info;
152 }
153
154 } catch (thrown) {
155 state = GenStateCompleted;
156
157 if (method === "next") {
158 context.dispatchException(thrown);
159 } else {
160 arg = thrown;
161 }
162 }
163 }
164 }
165
166 generator.next = invoke.bind(generator, "next");
167 generator.throw = invoke.bind(generator, "throw");
168 }
169
170 Generator.prototype.toString = function() {
171 return "[object Generator]";
172 };
173
174 function pushTryEntry(triple) {
175 var entry = { tryLoc: triple[0] };
176
177 if (1 in triple) {
178 entry.catchLoc = triple[1];
179 }
180
181 if (2 in triple) {
182 entry.finallyLoc = triple[2];
183 }
184
185 this.tryEntries.push(entry);
186 }
187
188 function resetTryEntry(entry, i) {
189 var record = entry.completion || {};
190 record.type = i === 0 ? "normal" : "return";
191 delete record.arg;
192 entry.completion = record;
193 }
194
195 function Context(tryList) {
196 // The root entry object (effectively a try statement without a catch
197 // or a finally block) gives us a place to store values thrown from
198 // locations where there is no enclosing try statement.
199 this.tryEntries = [{ tryLoc: "root" }];
200 tryList.forEach(pushTryEntry, this);
201 this.reset();
202 }
203
204 Context.prototype = {
205 constructor: Context,
206
207 reset: function() {
208 this.prev = 0;
209 this.next = 0;
210 this.sent = undefined;
211 this.done = false;
212 this.delegate = null;
213
214 this.tryEntries.forEach(resetTryEntry);
215
216 // Pre-initialize at least 20 temporary variables to enable hidden
217 // class optimizations for simple generators.
218 for (var tempIndex = 0, tempName;
219 hasOwn.call(this, tempName = "t" + tempIndex) || tempIndex < 20;
220 ++tempIndex) {
221 this[tempName] = null;
222 }
223 },
224
225 stop: function() {
226 this.done = true;
227
228 var rootEntry = this.tryEntries[0];
229 var rootRecord = rootEntry.completion;
230 if (rootRecord.type === "throw") {
231 throw rootRecord.arg;
232 }
233
234 return this.rval;
235 },
236
237 keys: function(object) {
238 var keys = [];
239 for (var key in object) {
240 keys.push(key);
241 }
242 keys.reverse();
243
244 // Rather than returning an object with a next method, we keep
245 // things simple and return the next function itself.
246 return function next() {
247 while (keys.length) {
248 var key = keys.pop();
249 if (key in object) {
250 next.value = key;
251 next.done = false;
252 return next;
253 }
254 }
255
256 // To avoid creating an additional object, we just hang the .value
257 // and .done properties off the next function object itself. This
258 // also ensures that the minifier will not anonymize the function.
259 next.done = true;
260 return next;
261 };
262 },
263
264 dispatchException: function(exception) {
265 if (this.done) {
266 throw exception;
267 }
268
269 var context = this;
270 function handle(loc, caught) {
271 record.type = "throw";
272 record.arg = exception;
273 context.next = loc;
274 return !!caught;
275 }
276
277 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
278 var entry = this.tryEntries[i];
279 var record = entry.completion;
280
281 if (entry.tryLoc === "root") {
282 // Exception thrown outside of any try block that could handle
283 // it, so set the completion value of the entire function to
284 // throw the exception.
285 return handle("end");
286 }
287
288 if (entry.tryLoc <= this.prev) {
289 var hasCatch = hasOwn.call(entry, "catchLoc");
290 var hasFinally = hasOwn.call(entry, "finallyLoc");
291
292 if (hasCatch && hasFinally) {
293 if (this.prev < entry.catchLoc) {
294 return handle(entry.catchLoc, true);
295 } else if (this.prev < entry.finallyLoc) {
296 return handle(entry.finallyLoc);
297 }
298
299 } else if (hasCatch) {
300 if (this.prev < entry.catchLoc) {
301 return handle(entry.catchLoc, true);
302 }
303
304 } else if (hasFinally) {
305 if (this.prev < entry.finallyLoc) {
306 return handle(entry.finallyLoc);
307 }
308
309 } else {
310 throw new Error("try statement without catch or finally");
311 }
312 }
313 }
314 },
315
316 _findFinallyEntry: function(finallyLoc) {
317 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
318 var entry = this.tryEntries[i];
319 if (entry.tryLoc <= this.prev &&
320 hasOwn.call(entry, "finallyLoc") && (
321 entry.finallyLoc === finallyLoc ||
322 this.prev < entry.finallyLoc)) {
323 return entry;
324 }
325 }
326 },
327
328 abrupt: function(type, arg) {
329 var entry = this._findFinallyEntry();
330 var record = entry ? entry.completion : {};
331
332 record.type = type;
333 record.arg = arg;
334
335 if (entry) {
336 this.next = entry.finallyLoc;
337 } else {
338 this.complete(record);
339 }
340
341 return ContinueSentinel;
342 },
343
344 complete: function(record) {
345 if (record.type === "throw") {
346 throw record.arg;
347 }
348
349 if (record.type === "break" ||
350 record.type === "continue") {
351 this.next = record.arg;
352 } else if (record.type === "return") {
353 this.rval = record.arg;
354 this.next = "end";
355 }
356
357 return ContinueSentinel;
358 },
359
360 finish: function(finallyLoc) {
361 var entry = this._findFinallyEntry(finallyLoc);
362 return this.complete(entry.completion);
363 },
364
365 "catch": function(tryLoc) {
366 for (var i = this.tryEntries.length - 1; i >= 0; --i) {
367 var entry = this.tryEntries[i];
368 if (entry.tryLoc === tryLoc) {
369 var record = entry.completion;
370 if (record.type === "throw") {
371 var thrown = record.arg;
372 resetTryEntry(entry, i);
373 }
374 return thrown;
375 }
376 }
377
378 // The context.catch method must only be called with a location
379 // argument that corresponds to a known catch block.
380 throw new Error("illegal catch attempt");
381 },
382
383 delegateYield: function(generator, resultName, nextLoc) {
384 this.delegate = {
385 generator: generator,
386 resultName: resultName,
387 nextLoc: nextLoc
388 };
389
390 return ContinueSentinel;
391 }
392 };
393}).apply(this, Function("return [this, function GeneratorFunction(){}]")());
394
395var fs = require('graceful-fs')
396
397/**
398 * Check if a file exists. Throws if it does not.
399 * Mostly just for a nicer error message.
400 *
401 * @param {String} filename
402 * @return {Object}
403 * @api public
404 */;
405
406/**
407 * Check if a file exists. Throws if it does not.
408 * Mostly just for a nicer error message.
409 *
410 * @param {String} filename
411 * @return {Object}
412 * @api public
413 */
414
415exports.exists = wrapGenerator.mark(function(filename) {
416 return wrapGenerator(function($ctx0) {
417 while (1) switch ($ctx0.prev = $ctx0.next) {
418 case 0:
419 $ctx0.prev = 0;
420 $ctx0.next = 3;
421 return fs.stat.bind(null, filename);
422 case 3:
423 return $ctx0.abrupt("return", $ctx0.sent);
424 case 6:
425 $ctx0.prev = 6;
426 $ctx0.t0 = $ctx0.catch(0);
427
428 if (!($ctx0.t0.code === 'ENOENT')) {
429 $ctx0.next = 10;
430 break;
431 }
432
433 throw new Error('file "' + filename + '" does not exist.');
434 case 10:
435 throw $ctx0.t0;
436 case 11:
437 case "end":
438 return $ctx0.stop();
439 }
440 }, this, [[0, 6]]);
441})
442
443/**
444 * Unlink a file. Ignores errors incase it doesn't exist.
445 *
446 * @param {String} filename
447 * @api public
448 */;
449
450/**
451 * Unlink a file. Ignores errors incase it doesn't exist.
452 *
453 * @param {String} filename
454 * @api public
455 */
456
457exports.unlink = wrapGenerator.mark(function(filename) {
458 return wrapGenerator(function($ctx1) {
459 while (1) switch ($ctx1.prev = $ctx1.next) {
460 case 0:
461 $ctx1.prev = 0;
462 $ctx1.next = 3;
463 return fs.unlink.bind(null, filename);
464 case 3:
465 $ctx1.next = 10;
466 break;
467 case 5:
468 $ctx1.prev = 5;
469 $ctx1.t1 = $ctx1.catch(0);
470
471 if (!($ctx1.t1.code === 'ENOENT')) {
472 $ctx1.next = 9;
473 break;
474 }
475
476 return $ctx1.abrupt("return");
477 case 9:
478 throw $ctx1.t1;
479 case 10:
480 case "end":
481 return $ctx1.stop();
482 }
483 }, this, [[0, 5]]);
484})
485
486/**
487 * This is how the url rewriter and file copy/symlink will rewrite the file names.
488 * This will create names like github's with `/`s.
489 * i.e. fortawesome/fontawesome/v4.0.3/fonts/font.woff
490 * and, for local components, lib/my-local-component/image.png
491 *
492 * @param {Object} branch
493 * @return {String}
494 * @api public
495 */;
496
497/**
498 * This is how the url rewriter and file copy/symlink will rewrite the file names.
499 * This will create names like github's with `/`s.
500 * i.e. fortawesome/fontawesome/v4.0.3/fonts/font.woff
501 * and, for local components, lib/my-local-component/image.png
502 *
503 * @param {Object} branch
504 * @return {String}
505 * @api public
506 */
507
508exports.rewriteUrl = function (branch) {
509 if (branch.type === 'local') return branch.relativePath || branch.name;
510 if (branch.type === 'dependency') return branch.name + '/' + branch.ref;
511}
512
513/**
514 * Strip leading `./` from filenames.
515 *
516 * @param {String} filename
517 * @return {String}
518 * @api public
519 */;
520
521/**
522 * Strip leading `./` from filenames.
523 *
524 * @param {String} filename
525 * @return {String}
526 * @api public
527 */
528
529exports.stripLeading = function (x) {
530 if (x.slice(0, 2) === './') return x.slice(2);
531 return x;
532}
533
534/**
535 * Check if an object is a Generator Function.
536 *
537 * @param {Object} obj
538 * @return {Boolean}
539 * @api private
540 */;
541
542/**
543 * Check if an object is a Generator Function.
544 *
545 * @param {Object} obj
546 * @return {Boolean}
547 * @api private
548 */
549
550exports.isGeneratorFunction = function (obj) {
551 return obj
552 && obj.constructor
553 && 'GeneratorFunction' === obj.constructor.name;
554}