macgyver 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +45 -0
  6. data/Rakefile +1 -0
  7. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Growl +0 -0
  8. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Growl +0 -0
  9. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/Growl.h +5 -0
  10. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h +551 -0
  11. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Headers/GrowlDefines.h +341 -0
  12. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/Resources/Info.plist +40 -0
  13. data/assets/MacGap.app/Contents/Frameworks/Growl.framework/Versions/A/_CodeSignature/CodeResources +34 -0
  14. data/assets/MacGap.app/Contents/Info.plist +48 -0
  15. data/assets/MacGap.app/Contents/MacOS/MacGap +0 -0
  16. data/assets/MacGap.app/Contents/PkgInfo +1 -0
  17. data/assets/MacGap.app/Contents/Resources/_debugger.js +1718 -0
  18. data/assets/MacGap.app/Contents/Resources/_http_agent.js +310 -0
  19. data/assets/MacGap.app/Contents/Resources/_http_client.js +533 -0
  20. data/assets/MacGap.app/Contents/Resources/_http_common.js +222 -0
  21. data/assets/MacGap.app/Contents/Resources/_http_incoming.js +194 -0
  22. data/assets/MacGap.app/Contents/Resources/_http_outgoing.js +597 -0
  23. data/assets/MacGap.app/Contents/Resources/_http_server.js +510 -0
  24. data/assets/MacGap.app/Contents/Resources/_linklist.js +76 -0
  25. data/assets/MacGap.app/Contents/Resources/_stream_duplex.js +69 -0
  26. data/assets/MacGap.app/Contents/Resources/_stream_passthrough.js +41 -0
  27. data/assets/MacGap.app/Contents/Resources/_stream_readable.js +900 -0
  28. data/assets/MacGap.app/Contents/Resources/_stream_transform.js +204 -0
  29. data/assets/MacGap.app/Contents/Resources/_stream_writable.js +456 -0
  30. data/assets/MacGap.app/Contents/Resources/_tls_legacy.js +887 -0
  31. data/assets/MacGap.app/Contents/Resources/_tls_wrap.js +831 -0
  32. data/assets/MacGap.app/Contents/Resources/application.icns +0 -0
  33. data/assets/MacGap.app/Contents/Resources/assert.js +326 -0
  34. data/assets/MacGap.app/Contents/Resources/buffer.js +724 -0
  35. data/assets/MacGap.app/Contents/Resources/child_process.js +1107 -0
  36. data/assets/MacGap.app/Contents/Resources/cluster.js +613 -0
  37. data/assets/MacGap.app/Contents/Resources/console.js +108 -0
  38. data/assets/MacGap.app/Contents/Resources/constants.js +22 -0
  39. data/assets/MacGap.app/Contents/Resources/crypto.js +691 -0
  40. data/assets/MacGap.app/Contents/Resources/dgram.js +459 -0
  41. data/assets/MacGap.app/Contents/Resources/dns.js +274 -0
  42. data/assets/MacGap.app/Contents/Resources/domain.js +292 -0
  43. data/assets/MacGap.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  44. data/assets/MacGap.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  45. data/assets/MacGap.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  46. data/assets/MacGap.app/Contents/Resources/en.lproj/Window.nib +0 -0
  47. data/assets/MacGap.app/Contents/Resources/events.js +312 -0
  48. data/assets/MacGap.app/Contents/Resources/freelist.js +43 -0
  49. data/assets/MacGap.app/Contents/Resources/fs.js +1732 -0
  50. data/assets/MacGap.app/Contents/Resources/http.js +119 -0
  51. data/assets/MacGap.app/Contents/Resources/https.js +134 -0
  52. data/assets/MacGap.app/Contents/Resources/module.js +529 -0
  53. data/assets/MacGap.app/Contents/Resources/net.js +1378 -0
  54. data/assets/MacGap.app/Contents/Resources/nodelike.js +195 -0
  55. data/assets/MacGap.app/Contents/Resources/os.js +64 -0
  56. data/assets/MacGap.app/Contents/Resources/path.js +517 -0
  57. data/assets/MacGap.app/Contents/Resources/public/index.html +38 -0
  58. data/assets/MacGap.app/Contents/Resources/punycode.js +507 -0
  59. data/assets/MacGap.app/Contents/Resources/querystring.js +206 -0
  60. data/assets/MacGap.app/Contents/Resources/readline.js +1311 -0
  61. data/assets/MacGap.app/Contents/Resources/repl.js +945 -0
  62. data/assets/MacGap.app/Contents/Resources/smalloc.js +90 -0
  63. data/assets/MacGap.app/Contents/Resources/stream.js +127 -0
  64. data/assets/MacGap.app/Contents/Resources/string_decoder.js +189 -0
  65. data/assets/MacGap.app/Contents/Resources/sys.js +24 -0
  66. data/assets/MacGap.app/Contents/Resources/timers.js +568 -0
  67. data/assets/MacGap.app/Contents/Resources/tls.js +220 -0
  68. data/assets/MacGap.app/Contents/Resources/tty.js +129 -0
  69. data/assets/MacGap.app/Contents/Resources/url.js +693 -0
  70. data/assets/MacGap.app/Contents/Resources/util.js +688 -0
  71. data/assets/MacGap.app/Contents/Resources/vm.js +73 -0
  72. data/assets/MacGap.app/Contents/Resources/zlib.js +524 -0
  73. data/assets/index.html +38 -0
  74. data/bin/macgyver +104 -0
  75. data/macgyver.gemspec +19 -0
  76. data/test/public/index.html +27 -0
  77. metadata +121 -0
