macgyver 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,204 @@
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
+
23
+ // a transform stream is a readable/writable stream where you do
24
+ // something with the data. Sometimes it's called a "filter",
25
+ // but that's not a great name for it, since that implies a thing where
26
+ // some bits pass through, and others are simply ignored. (That would
27
+ // be a valid example of a transform, of course.)
28
+ //
29
+ // While the output is causally related to the input, it's not a
30
+ // necessarily symmetric or synchronous transformation. For example,
31
+ // a zlib stream might take multiple plain-text writes(), and then
32
+ // emit a single compressed chunk some time in the future.
33
+ //
34
+ // Here's how this works:
35
+ //
36
+ // The Transform stream has all the aspects of the readable and writable
37
+ // stream classes. When you write(chunk), that calls _write(chunk,cb)
38
+ // internally, and returns false if there's a lot of pending writes
39
+ // buffered up. When you call read(), that calls _read(n) until
40
+ // there's enough pending readable data buffered up.
41
+ //
42
+ // In a transform stream, the written data is placed in a buffer. When
43
+ // _read(n) is called, it transforms the queued up data, calling the
44
+ // buffered _write cb's as it consumes chunks. If consuming a single
45
+ // written chunk would result in multiple output chunks, then the first
46
+ // outputted bit calls the readcb, and subsequent chunks just go into
47
+ // the read buffer, and will cause it to emit 'readable' if necessary.
48
+ //
49
+ // This way, back-pressure is actually determined by the reading side,
50
+ // since _read has to be called to start processing a new chunk. However,
51
+ // a pathological inflate type of transform can cause excessive buffering
52
+ // here. For example, imagine a stream where every byte of input is
53
+ // interpreted as an integer from 0-255, and then results in that many
54
+ // bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
55
+ // 1kb of data being output. In this case, you could write a very small
56
+ // amount of input, and end up with a very large amount of output. In
57
+ // such a pathological inflating mechanism, there'd be no way to tell
58
+ // the system to stop doing the transform. A single 4MB write could
59
+ // cause the system to run out of memory.
60
+ //
61
+ // However, even in such a pathological case, only a single written chunk
62
+ // would be consumed, and then the rest would wait (un-transformed) until
63
+ // the results of the previous transformed chunk were consumed.
64
+
65
+ module.exports = Transform;
66
+
67
+ var Duplex = require('_stream_duplex');
68
+ var util = require('util');
69
+ util.inherits(Transform, Duplex);
70
+
71
+
72
+ function TransformState(options, stream) {
73
+ this.afterTransform = function(er, data) {
74
+ return afterTransform(stream, er, data);
75
+ };
76
+
77
+ this.needTransform = false;
78
+ this.transforming = false;
79
+ this.writecb = null;
80
+ this.writechunk = null;
81
+ }
82
+
83
+ function afterTransform(stream, er, data) {
84
+ var ts = stream._transformState;
85
+ ts.transforming = false;
86
+
87
+ var cb = ts.writecb;
88
+
89
+ if (!cb)
90
+ return stream.emit('error', new Error('no writecb in Transform class'));
91
+
92
+ ts.writechunk = null;
93
+ ts.writecb = null;
94
+
95
+ if (!util.isNullOrUndefined(data))
96
+ stream.push(data);
97
+
98
+ if (cb)
99
+ cb(er);
100
+
101
+ var rs = stream._readableState;
102
+ rs.reading = false;
103
+ if (rs.needReadable || rs.length < rs.highWaterMark) {
104
+ stream._read(rs.highWaterMark);
105
+ }
106
+ }
107
+
108
+
109
+ function Transform(options) {
110
+ if (!(this instanceof Transform))
111
+ return new Transform(options);
112
+
113
+ Duplex.call(this, options);
114
+
115
+ this._transformState = new TransformState(options, this);
116
+
117
+ // when the writable side finishes, then flush out anything remaining.
118
+ var stream = this;
119
+
120
+ // start out asking for a readable event once data is transformed.
121
+ this._readableState.needReadable = true;
122
+
123
+ // we have implemented the _read method, and done the other things
124
+ // that Readable wants before the first _read call, so unset the
125
+ // sync guard flag.
126
+ this._readableState.sync = false;
127
+
128
+ this.once('prefinish', function() {
129
+ if (util.isFunction(this._flush))
130
+ this._flush(function(er) {
131
+ done(stream, er);
132
+ });
133
+ else
134
+ done(stream);
135
+ });
136
+ }
137
+
138
+ Transform.prototype.push = function(chunk, encoding) {
139
+ this._transformState.needTransform = false;
140
+ return Duplex.prototype.push.call(this, chunk, encoding);
141
+ };
142
+
143
+ // This is the part where you do stuff!
144
+ // override this function in implementation classes.
145
+ // 'chunk' is an input chunk.
146
+ //
147
+ // Call `push(newChunk)` to pass along transformed output
148
+ // to the readable side. You may call 'push' zero or more times.
149
+ //
150
+ // Call `cb(err)` when you are done with this chunk. If you pass
151
+ // an error, then that'll put the hurt on the whole operation. If you
152
+ // never call cb(), then you'll never get another chunk.
153
+ Transform.prototype._transform = function(chunk, encoding, cb) {
154
+ throw new Error('not implemented');
155
+ };
156
+
157
+ Transform.prototype._write = function(chunk, encoding, cb) {
158
+ var ts = this._transformState;
159
+ ts.writecb = cb;
160
+ ts.writechunk = chunk;
161
+ ts.writeencoding = encoding;
162
+ if (!ts.transforming) {
163
+ var rs = this._readableState;
164
+ if (ts.needTransform ||
165
+ rs.needReadable ||
166
+ rs.length < rs.highWaterMark)
167
+ this._read(rs.highWaterMark);
168
+ }
169
+ };
170
+
171
+ // Doesn't matter what the args are here.
172
+ // _transform does all the work.
173
+ // That we got here means that the readable side wants more data.
174
+ Transform.prototype._read = function(n) {
175
+ var ts = this._transformState;
176
+
177
+ if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) {
178
+ ts.transforming = true;
179
+ this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
180
+ } else {
181
+ // mark that we need a transform, so that any data that comes in
182
+ // will get processed, now that we've asked for it.
183
+ ts.needTransform = true;
184
+ }
185
+ };
186
+
187
+
188
+ function done(stream, er) {
189
+ if (er)
190
+ return stream.emit('error', er);
191
+
192
+ // if there's nothing in the write buffer, then that means
193
+ // that nothing more will ever be provided
194
+ var ws = stream._writableState;
195
+ var ts = stream._transformState;
196
+
197
+ if (ws.length)
198
+ throw new Error('calling transform done when ws.length != 0');
199
+
200
+ if (ts.transforming)
201
+ throw new Error('calling transform done when still transforming');
202
+
203
+ return stream.push(null);
204
+ }
@@ -0,0 +1,456 @@
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 bit simpler than readable streams.
23
+ // Implement an async ._write(chunk, cb), and it'll handle all
24
+ // the drain event emission and buffering.
25
+
26
+ module.exports = Writable;
27
+ Writable.WritableState = WritableState;
28
+
29
+ var util = require('util');
30
+ var Stream = require('stream');
31
+
32
+ util.inherits(Writable, Stream);
33
+
34
+ function WriteReq(chunk, encoding, cb) {
35
+ this.chunk = chunk;
36
+ this.encoding = encoding;
37
+ this.callback = cb;
38
+ }
39
+
40
+ function WritableState(options, stream) {
41
+ options = options || {};
42
+
43
+ // the point at which write() starts returning false
44
+ // Note: 0 is a valid value, means that we always return false if
45
+ // the entire buffer is not flushed immediately on write()
46
+ var hwm = options.highWaterMark;
47
+ var defaultHwm = options.objectMode ? 16 : 16 * 1024;
48
+ this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
49
+
50
+ // object stream flag to indicate whether or not this stream
51
+ // contains buffers or objects.
52
+ this.objectMode = !!options.objectMode;
53
+
54
+ // cast to ints.
55
+ this.highWaterMark = ~~this.highWaterMark;
56
+
57
+ this.needDrain = false;
58
+ // at the start of calling end()
59
+ this.ending = false;
60
+ // when end() has been called, and returned
61
+ this.ended = false;
62
+ // when 'finish' is emitted
63
+ this.finished = false;
64
+
65
+ // should we decode strings into buffers before passing to _write?
66
+ // this is here so that some node-core streams can optimize string
67
+ // handling at a lower level.
68
+ var noDecode = options.decodeStrings === false;
69
+ this.decodeStrings = !noDecode;
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
+ // not an actual buffer we keep track of, but a measurement
77
+ // of how much we're waiting to get pushed to some underlying
78
+ // socket or file.
79
+ this.length = 0;
80
+
81
+ // a flag to see when we're in the middle of a write.
82
+ this.writing = false;
83
+
84
+ // when true all writes will be buffered until .uncork() call
85
+ this.corked = 0;
86
+
87
+ // a flag to be able to tell if the onwrite cb is called immediately,
88
+ // or on a later tick. We set this to true at first, because any
89
+ // actions that shouldn't happen until "later" should generally also
90
+ // not happen before the first write call.
91
+ this.sync = true;
92
+
93
+ // a flag to know if we're processing previously buffered items, which
94
+ // may call the _write() callback in the same tick, so that we don't
95
+ // end up in an overlapped onwrite situation.
96
+ this.bufferProcessing = false;
97
+
98
+ // the callback that's passed to _write(chunk,cb)
99
+ this.onwrite = function(er) {
100
+ onwrite(stream, er);
101
+ };
102
+
103
+ // the callback that the user supplies to write(chunk,encoding,cb)
104
+ this.writecb = null;
105
+
106
+ // the amount that is being written when _write is called.
107
+ this.writelen = 0;
108
+
109
+ this.buffer = [];
110
+
111
+ // number of pending user-supplied write callbacks
112
+ // this must be 0 before 'finish' can be emitted
113
+ this.pendingcb = 0;
114
+
115
+ // emit prefinish if the only thing we're waiting for is _write cbs
116
+ // This is relevant for synchronous Transform streams
117
+ this.prefinished = false;
118
+ }
119
+
120
+ function Writable(options) {
121
+ // Writable ctor is applied to Duplexes, though they're not
122
+ // instanceof Writable, they're instanceof Readable.
123
+ if (!(this instanceof Writable) && !(this instanceof Stream.Duplex))
124
+ return new Writable(options);
125
+
126
+ this._writableState = new WritableState(options, this);
127
+
128
+ // legacy.
129
+ this.writable = true;
130
+
131
+ Stream.call(this);
132
+ }
133
+
134
+ // Otherwise people can pipe Writable streams, which is just wrong.
135
+ Writable.prototype.pipe = function() {
136
+ this.emit('error', new Error('Cannot pipe. Not readable.'));
137
+ };
138
+
139
+
140
+ function writeAfterEnd(stream, state, cb) {
141
+ var er = new Error('write after end');
142
+ // TODO: defer error events consistently everywhere, not just the cb
143
+ stream.emit('error', er);
144
+ process.nextTick(function() {
145
+ cb(er);
146
+ });
147
+ }
148
+
149
+ // If we get something that is not a buffer, string, null, or undefined,
150
+ // and we're not in objectMode, then that's an error.
151
+ // Otherwise stream chunks are all considered to be of length=1, and the
152
+ // watermarks determine how many objects to keep in the buffer, rather than
153
+ // how many bytes or characters.
154
+ function validChunk(stream, state, chunk, cb) {
155
+ var valid = true;
156
+ if (!util.isBuffer(chunk) &&
157
+ !util.isString(chunk) &&
158
+ !util.isNullOrUndefined(chunk) &&
159
+ !state.objectMode) {
160
+ var er = new TypeError('Invalid non-string/buffer chunk');
161
+ stream.emit('error', er);
162
+ process.nextTick(function() {
163
+ cb(er);
164
+ });
165
+ valid = false;
166
+ }
167
+ return valid;
168
+ }
169
+
170
+ Writable.prototype.write = function(chunk, encoding, cb) {
171
+ var state = this._writableState;
172
+ var ret = false;
173
+
174
+ if (util.isFunction(encoding)) {
175
+ cb = encoding;
176
+ encoding = null;
177
+ }
178
+
179
+ if (util.isBuffer(chunk))
180
+ encoding = 'buffer';
181
+ else if (!encoding)
182
+ encoding = state.defaultEncoding;
183
+
184
+ if (!util.isFunction(cb))
185
+ cb = function() {};
186
+
187
+ if (state.ended)
188
+ writeAfterEnd(this, state, cb);
189
+ else if (validChunk(this, state, chunk, cb)) {
190
+ state.pendingcb++;
191
+ ret = writeOrBuffer(this, state, chunk, encoding, cb);
192
+ }
193
+
194
+ return ret;
195
+ };
196
+
197
+ Writable.prototype.cork = function() {
198
+ var state = this._writableState;
199
+
200
+ state.corked++;
201
+ };
202
+
203
+ Writable.prototype.uncork = function() {
204
+ var state = this._writableState;
205
+
206
+ if (state.corked) {
207
+ state.corked--;
208
+
209
+ if (!state.writing &&
210
+ !state.corked &&
211
+ !state.finished &&
212
+ !state.bufferProcessing &&
213
+ state.buffer.length)
214
+ clearBuffer(this, state);
215
+ }
216
+ };
217
+
218
+ function decodeChunk(state, chunk, encoding) {
219
+ if (!state.objectMode &&
220
+ state.decodeStrings !== false &&
221
+ util.isString(chunk)) {
222
+ chunk = new Buffer(chunk, encoding);
223
+ }
224
+ return chunk;
225
+ }
226
+
227
+ // if we're already writing something, then just put this
228
+ // in the queue, and wait our turn. Otherwise, call _write
229
+ // If we return false, then we need a drain event, so set that flag.
230
+ function writeOrBuffer(stream, state, chunk, encoding, cb) {
231
+ chunk = decodeChunk(state, chunk, encoding);
232
+ if (util.isBuffer(chunk))
233
+ encoding = 'buffer';
234
+ var len = state.objectMode ? 1 : chunk.length;
235
+
236
+ state.length += len;
237
+
238
+ var ret = state.length < state.highWaterMark;
239
+ // we must ensure that previous needDrain will not be reset to false.
240
+ if (!ret)
241
+ state.needDrain = true;
242
+
243
+ if (state.writing || state.corked)
244
+ state.buffer.push(new WriteReq(chunk, encoding, cb));
245
+ else
246
+ doWrite(stream, state, false, len, chunk, encoding, cb);
247
+
248
+ return ret;
249
+ }
250
+
251
+ function doWrite(stream, state, writev, len, chunk, encoding, cb) {
252
+ state.writelen = len;
253
+ state.writecb = cb;
254
+ state.writing = true;
255
+ state.sync = true;
256
+ if (writev)
257
+ stream._writev(chunk, state.onwrite);
258
+ else
259
+ stream._write(chunk, encoding, state.onwrite);
260
+ state.sync = false;
261
+ }
262
+
263
+ function onwriteError(stream, state, sync, er, cb) {
264
+ if (sync)
265
+ process.nextTick(function() {
266
+ state.pendingcb--;
267
+ cb(er);
268
+ });
269
+ else {
270
+ state.pendingcb--;
271
+ cb(er);
272
+ }
273
+
274
+ stream.emit('error', er);
275
+ }
276
+
277
+ function onwriteStateUpdate(state) {
278
+ state.writing = false;
279
+ state.writecb = null;
280
+ state.length -= state.writelen;
281
+ state.writelen = 0;
282
+ }
283
+
284
+ function onwrite(stream, er) {
285
+ var state = stream._writableState;
286
+ var sync = state.sync;
287
+ var cb = state.writecb;
288
+
289
+ onwriteStateUpdate(state);
290
+
291
+ if (er)
292
+ onwriteError(stream, state, sync, er, cb);
293
+ else {
294
+ // Check if we're actually ready to finish, but don't emit yet
295
+ var finished = needFinish(stream, state);
296
+
297
+ if (!finished &&
298
+ !state.corked &&
299
+ !state.bufferProcessing &&
300
+ state.buffer.length) {
301
+ clearBuffer(stream, state);
302
+ }
303
+
304
+ if (sync) {
305
+ process.nextTick(function() {
306
+ afterWrite(stream, state, finished, cb);
307
+ });
308
+ } else {
309
+ afterWrite(stream, state, finished, cb);
310
+ }
311
+ }
312
+ }
313
+
314
+ function afterWrite(stream, state, finished, cb) {
315
+ if (!finished)
316
+ onwriteDrain(stream, state);
317
+ state.pendingcb--;
318
+ cb();
319
+ finishMaybe(stream, state);
320
+ }
321
+
322
+ // Must force callback to be called on nextTick, so that we don't
323
+ // emit 'drain' before the write() consumer gets the 'false' return
324
+ // value, and has a chance to attach a 'drain' listener.
325
+ function onwriteDrain(stream, state) {
326
+ if (state.length === 0 && state.needDrain) {
327
+ state.needDrain = false;
328
+ stream.emit('drain');
329
+ }
330
+ }
331
+
332
+
333
+ // if there's something in the buffer waiting, then process it
334
+ function clearBuffer(stream, state) {
335
+ state.bufferProcessing = true;
336
+
337
+ if (stream._writev && state.buffer.length > 1) {
338
+ // Fast case, write everything using _writev()
339
+ var cbs = [];
340
+ for (var c = 0; c < state.buffer.length; c++)
341
+ cbs.push(state.buffer[c].callback);
342
+
343
+ // count the one we are adding, as well.
344
+ // TODO(isaacs) clean this up
345
+ state.pendingcb++;
346
+ doWrite(stream, state, true, state.length, state.buffer, '', function(err) {
347
+ for (var i = 0; i < cbs.length; i++) {
348
+ state.pendingcb--;
349
+ cbs[i](err);
350
+ }
351
+ });
352
+
353
+ // Clear buffer
354
+ state.buffer = [];
355
+ } else {
356
+ // Slow case, write chunks one-by-one
357
+ for (var c = 0; c < state.buffer.length; c++) {
358
+ var entry = state.buffer[c];
359
+ var chunk = entry.chunk;
360
+ var encoding = entry.encoding;
361
+ var cb = entry.callback;
362
+ var len = state.objectMode ? 1 : chunk.length;
363
+
364
+ doWrite(stream, state, false, len, chunk, encoding, cb);
365
+
366
+ // if we didn't call the onwrite immediately, then
367
+ // it means that we need to wait until it does.
368
+ // also, that means that the chunk and cb are currently
369
+ // being processed, so move the buffer counter past them.
370
+ if (state.writing) {
371
+ c++;
372
+ break;
373
+ }
374
+ }
375
+
376
+ if (c < state.buffer.length)
377
+ state.buffer = state.buffer.slice(c);
378
+ else
379
+ state.buffer.length = 0;
380
+ }
381
+
382
+ state.bufferProcessing = false;
383
+ }
384
+
385
+ Writable.prototype._write = function(chunk, encoding, cb) {
386
+ cb(new Error('not implemented'));
387
+
388
+ };
389
+
390
+ Writable.prototype._writev = null;
391
+
392
+ Writable.prototype.end = function(chunk, encoding, cb) {
393
+ var state = this._writableState;
394
+
395
+ if (util.isFunction(chunk)) {
396
+ cb = chunk;
397
+ chunk = null;
398
+ encoding = null;
399
+ } else if (util.isFunction(encoding)) {
400
+ cb = encoding;
401
+ encoding = null;
402
+ }
403
+
404
+ if (!util.isNullOrUndefined(chunk))
405
+ this.write(chunk, encoding);
406
+
407
+ // .end() fully uncorks
408
+ if (state.corked) {
409
+ state.corked = 1;
410
+ this.uncork();
411
+ }
412
+
413
+ // ignore unnecessary end() calls.
414
+ if (!state.ending && !state.finished)
415
+ endWritable(this, state, cb);
416
+ };
417
+
418
+
419
+ function needFinish(stream, state) {
420
+ return (state.ending &&
421
+ state.length === 0 &&
422
+ !state.finished &&
423
+ !state.writing);
424
+ }
425
+
426
+ function prefinish(stream, state) {
427
+ if (!state.prefinished) {
428
+ state.prefinished = true;
429
+ stream.emit('prefinish');
430
+ }
431
+ }
432
+
433
+ function finishMaybe(stream, state) {
434
+ var need = needFinish(stream, state);
435
+ if (need) {
436
+ if (state.pendingcb === 0) {
437
+ prefinish(stream, state);
438
+ state.finished = true;
439
+ stream.emit('finish');
440
+ } else
441
+ prefinish(stream, state);
442
+ }
443
+ return need;
444
+ }
445
+
446
+ function endWritable(stream, state, cb) {
447
+ state.ending = true;
448
+ finishMaybe(stream, state);
449
+ if (cb) {
450
+ if (state.finished)
451
+ process.nextTick(cb);
452
+ else
453
+ stream.once('finish', cb);
454
+ }
455
+ state.ended = true;
456
+ }