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,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
+ }