@@ -0,0 +1,76 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ function init(list) {
23
+ list._idleNext = list;
24
+ list._idlePrev = list;
25
+ }
26
+ exports.init = init;
27
+
28
+
29
+ // show the most idle item
30
+ function peek(list) {
31
+ if (list._idlePrev == list) return null;
32
+ return list._idlePrev;
33
+ }
34
+ exports.peek = peek;
35
+
36
+
37
+ // remove the most idle item from the list
38
+ function shift(list) {
39
+ var first = list._idlePrev;
40
+ remove(first);
41
+ return first;
42
+ }
43
+ exports.shift = shift;
44
+
45
+
46
+ // remove a item from its list
47
+ function remove(item) {
48
+ if (item._idleNext) {
49
+ item._idleNext._idlePrev = item._idlePrev;
50
+ }
51
+
52
+ if (item._idlePrev) {
53
+ item._idlePrev._idleNext = item._idleNext;
54
+ }
55
+
56
+ item._idleNext = null;
57
+ item._idlePrev = null;
58
+ }
59
+ exports.remove = remove;
60
+
61
+
62
+ // remove a item from its list and place at the end.
63
+ function append(list, item) {
64
+ remove(item);
65
+ item._idleNext = list._idleNext;
66
+ list._idleNext._idlePrev = item;
67
+ item._idlePrev = list;
68
+ list._idleNext = item;
69
+ }
70
+ exports.append = append;
71
+
72
+
73
+ function isEmpty(list) {
74
+ return list._idleNext === list;
75
+ }
76
+ exports.isEmpty = isEmpty;
@@ -0,0 +1,69 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ // a duplex stream is just a stream that is both readable and writable.
23
+ // Since JS doesn't have multiple prototypal inheritance, this class
24
+ // prototypally inherits from Readable, and then parasitically from
25
+ // Writable.
26
+
27
+ module.exports = Duplex;
28
+ var util = require('util');
29
+ var Readable = require('_stream_readable');
30
+ var Writable = require('_stream_writable');
31
+
32
+ util.inherits(Duplex, Readable);
33
+
34
+ Object.keys(Writable.prototype).forEach(function(method) {
35
+ if (!Duplex.prototype[method])
36
+ Duplex.prototype[method] = Writable.prototype[method];
37
+ });
38
+
39
+ function Duplex(options) {
40
+ if (!(this instanceof Duplex))
41
+ return new Duplex(options);
42
+
43
+ Readable.call(this, options);
44
+ Writable.call(this, options);
45
+
46
+ if (options && options.readable === false)
47
+ this.readable = false;
48
+
49
+ if (options && options.writable === false)
50
+ this.writable = false;
51
+
52
+ this.allowHalfOpen = true;
53
+ if (options && options.allowHalfOpen === false)
54
+ this.allowHalfOpen = false;
55
+
56
+ this.once('end', onend);
57
+ }
58
+
59
+ // the no-half-open enforcer
60
+ function onend() {
61
+ // if we allow half-open state, or if the writable side ended,
62
+ // then we're ok.
63
+ if (this.allowHalfOpen || this._writableState.ended)
64
+ return;
65
+
66
+ // no more data can be written.
67
+ // But allow more writes to happen in this tick.
68
+ process.nextTick(this.end.bind(this));
69
+ }
@@ -0,0 +1,41 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ // a passthrough stream.
23
+ // basically just the most minimal sort of Transform stream.
24
+ // Every written chunk gets output as-is.
25
+
26
+ module.exports = PassThrough;
27
+
28
+ var Transform = require('_stream_transform');
29
+ var util = require('util');
30
+ util.inherits(PassThrough, Transform);
31
+
32
+ function PassThrough(options) {
33
+ if (!(this instanceof PassThrough))
34
+ return new PassThrough(options);
35
+
36
+ Transform.call(this, options);
37
+ }
38
+
39
+ PassThrough.prototype._transform = function(chunk, encoding, cb) {
40
+ cb(null, chunk);
41
+ };
@@ -0,0 +1,900 @@
1
+ // Copyright Joyent, Inc. and other Node contributors.
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining a
4
+ // copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ // persons to whom the Software is furnished to do so, subject to the
9
+ // following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be included
12
+ // in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ module.exports = Readable;
23
+ Readable.ReadableState = ReadableState;
24
+
25
+ var EE = require('events').EventEmitter;
26
+ var Stream = require('stream');
27
+ var util = require('util');
28
+ var StringDecoder;
29
+ var debug = util.debuglog('stream');
30
+
31
+ util.inherits(Readable, Stream);
32
+
33
+ function ReadableState(options, stream) {
34
+ options = options || {};
35
+
36
+ // the point at which it stops calling _read() to fill the buffer
37
+ // Note: 0 is a valid value, means "don't call _read preemptively ever"
38
+ var hwm = options.highWaterMark;
39
+ var defaultHwm = options.objectMode ? 16 : 16 * 1024;
40
+ this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
41
+
42
+ // cast to ints.
43
+ this.highWaterMark = ~~this.highWaterMark;
44
+
45
+ this.buffer = [];
46
+ this.length = 0;
47
+ this.pipes = null;
48
+ this.pipesCount = 0;
49
+ this.flowing = null;
50
+ this.ended = false;
51
+ this.endEmitted = false;
52
+ this.reading = false;
53
+
54
+ // a flag to be able to tell if the onwrite cb is called immediately,
55
+ // or on a later tick. We set this to true at first, because any
56
+ // actions that shouldn't happen until "later" should generally also
57
+ // not happen before the first write call.
58
+ this.sync = true;
59
+
60
+ // whenever we return null, then we set a flag to say
61
+ // that we're awaiting a 'readable' event emission.
62
+ this.needReadable = false;
63
+ this.emittedReadable = false;
64
+ this.readableListening = false;
65
+
66
+
67
+ // object stream flag. Used to make read(n) ignore n and to
68
+ // make all the buffer merging and length checks go away
69
+ this.objectMode = !!options.objectMode;
70
+
71
+ // Crypto is kind of old and crusty. Historically, its default string
72
+ // encoding is 'binary' so we have to make this configurable.
73
+ // Everything else in the universe uses 'utf8', though.
74
+ this.defaultEncoding = options.defaultEncoding || 'utf8';
75
+
76
+ // when piping, we only care about 'readable' events that happen
77
+ // after read()ing all the bytes and not getting any pushback.
78
+ this.ranOut = false;
79
+
80
+ // the number of writers that are awaiting a drain event in .pipe()s
81
+ this.awaitDrain = 0;
82
+
83
+ // if true, a maybeReadMore has been scheduled
84
+ this.readingMore = false;
85
+
86
+ this.decoder = null;
87
+ this.encoding = null;
88
+ if (options.encoding) {
89
+ if (!StringDecoder)
90
+ StringDecoder = require('string_decoder').StringDecoder;
91
+ this.decoder = new StringDecoder(options.encoding);
92
+ this.encoding = options.encoding;
93
+ }
94
+ }
95
+
96
+ function Readable(options) {
97
+ if (!(this instanceof Readable))
98
+ return new Readable(options);
99
+
100
+ this._readableState = new ReadableState(options, this);
101
+
102
+ // legacy
103
+ this.readable = true;
104
+
105
+ Stream.call(this);
106
+ }
107
+
108
+ // Manually shove something into the read() buffer.
109
+ // This returns true if the highWaterMark has not been hit yet,
110
+ // similar to how Writable.write() returns true if you should
111
+ // write() some more.
112
+ Readable.prototype.push = function(chunk, encoding) {
113
+ var state = this._readableState;
114
+
115
+ if (util.isString(chunk) && !state.objectMode) {
116
+ encoding = encoding || state.defaultEncoding;
117
+ if (encoding !== state.encoding) {
118
+ chunk = new Buffer(chunk, encoding);
119
+ encoding = '';
120
+ }
121
+ }
122
+
123
+ return readableAddChunk(this, state, chunk, encoding, false);
124
+ };
125
+
126
+ // Unshift should *always* be something directly out of read()
127
+ Readable.prototype.unshift = function(chunk) {
128
+ var state = this._readableState;
129
+ return readableAddChunk(this, state, chunk, '', true);
130
+ };
131
+
132
+ function readableAddChunk(stream, state, chunk, encoding, addToFront) {
133
+ var er = chunkInvalid(state, chunk);
134
+ if (er) {
135
+ stream.emit('error', er);
136
+ } else if (util.isNullOrUndefined(chunk)) {
137
+ state.reading = false;
138
+ if (!state.ended)
139
+ onEofChunk(stream, state);
140
+ } else if (state.objectMode || chunk && chunk.length > 0) {
141
+ if (state.ended && !addToFront) {
142
+ var e = new Error('stream.push() after EOF');
143
+ stream.emit('error', e);
144
+ } else if (state.endEmitted && addToFront) {
145
+ var e = new Error('stream.unshift() after end event');
146
+ stream.emit('error', e);
147
+ } else {
148
+ if (state.decoder && !addToFront && !encoding)
149
+ chunk = state.decoder.write(chunk);
150
+
151
+ if (!addToFront)
152
+ state.reading = false;
153
+
154
+ // if we want the data now, just emit it.
155
+ if (state.flowing && state.length === 0 && !state.sync) {
156
+ stream.emit('data', chunk);
157
+ stream.read(0);
158
+ } else {
159
+ // update the buffer info.
160
+ state.length += state.objectMode ? 1 : chunk.length;
161
+ if (addToFront)
162
+ state.buffer.unshift(chunk);
163
+ else
164
+ state.buffer.push(chunk);
165
+
166
+ if (state.needReadable)
167
+ emitReadable(stream);
168
+ }
169
+
170
+ maybeReadMore(stream, state);
171
+ }
172
+ } else if (!addToFront) {
173
+ state.reading = false;
174
+ }
175
+
176
+ return needMoreData(state);
177
+ }
178
+
179
+
180
+
181
+ // if it's past the high water mark, we can push in some more.
182
+ // Also, if we have no data yet, we can stand some
183
+ // more bytes. This is to work around cases where hwm=0,
184
+ // such as the repl. Also, if the push() triggered a
185
+ // readable event, and the user called read(largeNumber) such that
186
+ // needReadable was set, then we ought to push more, so that another
187
+ // 'readable' event will be triggered.
188
+ function needMoreData(state) {
189
+ return !state.ended &&
190
+ (state.needReadable ||
191
+ state.length < state.highWaterMark ||
192
+ state.length === 0);
193
+ }
194
+
195
+ // backwards compatibility.
196
+ Readable.prototype.setEncoding = function(enc) {
197
+ if (!StringDecoder)
198
+ StringDecoder = require('string_decoder').StringDecoder;
199
+ this._readableState.decoder = new StringDecoder(enc);
200
+ this._readableState.encoding = enc;
201
+ return this;
202
+ };
203
+
204
+ // Don't raise the hwm > 128MB
205
+ var MAX_HWM = 0x800000;
206
+ function roundUpToNextPowerOf2(n) {
207
+ if (n >= MAX_HWM) {
208
+ n = MAX_HWM;
209
+ } else {
210
+ // Get the next highest power of 2
211
+ n--;
212
+ for (var p = 1; p < 32; p <<= 1) n |= n >> p;
213
+ n++;
214
+ }
215
+ return n;
216
+ }
217
+
218
+ function howMuchToRead(n, state) {
219
+ if (state.length === 0 && state.ended)
220
+ return 0;
221
+
222
+ if (state.objectMode)
223
+ return n === 0 ? 0 : 1;
224
+
225
+ if (isNaN(n) || util.isNull(n)) {
226
+ // only flow one buffer at a time
227
+ if (state.flowing && state.buffer.length)
228
+ return state.buffer[0].length;
229
+ else
230
+ return state.length;
231
+ }
232
+
233
+ if (n <= 0)
234
+ return 0;
235
+
236
+ // If we're asking for more than the target buffer level,
237
+ // then raise the water mark. Bump up to the next highest
238
+ // power of 2, to prevent increasing it excessively in tiny
239
+ // amounts.
240
+ if (n > state.highWaterMark)
241
+ state.highWaterMark = roundUpToNextPowerOf2(n);
242
+
243
+ // don't have that much. return null, unless we've ended.
244
+ if (n > state.length) {
245
+ if (!state.ended) {
246
+ state.needReadable = true;
247
+ return 0;
248
+ } else
249
+ return state.length;
250
+ }
251
+
252
+ return n;
253
+ }
254
+
255
+ // you can override either this method, or the async _read(n) below.
256
+ Readable.prototype.read = function(n) {
257
+ debug('read', n);
258
+ var state = this._readableState;
259
+ var nOrig = n;
260
+
261
+ if (!util.isNumber(n) || n > 0)
262
+ state.emittedReadable = false;
263
+
264
+ // if we're doing read(0) to trigger a readable event, but we
265
+ // already have a bunch of data in the buffer, then just trigger
266
+ // the 'readable' event and move on.
267
+ if (n === 0 &&
268
+ state.needReadable &&
269
+ (state.length >= state.highWaterMark || state.ended)) {
270
+ debug('read: emitReadable', state.length, state.ended);
271
+ if (state.length === 0 && state.ended)
272
+ endReadable(this);
273
+ else
274
+ emitReadable(this);
275
+ return null;
276
+ }
277
+
278
+ n = howMuchToRead(n, state);
279
+
280
+ // if we've ended, and we're now clear, then finish it up.
281
+ if (n === 0 && state.ended) {
282
+ if (state.length === 0)
283
+ endReadable(this);
284
+ return null;
285
+ }
286
+
287
+ // All the actual chunk generation logic needs to be
288
+ // *below* the call to _read. The reason is that in certain
289
+ // synthetic stream cases, such as passthrough streams, _read
290
+ // may be a completely synchronous operation which may change
291
+ // the state of the read buffer, providing enough data when
292
+ // before there was *not* enough.
293
+ //
294
+ // So, the steps are:
295
+ // 1. Figure out what the state of things will be after we do
296
+ // a read from the buffer.
297
+ //
298
+ // 2. If that resulting state will trigger a _read, then call _read.
299
+ // Note that this may be asynchronous, or synchronous. Yes, it is
300
+ // deeply ugly to write APIs this way, but that still doesn't mean
301
+ // that the Readable class should behave improperly, as streams are
302
+ // designed to be sync/async agnostic.
303
+ // Take note if the _read call is sync or async (ie, if the read call
304
+ // has returned yet), so that we know whether or not it's safe to emit
305
+ // 'readable' etc.
306
+ //
307
+ // 3. Actually pull the requested chunks out of the buffer and return.
308
+
309
+ // if we need a readable event, then we need to do some reading.
310
+ var doRead = state.needReadable;
311
+ debug('need readable', doRead);
312
+
313
+ // if we currently have less than the highWaterMark, then also read some
314
+ if (state.length === 0 || state.length - n < state.highWaterMark) {
315
+ doRead = true;
316
+ debug('length less than watermark', doRead);
317
+ }
318
+
319
+ // however, if we've ended, then there's no point, and if we're already
320
+ // reading, then it's unnecessary.
321
+ if (state.ended || state.reading) {
322
+ doRead = false;
323
+ debug('reading or ended', doRead);
324
+ }
325
+
326
+ if (doRead) {
327
+ debug('do read');
328
+ state.reading = true;
329
+ state.sync = true;
330
+ // if the length is currently zero, then we *need* a readable event.
331
+ if (state.length === 0)
332
+ state.needReadable = true;
333
+ // call internal read method
334
+ this._read(state.highWaterMark);
335
+ state.sync = false;
336
+ }
337
+
338
+ // If _read pushed data synchronously, then `reading` will be false,
339
+ // and we need to re-evaluate how much data we can return to the user.
340
+ if (doRead && !state.reading)
341
+ n = howMuchToRead(nOrig, state);
342
+
343
+ var ret;
344
+ if (n > 0)
345
+ ret = fromList(n, state);
346
+ else
347
+ ret = null;
348
+
349
+ if (util.isNull(ret)) {
350
+ state.needReadable = true;
351
+ n = 0;
352
+ }
353
+
354
+ state.length -= n;
355
+
356
+ // If we have nothing in the buffer, then we want to know
357
+ // as soon as we *do* get something into the buffer.
358
+ if (state.length === 0 && !state.ended)
359
+ state.needReadable = true;
360
+
361
+ // If we tried to read() past the EOF, then emit end on the next tick.
362
+ if (nOrig !== n && state.ended && state.length === 0)
363
+ endReadable(this);
364
+
365
+ if (!util.isNull(ret))
366
+ this.emit('data', ret);
367
+
368
+ return ret;
369
+ };
370
+
371
+ function chunkInvalid(state, chunk) {
372
+ var er = null;
373
+ if (!util.isBuffer(chunk) &&
374
+ !util.isString(chunk) &&
375
+ !util.isNullOrUndefined(chunk) &&
376
+ !state.objectMode &&
377
+ !er) {
378
+ er = new TypeError('Invalid non-string/buffer chunk');
379
+ }
380
+ return er;
381
+ }
382
+
383
+
384
+ function onEofChunk(stream, state) {
385
+ if (state.decoder && !state.ended) {
386
+ var chunk = state.decoder.end();
387
+ if (chunk && chunk.length) {
388
+ state.buffer.push(chunk);
389
+ state.length += state.objectMode ? 1 : chunk.length;
390
+ }
391
+ }
392
+ state.ended = true;
393
+
394
+ // emit 'readable' now to make sure it gets picked up.
395
+ emitReadable(stream);
396
+ }
397
+
398
+ // Don't emit readable right away in sync mode, because this can trigger
399
+ // another read() call => stack overflow. This way, it might trigger
400
+ // a nextTick recursion warning, but that's not so bad.
401
+ function emitReadable(stream) {
402
+ var state = stream._readableState;
403
+ state.needReadable = false;
404
+ if (!state.emittedReadable) {
405
+ debug('emitReadable', state.flowing);
406
+ state.emittedReadable = true;
407
+ if (state.sync)
408
+ process.nextTick(function() {
409
+ emitReadable_(stream);
410
+ });
411
+ else
412
+ emitReadable_(stream);
413
+ }
414
+ }
415
+
416
+ function emitReadable_(stream) {
417
+ debug('emit readable');
418
+ stream.emit('readable');
419
+ flow(stream);
420
+ }
421
+
422
+
423
+ // at this point, the user has presumably seen the 'readable' event,
424
+ // and called read() to consume some data. that may have triggered
425
+ // in turn another _read(n) call, in which case reading = true if
426
+ // it's in progress.
427
+ // However, if we're not ended, or reading, and the length < hwm,
428
+ // then go ahead and try to read some more preemptively.
429
+ function maybeReadMore(stream, state) {
430
+ if (!state.readingMore) {
431
+ state.readingMore = true;
432
+ process.nextTick(function() {
433
+ maybeReadMore_(stream, state);
434
+ });
435
+ }
436
+ }
437
+
438
+ function maybeReadMore_(stream, state) {
439
+ var len = state.length;
440
+ while (!state.reading && !state.flowing && !state.ended &&
441
+ state.length < state.highWaterMark) {
442
+ debug('maybeReadMore read 0');
443
+ stream.read(0);
444
+ if (len === state.length)
445
+ // didn't get any data, stop spinning.
446
+ break;
447
+ else
448
+ len = state.length;
449
+ }
450
+ state.readingMore = false;
451
+ }
452
+
453
+ // abstract method. to be overridden in specific implementation classes.
454
+ // call cb(er, data) where data is <= n in length.
455
+ // for virtual (non-string, non-buffer) streams, "length" is somewhat
456
+ // arbitrary, and perhaps not very meaningful.
457
+ Readable.prototype._read = function(n) {
458
+ this.emit('error', new Error('not implemented'));
459
+ };
460
+
461
+ Readable.prototype.pipe = function(dest, pipeOpts) {
462
+ var src = this;
463
+ var state = this._readableState;
464
+
465
+ switch (state.pipesCount) {
466
+ case 0:
467
+ state.pipes = dest;
468
+ break;
469
+ case 1:
470
+ state.pipes = [state.pipes, dest];
471
+ break;
472
+ default:
473
+ state.pipes.push(dest);
474
+ break;
475
+ }
476
+ state.pipesCount += 1;
477
+ debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
478
+
479
+ var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
480
+ dest !== process.stdout &&
481
+ dest !== process.stderr;
482
+
483
+ var endFn = doEnd ? onend : cleanup;
484
+ if (state.endEmitted)
485
+ process.nextTick(endFn);
486
+ else
487
+ src.once('end', endFn);
488
+
489
+ dest.on('unpipe', onunpipe);
490
+ function onunpipe(readable) {
491
+ debug('onunpipe');
492
+ if (readable === src) {
493
+ cleanup();
494
+ }
495
+ }
496
+
497
+ function onend() {
498
+ debug('onend');
499
+ dest.end();
500
+ }
501
+
502
+ // when the dest drains, it reduces the awaitDrain counter
503
+ // on the source. This would be more elegant with a .once()
504
+ // handler in flow(), but adding and removing repeatedly is
505
+ // too slow.
506
+ var ondrain = pipeOnDrain(src);
507
+ dest.on('drain', ondrain);
508
+
509
+ function cleanup() {
510
+ debug('cleanup');
511
+ // cleanup event handlers once the pipe is broken
512
+ dest.removeListener('close', onclose);
513
+ dest.removeListener('finish', onfinish);
514
+ dest.removeListener('drain', ondrain);
515
+ dest.removeListener('error', onerror);
516
+ dest.removeListener('unpipe', onunpipe);
517
+ src.removeListener('end', onend);
518
+ src.removeListener('end', cleanup);
519
+ src.removeListener('data', ondata);
520
+
521
+ // if the reader is waiting for a drain event from this
522
+ // specific writer, then it would cause it to never start
523
+ // flowing again.
524
+ // So, if this is awaiting a drain, then we just call it now.
525
+ // If we don't know, then assume that we are waiting for one.
526
+ if (state.awaitDrain &&
527
+ (!dest._writableState || dest._writableState.needDrain))
528
+ ondrain();
529
+ }
530
+
531
+ src.on('data', ondata);
532
+ function ondata(chunk) {
533
+ debug('ondata');
534
+ var ret = dest.write(chunk);
535
+ if (false === ret) {
536
+ debug('false write response, pause',
537
+ src._readableState.awaitDrain);
538
+ src._readableState.awaitDrain++;
539
+ src.pause();
540
+ }
541
+ }
542
+
543
+ // if the dest has an error, then stop piping into it.
544
+ // however, don't suppress the throwing behavior for this.
545
+ function onerror(er) {
546
+ debug('onerror', er);
547
+ unpipe();
548
+ dest.removeListener('error', onerror);
549
+ if (EE.listenerCount(dest, 'error') === 0)
550
+ dest.emit('error', er);
551
+ }
552
+ // This is a brutally ugly hack to make sure that our error handler
553
+ // is attached before any userland ones. NEVER DO THIS.
554
+ if (!dest._events || !dest._events.error)
555
+ dest.on('error', onerror);
556
+ else if (Array.isArray(dest._events.error))
557
+ dest._events.error.unshift(onerror);
558
+ else
559
+ dest._events.error = [onerror, dest._events.error];
560
+
561
+
562
+
563
+ // Both close and finish should trigger unpipe, but only once.
564
+ function onclose() {
565
+ dest.removeListener('finish', onfinish);
566
+ unpipe();
567
+ }
568
+ dest.once('close', onclose);
569
+ function onfinish() {
570
+ debug('onfinish');
571
+ dest.removeListener('close', onclose);
572
+ unpipe();
573
+ }
574
+ dest.once('finish', onfinish);
575
+
576
+ function unpipe() {
577
+ debug('unpipe');
578
+ src.unpipe(dest);
579
+ }
580
+
581
+ // tell the dest that it's being piped to
582
+ dest.emit('pipe', src);
583
+
584
+ // start the flow if it hasn't been started already.
585
+ if (!state.flowing) {
586
+ debug('pipe resume');
587
+ src.resume();
588
+ }
589
+
590
+ return dest;
591
+ };
592
+
593
+ function pipeOnDrain(src) {
594
+ return function() {
595
+ var state = src._readableState;
596
+ debug('pipeOnDrain', state.awaitDrain);
597
+ if (state.awaitDrain)
598
+ state.awaitDrain--;
599
+ if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
600
+ state.flowing = true;
601
+ flow(src);
602
+ }
603
+ };
604
+ }
605
+
606
+
607
+ Readable.prototype.unpipe = function(dest) {
608
+ var state = this._readableState;
609
+
610
+ // if we're not piping anywhere, then do nothing.
611
+ if (state.pipesCount === 0)
612
+ return this;
613
+
614
+ // just one destination. most common case.
615
+ if (state.pipesCount === 1) {
616
+ // passed in one, but it's not the right one.
617
+ if (dest && dest !== state.pipes)
618
+ return this;
619
+
620
+ if (!dest)
621
+ dest = state.pipes;
622
+
623
+ // got a match.
624
+ state.pipes = null;
625
+ state.pipesCount = 0;
626
+ state.flowing = false;
627
+ if (dest)
628
+ dest.emit('unpipe', this);
629
+ return this;
630
+ }
631
+
632
+ // slow case. multiple pipe destinations.
633
+
634
+ if (!dest) {
635
+ // remove all.
636
+ var dests = state.pipes;
637
+ var len = state.pipesCount;
638
+ state.pipes = null;
639
+ state.pipesCount = 0;
640
+ state.flowing = false;
641
+
642
+ for (var i = 0; i < len; i++)
643
+ dests[i].emit('unpipe', this);
644
+ return this;
645
+ }
646
+
647
+ // try to find the right one.
648
+ var i = state.pipes.indexOf(dest);
649
+ if (i === -1)
650
+ return this;
651
+
652
+ state.pipes.splice(i, 1);
653
+ state.pipesCount -= 1;
654
+ if (state.pipesCount === 1)
655
+ state.pipes = state.pipes[0];
656
+
657
+ dest.emit('unpipe', this);
658
+
659
+ return this;
660
+ };
661
+
662
+ // set up data events if they are asked for
663
+ // Ensure readable listeners eventually get something
664
+ Readable.prototype.on = function(ev, fn) {
665
+ var res = Stream.prototype.on.call(this, ev, fn);
666
+
667
+ // If listening to data, and it has not explicitly been paused,
668
+ // then call resume to start the flow of data on the next tick.
669
+ if (ev === 'data' && false !== this._readableState.flowing) {
670
+ this.resume();
671
+ }
672
+
673
+ if (ev === 'readable' && this.readable) {
674
+ var state = this._readableState;
675
+ if (!state.readableListening) {
676
+ state.readableListening = true;
677
+ state.emittedReadable = false;
678
+ state.needReadable = true;
679
+ if (!state.reading) {
680
+ var self = this;
681
+ process.nextTick(function() {
682
+ debug('readable nexttick read 0');
683
+ self.read(0);
684
+ });
685
+ } else if (state.length) {
686
+ emitReadable(this, state);
687
+ }
688
+ }
689
+ }
690
+
691
+ return res;
692
+ };
693
+ Readable.prototype.addListener = Readable.prototype.on;
694
+
695
+ // pause() and resume() are remnants of the legacy readable stream API
696
+ // If the user uses them, then switch into old mode.
697
+ Readable.prototype.resume = function() {
698
+ var state = this._readableState;
699
+ if (!state.flowing) {
700
+ debug('resume');
701
+ state.flowing = true;
702
+ if (!state.reading) {
703
+ debug('resume read 0');
704
+ this.read(0);
705
+ }
706
+ resume(this, state);
707
+ }
708
+ return this;
709
+ };
710
+
711
+ function resume(stream, state) {
712
+ if (!state.resumeScheduled) {
713
+ state.resumeScheduled = true;
714
+ process.nextTick(function() {
715
+ resume_(stream, state);
716
+ });
717
+ }
718
+ }
719
+
720
+ function resume_(stream, state) {
721
+ state.resumeScheduled = false;
722
+ stream.emit('resume');
723
+ flow(stream);
724
+ if (state.flowing && !state.reading)
725
+ stream.read(0);
726
+ }
727
+
728
+ Readable.prototype.pause = function() {
729
+ debug('call pause flowing=%j', this._readableState.flowing);
730
+ if (false !== this._readableState.flowing) {
731
+ debug('pause');
732
+ this._readableState.flowing = false;
733
+ this.emit('pause');
734
+ }
735
+ return this;
736
+ };
737
+
738
+ function flow(stream) {
739
+ var state = stream._readableState;
740
+ debug('flow', state.flowing);
741
+ if (state.flowing) {
742
+ do {
743
+ var chunk = stream.read();
744
+ } while (null !== chunk && state.flowing);
745
+ }
746
+ }
747
+
748
+ // wrap an old-style stream as the async data source.
749
+ // This is *not* part of the readable stream interface.
750
+ // It is an ugly unfortunate mess of history.
751
+ Readable.prototype.wrap = function(stream) {
752
+ var state = this._readableState;
753
+ var paused = false;
754
+
755
+ var self = this;
756
+ stream.on('end', function() {
757
+ debug('wrapped end');
758
+ if (state.decoder && !state.ended) {
759
+ var chunk = state.decoder.end();
760
+ if (chunk && chunk.length)
761
+ self.push(chunk);
762
+ }
763
+
764
+ self.push(null);
765
+ });
766
+
767
+ stream.on('data', function(chunk) {
768
+ debug('wrapped data');
769
+ if (state.decoder)
770
+ chunk = state.decoder.write(chunk);
771
+ if (!chunk || !state.objectMode && !chunk.length)
772
+ return;
773
+
774
+ var ret = self.push(chunk);
775
+ if (!ret) {
776
+ paused = true;
777
+ stream.pause();
778
+ }
779
+ });
780
+
781
+ // proxy all the other methods.
782
+ // important when wrapping filters and duplexes.
783
+ for (var i in stream) {
784
+ if (util.isFunction(stream[i]) && util.isUndefined(this[i])) {
785
+ this[i] = function(method) { return function() {
786
+ return stream[method].apply(stream, arguments);
787
+ }}(i);
788
+ }
789
+ }
790
+
791
+ // proxy certain important events.
792
+ var events = ['error', 'close', 'destroy', 'pause', 'resume'];
793
+ events.forEach(function(ev) {
794
+ stream.on(ev, self.emit.bind(self, ev));
795
+ });
796
+
797
+ // when we try to consume some more bytes, simply unpause the
798
+ // underlying stream.
799
+ self._read = function(n) {
800
+ debug('wrapped _read', n);
801
+ if (paused) {
802
+ paused = false;
803
+ stream.resume();
804
+ }
805
+ };
806
+
807
+ return self;
808
+ };
809
+
810
+
811
+
812
+ // exposed for testing purposes only.
813
+ Readable._fromList = fromList;
814
+
815
+ // Pluck off n bytes from an array of buffers.
816
+ // Length is the combined lengths of all the buffers in the list.
817
+ function fromList(n, state) {
818
+ var list = state.buffer;
819
+ var length = state.length;
820
+ var stringMode = !!state.decoder;
821
+ var objectMode = !!state.objectMode;
822
+ var ret;
823
+
824
+ // nothing in the list, definitely empty.
825
+ if (list.length === 0)
826
+ return null;
827
+
828
+ if (length === 0)
829
+ ret = null;
830
+ else if (objectMode)
831
+ ret = list.shift();
832
+ else if (!n || n >= length) {
833
+ // read it all, truncate the array.
834
+ if (stringMode)
835
+ ret = list.join('');
836
+ else
837
+ ret = Buffer.concat(list, length);
838
+ list.length = 0;
839
+ } else {
840
+ // read just some of it.
841
+ if (n < list[0].length) {
842
+ // just take a part of the first list item.
843
+ // slice is the same for buffers and strings.
844
+ var buf = list[0];
845
+ ret = buf.slice(0, n);
846
+ list[0] = buf.slice(n);
847
+ } else if (n === list[0].length) {
848
+ // first list is a perfect match
849
+ ret = list.shift();
850
+ } else {
851
+ // complex case.
852
+ // we have enough to cover it, but it spans past the first buffer.
853
+ if (stringMode)
854
+ ret = '';
855
+ else
856
+ ret = new Buffer(n);
857
+
858
+ var c = 0;
859
+ for (var i = 0, l = list.length; i < l && c < n; i++) {
860
+ var buf = list[0];
861
+ var cpy = Math.min(n - c, buf.length);
862
+
863
+ if (stringMode)
864
+ ret += buf.slice(0, cpy);
865
+ else
866
+ buf.copy(ret, c, 0, cpy);
867
+
868
+ if (cpy < buf.length)
869
+ list[0] = buf.slice(cpy);
870
+ else
871
+ list.shift();
872
+
873
+ c += cpy;
874
+ }
875
+ }
876
+ }
877
+
878
+ return ret;
879
+ }
880
+
881
+ function endReadable(stream) {
882
+ var state = stream._readableState;
883
+
884
+ // If we get here before consuming all the bytes, then that is a
885
+ // bug in node. Should never happen.
886
+ if (state.length > 0)
887
+ throw new Error('endReadable called on non-empty stream');
888
+
889
+ if (!state.endEmitted) {
890
+ state.ended = true;
891
+ process.nextTick(function() {
892
+ // Check that we didn't get one last unshift.
893
+ if (!state.endEmitted && state.length === 0) {
894
+ state.endEmitted = true;
895
+ stream.readable = false;
896
+ stream.emit('end');
897
+ }
898
+ });
899
+ }
900
+ }