diff --git a/.travis.yml b/.travis.yml index 0c5d2bc262..40992555bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -46,18 +46,8 @@ matrix: env: TASK=test - node_js: 8 env: TASK=test - - node_js: 6 - env: TASK=browser BROWSER_NAME=ie BROWSER_VERSION="9..latest" - - node_js: 6 - env: TASK=browser BROWSER_NAME=opera BROWSER_VERSION="11..latest" - - node_js: 6 - env: TASK=browser BROWSER_NAME=chrome BROWSER_VERSION="-3..latest" - - node_js: 6 - env: TASK=browser BROWSER_NAME=firefox BROWSER_VERSION="-3..latest" - - node_js: 6 - env: TASK=browser BROWSER_NAME=safari BROWSER_VERSION="5..latest" - - node_js: 6 - env: TASK=browser BROWSER_NAME=microsoftedge BROWSER_VERSION=latest + - node_js: 9 + env: TASK=test script: "npm run $TASK" env: global: diff --git a/README.md b/README.md index 9235e26ce9..f0d8b47c13 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # readable-stream -***Node-core v8.1.3 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) +***Node-core v8.9.4 streams for userland*** [![Build Status](https://travis-ci.org/nodejs/readable-stream.svg?branch=master)](https://travis-ci.org/nodejs/readable-stream) [![NPM](https://nodei.co/npm/readable-stream.png?downloads=true&downloadRank=true)](https://nodei.co/npm/readable-stream/) @@ -18,7 +18,7 @@ npm install --save readable-stream This package is a mirror of the Streams2 and Streams3 implementations in Node-core. -Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.1.3/docs/api/stream.html). +Full documentation may be found on the [Node.js website](https://nodejs.org/dist/v8.9.4/docs/api/stream.html). If you want to guarantee a stable streams base, regardless of what version of Node you, or the users of your libraries are using, use **readable-stream** *only* and avoid the *"stream"* module in Node-core, for background see [this blogpost](http://r.va.gg/2014/06/why-i-dont-use-nodes-core-stream-module.html). diff --git a/build/build.js b/build/build.js index 2e7a027fb5..2580303c87 100644 --- a/build/build.js +++ b/build/build.js @@ -56,21 +56,30 @@ function processFile (inputLoc, out, replacements) { data = data.replace(regexp, arg2) }) if (inputLoc.slice(-3) === '.js') { - const transformed = babel.transform(data, { - plugins: [ - 'transform-es2015-parameters', - 'transform-es2015-arrow-functions', - 'transform-es2015-block-scoping', - 'transform-es2015-template-literals', - 'transform-es2015-shorthand-properties', - 'transform-es2015-for-of', - ['transform-es2015-classes', { loose: true }], - 'transform-es2015-destructuring', - 'transform-es2015-computed-properties', - 'transform-es2015-spread' - ] - }) - data = transformed.code + try { + const transformed = babel.transform(data, { + plugins: [ + 'transform-es2015-parameters', + 'transform-es2015-arrow-functions', + 'transform-es2015-block-scoping', + 'transform-es2015-template-literals', + 'transform-es2015-shorthand-properties', + 'transform-es2015-for-of', + ['transform-es2015-classes', { loose: true }], + 'transform-es2015-destructuring', + 'transform-es2015-computed-properties', + 'transform-es2015-spread' + ] + }) + data = transformed.code + } catch (err) { + fs.writeFile(out + '.errored.js', data, encoding, function () { + console.log('Wrote errored', out) + + throw err + }) + return + } } fs.writeFile(out, data, encoding, function (err) { if (err) throw err @@ -140,6 +149,8 @@ pump( file !== 'test-stream-base-no-abort.js' && file !== 'test-stream-preprocess.js' && file !== 'test-stream-inheritance.js' && + file !== 'test-stream-base-prototype-accessors.js' && + file !== 'test-stream-base-prototype-accessors-enumerability.js' && file !== 'test-stream-base-typechecking.js') { processTestFile(file) } @@ -150,11 +161,20 @@ pump( //-------------------------------------------------------------------- // Grab the nodejs/node test/common.js - processFile( - testsrcurl.replace(/parallel\/$/, 'common/index.js') - , path.join(testourroot, '../common.js') - , testReplace['common.js'] - ) + glob(path.join(src, 'test/common/*'), function (err, list) { + if (err) { + throw err + } + + list.forEach(function (file) { + file = path.basename(file) + processFile( + path.join(testsrcurl.replace(/parallel\/$/, 'common/'), file) + , path.join(testourroot.replace('parallel', 'common'), file) + , testReplace['common.js'] + ) + }) + }) //-------------------------------------------------------------------- // Update Node version in README diff --git a/build/common-replacements.js b/build/common-replacements.js index c2dd472456..e17f5d7910 100644 --- a/build/common-replacements.js +++ b/build/common-replacements.js @@ -8,7 +8,7 @@ module.exports.altForEachImplReplacement = [ ] module.exports.altForEachUseReplacement = [ - /(\W)([\w\.\(\),\[\]]+)(\.forEach\()/gm + /(\W)([\w\.\(\),\[\] ']+)(\.forEach\()/gm , '$1forEach($2, ' ] diff --git a/build/files.js b/build/files.js index ec2399e9b5..f386ddda5c 100644 --- a/build/files.js +++ b/build/files.js @@ -125,7 +125,7 @@ const headRegexp = /(^module.exports = \w+;?)/m , `$1 /**/ - var processNextTick = require(\'process-nextick-args\'); + var processNextTick = require(\'process-nextick-args\').nextTick; /**/ ` ] @@ -159,10 +159,11 @@ const headRegexp = /(^module.exports = \w+;?)/m ` ] , safeBufferFix = [ - /(?:var|const) Buffer = require\('buffer'\)\.Buffer;/, + /(?:var|const) (?:{ )Buffer(?: }) = require\('buffer'\)(?:\.Buffer)?;/, `/**/ - var Buffer = require('safe-buffer').Buffer -/**/` + var Buffer = require('safe-buffer').Buffer; +/**/ +` ] , internalDirectory = [ /require\('internal\/streams\/([a-zA-z]+)'\)/g, @@ -177,8 +178,8 @@ const headRegexp = /(^module.exports = \w+;?)/m , `function(er) { onwrite(stream, er); }` ] , addUintStuff = [ - /(?:var|const) Buffer = require\('buffer'\)\.Buffer;/ - , `/**/ + /(?:var|const) Buffer = require\('safe-buffer'\)\.Buffer;/ + , ` const Buffer = require('safe-buffer').Buffer const OurUint8Array = global.Uint8Array || function () {} function _uint8ArrayToBuffer(chunk) { @@ -187,7 +188,6 @@ function _uint8ArrayToBuffer(chunk) { function _isUint8Array(obj) { return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; } -/**/ ` ] , addConstructors = [ @@ -276,6 +276,7 @@ module.exports['_stream_readable.js'] = [ , processNextTickReplacement , eventEmittterListenerCountReplacement , internalDirectory + , safeBufferFix , fixUintStuff , addUintStuff ] @@ -310,6 +311,7 @@ module.exports['_stream_writable.js'] = [ , fixInstanceCheck , removeOnWriteBind , internalDirectory + , safeBufferFix , fixUintStuff , addUintStuff , fixBufferCheck @@ -317,9 +319,28 @@ module.exports['_stream_writable.js'] = [ , useCorkedRequest , addConstructors ] + module.exports['internal/streams/BufferList.js'] = [ - safeBufferFix + [ + /(?:var|const) (?:{ )Buffer(?: }) = require\('buffer'\)(?:\.Buffer)?;/, + ` +const Buffer = require('safe-buffer').Buffer +const util = require('util') + ` + ] , fixCopyBuffer + , [ + /$/, + ` + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + const obj = util.inspect({ length: this.length }); + return \`\${this.constructor.name} \${obj}\`; + } +} +` + ] ] module.exports['internal/streams/destroy.js'] = [ diff --git a/build/package.json b/build/package.json index a72e400a0c..cf2a76902f 100644 --- a/build/package.json +++ b/build/package.json @@ -4,9 +4,9 @@ "description": "", "main": "build.js", "dependencies": { - "babel-core": "^6.24.1", + "babel-core": "^6.26.0", "babel-plugin-transform-es2015-arrow-functions": "^6.5.2", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", + "babel-plugin-transform-es2015-block-scoping": "^6.26.0", "babel-plugin-transform-es2015-classes": "^6.24.1", "babel-plugin-transform-es2015-computed-properties": "^6.24.1", "babel-plugin-transform-es2015-destructuring": "^6.18.0", @@ -17,10 +17,10 @@ "babel-plugin-transform-es2015-template-literals": "^6.8.0", "bl": "^1.2.1", "glob": "^7.1.2", - "gunzip-maybe": "^1.4.0", - "hyperquest": "^2.1.2", - "pump": "^1.0.2", - "rimraf": "^2.6.1", - "tar-fs": "^1.15.2" + "gunzip-maybe": "^1.4.1", + "hyperquest": "^2.1.3", + "pump": "^3.0.0", + "rimraf": "^2.6.2", + "tar-fs": "^1.16.0" } } diff --git a/build/test-replacements.js b/build/test-replacements.js index ce8be65161..61ee998586 100644 --- a/build/test-replacements.js +++ b/build/test-replacements.js @@ -161,7 +161,7 @@ module.exports['common.js'] = [ ], [ /require\(['"]stream['"]\)/g - , 'require(\'../\')' + , 'require(\'../../\')' ], [ /^var util = require\('util'\);/m @@ -194,8 +194,13 @@ module.exports['common.js'] = [ '}).enable();*/' ], [ - /const async_wrap = process.binding\('async_wrap'\);/, - '//const async_wrap = process.binding(\'async_wrap\');' + /(?:var|const) async_wrap = process\.binding\('async_wrap'\);\n.*(?:var|const) (?:{ )?kCheck(?: })? = async_wrap\.constants(?:\.kCheck)?;/gm, + '// const async_wrap = process.binding(\'async_wrap\');\n' + + ' // const kCheck = async_wrap.constants.kCheck;' +], +[ + /async_wrap\.async_hook_fields\[kCheck\] \+= 1;/, + '// async_wrap.async_hook_fields[kCheck] += 1;' ] ] diff --git a/lib/_stream_duplex.js b/lib/_stream_duplex.js index c599463dd8..4f2556acad 100644 --- a/lib/_stream_duplex.js +++ b/lib/_stream_duplex.js @@ -28,7 +28,7 @@ /**/ -var processNextTick = require('process-nextick-args'); +var processNextTick = require('process-nextick-args').nextTick; /**/ /**/ diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index ee9001cdf0..1002199adf 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -23,7 +23,7 @@ /**/ -var processNextTick = require('process-nextick-args'); +var processNextTick = require('process-nextick-args').nextTick; /**/ module.exports = Readable; @@ -50,9 +50,8 @@ var EElistenerCount = function (emitter, type) { var Stream = require('./internal/streams/stream'); /**/ -// TODO(bmeurer): Change this back to const once hole checks are -// properly optimized away early in Ignition+TurboFan. /**/ + var Buffer = require('safe-buffer').Buffer; var OurUint8Array = global.Uint8Array || function () {}; function _uint8ArrayToBuffer(chunk) { @@ -61,6 +60,7 @@ function _uint8ArrayToBuffer(chunk) { function _isUint8Array(obj) { return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; } + /**/ /**/ @@ -89,15 +89,13 @@ var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; function prependListener(emitter, event, fn) { // Sadly this is not cacheable as some libraries bundle their own // event emitter implementation with them. - if (typeof emitter.prependListener === 'function') { - return emitter.prependListener(event, fn); - } else { - // This is a hack to make sure that our error handler is attached before any - // userland ones. NEVER DO THIS. This is here only because this code needs - // to continue to work with older versions of Node.js that do not include - // the prependListener() method. The goal is to eventually remove this hack. - if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; - } + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; } function ReadableState(options, stream) { @@ -105,17 +103,26 @@ function ReadableState(options, stream) { options = options || {}; + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + // object stream flag. Used to make read(n) ignore n and to // make all the buffer merging and length checks go away this.objectMode = !!options.objectMode; - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; // the point at which it stops calling _read() to fill the buffer // Note: 0 is a valid value, means "don't call _read preemptively ever" var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; // cast to ints. this.highWaterMark = Math.floor(this.highWaterMark); @@ -810,18 +817,19 @@ function flow(stream) { // This is *not* part of the readable stream interface. // It is an ugly unfortunate mess of history. Readable.prototype.wrap = function (stream) { + var _this = this; + var state = this._readableState; var paused = false; - var self = this; stream.on('end', function () { debug('wrapped end'); if (state.decoder && !state.ended) { var chunk = state.decoder.end(); - if (chunk && chunk.length) self.push(chunk); + if (chunk && chunk.length) _this.push(chunk); } - self.push(null); + _this.push(null); }); stream.on('data', function (chunk) { @@ -831,7 +839,7 @@ Readable.prototype.wrap = function (stream) { // don't skip over falsy values in objectMode if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; - var ret = self.push(chunk); + var ret = _this.push(chunk); if (!ret) { paused = true; stream.pause(); @@ -852,12 +860,12 @@ Readable.prototype.wrap = function (stream) { // proxy certain important events. for (var n = 0; n < kProxyEvents.length; n++) { - stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n])); + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); } // when we try to consume some more bytes, simply unpause the // underlying stream. - self._read = function (n) { + this._read = function (n) { debug('wrapped _read', n); if (paused) { paused = false; @@ -865,7 +873,7 @@ Readable.prototype.wrap = function (stream) { } }; - return self; + return this; }; // exposed for testing purposes only. diff --git a/lib/_stream_transform.js b/lib/_stream_transform.js index a0c23173da..5d1f8b876d 100644 --- a/lib/_stream_transform.js +++ b/lib/_stream_transform.js @@ -74,39 +74,28 @@ util.inherits = require('inherits'); util.inherits(Transform, Duplex); -function TransformState(stream) { - this.afterTransform = function (er, data) { - return afterTransform(stream, er, data); - }; - - this.needTransform = false; - this.transforming = false; - this.writecb = null; - this.writechunk = null; - this.writeencoding = null; -} - -function afterTransform(stream, er, data) { - var ts = stream._transformState; +function afterTransform(er, data) { + var ts = this._transformState; ts.transforming = false; var cb = ts.writecb; if (!cb) { - return stream.emit('error', new Error('write callback called multiple times')); + return this.emit('error', new Error('write callback called multiple times')); } ts.writechunk = null; ts.writecb = null; - if (data !== null && data !== undefined) stream.push(data); + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); cb(er); - var rs = stream._readableState; + var rs = this._readableState; rs.reading = false; if (rs.needReadable || rs.length < rs.highWaterMark) { - stream._read(rs.highWaterMark); + this._read(rs.highWaterMark); } } @@ -115,9 +104,14 @@ function Transform(options) { Duplex.call(this, options); - this._transformState = new TransformState(this); - - var stream = this; + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; // start out asking for a readable event once data is transformed. this._readableState.needReadable = true; @@ -134,11 +128,19 @@ function Transform(options) { } // When the writable side finishes, then flush out anything remaining. - this.once('prefinish', function () { - if (typeof this._flush === 'function') this._flush(function (er, data) { - done(stream, er, data); - });else done(stream); - }); + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } } Transform.prototype.push = function (chunk, encoding) { @@ -188,27 +190,25 @@ Transform.prototype._read = function (n) { }; Transform.prototype._destroy = function (err, cb) { - var _this = this; + var _this2 = this; Duplex.prototype._destroy.call(this, err, function (err2) { cb(err2); - _this.emit('close'); + _this2.emit('close'); }); }; function done(stream, er, data) { if (er) return stream.emit('error', er); - if (data !== null && data !== undefined) stream.push(data); + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); // if there's nothing in the write buffer, then that means // that nothing more will ever be provided - var ws = stream._writableState; - var ts = stream._transformState; - - if (ws.length) throw new Error('Calling transform done when ws.length != 0'); + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); - if (ts.transforming) throw new Error('Calling transform done when still transforming'); + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); return stream.push(null); } \ No newline at end of file diff --git a/lib/_stream_writable.js b/lib/_stream_writable.js index d20da88c75..95125f927f 100644 --- a/lib/_stream_writable.js +++ b/lib/_stream_writable.js @@ -27,7 +27,7 @@ /**/ -var processNextTick = require('process-nextick-args'); +var processNextTick = require('process-nextick-args').nextTick; /**/ module.exports = Writable; @@ -79,6 +79,7 @@ var Stream = require('./internal/streams/stream'); /**/ /**/ + var Buffer = require('safe-buffer').Buffer; var OurUint8Array = global.Uint8Array || function () {}; function _uint8ArrayToBuffer(chunk) { @@ -87,6 +88,7 @@ function _uint8ArrayToBuffer(chunk) { function _isUint8Array(obj) { return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; } + /**/ var destroyImpl = require('./internal/streams/destroy'); @@ -100,18 +102,27 @@ function WritableState(options, stream) { options = options || {}; + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + // object stream flag to indicate whether or not this stream // contains buffers or objects. this.objectMode = !!options.objectMode; - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; // the point at which write() starts returning false // Note: 0 is a valid value, means that we always return false if // the entire buffer is not flushed immediately on write() var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; // cast to ints. this.highWaterMark = Math.floor(this.highWaterMark); @@ -225,6 +236,7 @@ if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.protot Object.defineProperty(Writable, Symbol.hasInstance, { value: function (object) { if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; return object && object._writableState instanceof WritableState; } @@ -302,7 +314,7 @@ function validChunk(stream, state, chunk, cb) { Writable.prototype.write = function (chunk, encoding, cb) { var state = this._writableState; var ret = false; - var isBuf = _isUint8Array(chunk) && !state.objectMode; + var isBuf = !state.objectMode && _isUint8Array(chunk); if (isBuf && !Buffer.isBuffer(chunk)) { chunk = _uint8ArrayToBuffer(chunk); @@ -514,6 +526,7 @@ function clearBuffer(stream, state) { } else { state.corkedRequestsFree = new CorkedRequest(state); } + state.bufferedRequestCount = 0; } else { // Slow case, write chunks one-by-one while (entry) { @@ -524,6 +537,7 @@ function clearBuffer(stream, state) { doWrite(stream, state, false, len, chunk, encoding, cb); entry = entry.next; + state.bufferedRequestCount--; // if we didn't call the onwrite immediately, then // it means that we need to wait until it does. // also, that means that the chunk and cb are currently @@ -536,7 +550,6 @@ function clearBuffer(stream, state) { if (entry === null) state.lastBufferedRequest = null; } - state.bufferedRequestCount = 0; state.bufferedRequest = entry; state.bufferProcessing = false; } diff --git a/lib/internal/streams/BufferList.js b/lib/internal/streams/BufferList.js index d467615978..aefc68bd90 100644 --- a/lib/internal/streams/BufferList.js +++ b/lib/internal/streams/BufferList.js @@ -1,11 +1,9 @@ 'use strict'; -/**/ - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Buffer = require('safe-buffer').Buffer; -/**/ +var util = require('util'); function copyBuffer(src, target, offset) { src.copy(target, offset); @@ -71,4 +69,11 @@ module.exports = function () { }; return BufferList; -}(); \ No newline at end of file +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} \ No newline at end of file diff --git a/lib/internal/streams/destroy.js b/lib/internal/streams/destroy.js index b3e58c33bc..134cabf893 100644 --- a/lib/internal/streams/destroy.js +++ b/lib/internal/streams/destroy.js @@ -2,7 +2,7 @@ /**/ -var processNextTick = require('process-nextick-args'); +var processNextTick = require('process-nextick-args').nextTick; /**/ // undocumented cb() API, needed for core, not for public API @@ -18,7 +18,7 @@ function destroy(err, cb) { } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { processNextTick(emitErrorNT, this, err); } - return; + return this; } // we set destroyed to true before firing error callbacks in order @@ -43,6 +43,8 @@ function destroy(err, cb) { cb(err); } }); + + return this; } function undestroy() { diff --git a/package.json b/package.json index 5e0c78e286..5640f3b95e 100644 --- a/package.json +++ b/package.json @@ -7,19 +7,19 @@ "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", + "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.0.3", "util-deprecate": "~1.0.1" }, "devDependencies": { - "assert": "~1.4.0", + "assert": "^1.4.0", "babel-polyfill": "^6.9.1", "buffer": "^4.9.0", "nyc": "^6.4.0", - "tap": "~0.7.1", - "tape": "~4.5.1", - "zuul": "~3.10.0" + "tap": "^0.7.0", + "tape": "^4.8.0", + "zuul": "^3.11.1" }, "scripts": { "test": "tap test/parallel/*.js test/ours/*.js && node test/verify-dependencies.js", diff --git a/test/common/README.md b/test/common/README.md new file mode 100644 index 0000000000..0e25d983de --- /dev/null +++ b/test/common/README.md @@ -0,0 +1,541 @@ +/**/ + require('babel-polyfill'); + var util = require('util'); + for (var i in util) exports[i] = util[i]; + /**//**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +# Node.js Core Test Common Modules + +This directory contains modules used to test the Node.js implementation. + +## Table of Contents + +* [Benchmark module](#benchmark-module) +* [Common module API](#common-module-api) +* [Countdown module](#countdown-module) +* [DNS module](#dns-module) +* [Duplex pair helper](#duplex-pair-helper) +* [Fixtures module](#fixtures-module) +* [WPT module](#wpt-module) + +## Benchmark Module + +The `benchmark` module is used by tests to run benchmarks. + +### runBenchmark(name, args, env) + +* `name` [<String>] Name of benchmark suite to be run. +* `args` [<Array>] Array of environment variable key/value pairs (ex: + `n=1`) to be applied via `--set`. +* `env` [<Object>] Environment variables to be applied during the run. + +## Common Module API + +The `common` module is used by tests for consistency across repeated +tasks. + +### allowGlobals(...whitelist) +* `whitelist` [<Array>] Array of Globals +* return [<Array>] + +Takes `whitelist` and concats that with predefined `knownGlobals`. + +### arrayStream +A stream to push an array into a REPL + +### busyLoop(time) +* `time` [<Number>] + +Blocks for `time` amount of time. + +### canCreateSymLink() +* return [<Boolean>] + +Checks whether the current running process can create symlinks. On Windows, this +returns `false` if the process running doesn't have privileges to create +symlinks +([SeCreateSymbolicLinkPrivilege](https://msdn.microsoft.com/en-us/library/windows/desktop/bb530716(v=vs.85).aspx)). +On non-Windows platforms, this always returns `true`. + +### crashOnUnhandledRejection() + +Installs a `process.on('unhandledRejection')` handler that crashes the process +after a tick. This is useful for tests that use Promises and need to make sure +no unexpected rejections occur, because currently they result in silent +failures. + +### ddCommand(filename, kilobytes) +* return [<Object>] + +Platform normalizes the `dd` command + +### enoughTestMem +* [<Boolean>] + +Indicates if there is more than 1gb of total memory. + +### expectsError([fn, ]settings[, exact]) +* `fn` [<Function>] a function that should throw. +* `settings` [<Object>] + that must contain the `code` property plus any of the other following + properties (some properties only apply for `AssertionError`): + * `code` [<String>] + expected error must have this value for its `code` property. + * `type` [<Function>] + expected error must be an instance of `type` and must be an Error subclass. + * `message` [<String>] or [<RegExp>] + if a string is provided for `message`, expected error must have it for its + `message` property; if a regular expression is provided for `message`, the + regular expression must match the `message` property of the expected error. + * `name` [<String>] + expected error must have this value for its `name` property. + * `generatedMessage` [<String>] + (`AssertionError` only) expected error must have this value for its + `generatedMessage` property. + * `actual` <any> + (`AssertionError` only) expected error must have this value for its + `actual` property. + * `expected` <any> + (`AssertionError` only) expected error must have this value for its + `expected` property. + * `operator` <any> + (`AssertionError` only) expected error must have this value for its + `operator` property. +* `exact` [<Number>] default = 1 +* return [<Function>] + + If `fn` is provided, it will be passed to `assert.throws` as first argument + and `undefined` will be returned. + Otherwise a function suitable as callback or for use as a validation function + passed as the second argument to `assert.throws()` will be returned. If the + returned function has not been called exactly `exact` number of times when the + test is complete, then the test will fail. + +### expectWarning(name, expected) +* `name` [<String>] +* `expected` [<String>] | [<Array>] + +Tests whether `name` and `expected` are part of a raised warning. + +### fileExists(pathname) +* pathname [<String>] +* return [<Boolean>] + +Checks if `pathname` exists + +### fires(promise, [error], [timeoutMs]) +* promise [<Promise] +* error [<String] default = 'timeout' +* timeoutMs [<Number] default = 100 + +Returns a new promise that will propagate `promise` resolution or rejection if +that happens within the `timeoutMs` timespan, or rejects with `error` as +a reason otherwise. + +### getArrayBufferViews(buf) +* `buf` [<Buffer>] +* return [<ArrayBufferView[]>] + +Returns an instance of all possible `ArrayBufferView`s of the provided Buffer. + +### getCallSite(func) +* `func` [<Function>] +* return [<String>] + +Returns the file name and line number for the provided Function. + +### globalCheck +* [<Boolean>] + +Set to `false` if the test should not check for global leaks. + +### hasCrypto +* [<Boolean>] + +Indicates whether OpenSSL is available. + +### hasFipsCrypto +* [<Boolean>] + +Indicates `hasCrypto` and `crypto` with fips. + +### hasIntl +* [<Boolean>] + +Indicates if [internationalization] is supported. + +### hasSmallICU +* [<Boolean>] + +Indicates `hasIntl` and `small-icu` are supported. + +### hasIPv6 +* [<Boolean>] + +Indicates whether `IPv6` is supported on this platform. + +### hasMultiLocalhost +* [<Boolean>] + +Indicates if there are multiple localhosts available. + +### hijackStderr(listener) +* `listener` [<Function>]: a listener with a single parameter + called `data`. + +Eavesdrop to `process.stderr.write` calls. Once `process.stderr.write` is +called, `listener` will also be called and the `data` of `write` function will +be passed to `listener`. What's more, `process.stderr.writeTimes` is a count of +the number of calls. + +### hijackStdout(listener) +* `listener` [<Function>]: a listener with a single parameter + called `data`. + +Eavesdrop to `process.stdout.write` calls. Once `process.stdout.write` is +called, `listener` will also be called and the `data` of `write` function will +be passed to `listener`. What's more, `process.stdout.writeTimes` is a count of +the number of calls. + +### inFreeBSDJail +* [<Boolean>] + +Checks whether free BSD Jail is true or false. + +### isAIX +* [<Boolean>] + +Platform check for Advanced Interactive eXecutive (AIX). + +### isAlive(pid) +* `pid` [<Number>] +* return [<Boolean>] + +Attempts to 'kill' `pid` + +### isFreeBSD +* [<Boolean>] + +Platform check for Free BSD. + +### isLinux +* [<Boolean>] + +Platform check for Linux. + +### isLinuxPPCBE +* [<Boolean>] + +Platform check for Linux on PowerPC. + +### isOSX +* [<Boolean>] + +Platform check for macOS. + +### isSunOS +* [<Boolean>] + +Platform check for SunOS. + +### isWindows +* [<Boolean>] + +Platform check for Windows. + +### isWOW64 +* [<Boolean>] + +Platform check for Windows 32-bit on Windows 64-bit. + +### leakedGlobals() +* return [<Array>] + +Indicates whether any globals are not on the `knownGlobals` list. + +### localhostIPv4 +* [<String>] + +IP of `localhost`. + +### localIPv6Hosts +* [<Array>] + +Array of IPV6 representations for `localhost`. + +### mustCall([fn][, exact]) +* `fn` [<Function>] default = () => {} +* `exact` [<Number>] default = 1 +* return [<Function>] + +Returns a function that calls `fn`. If the returned function has not been called +exactly `exact` number of times when the test is complete, then the test will +fail. + +If `fn` is not provided, an empty function will be used. + +### mustCallAtLeast([fn][, minimum]) +* `fn` [<Function>] default = () => {} +* `minimum` [<Number>] default = 1 +* return [<Function>] + +Returns a function that calls `fn`. If the returned function has not been called +at least `minimum` number of times when the test is complete, then the test will +fail. + +If `fn` is not provided, an empty function will be used. + +### mustNotCall([msg]) +* `msg` [<String>] default = 'function should not have been called' +* return [<Function>] + +Returns a function that triggers an `AssertionError` if it is invoked. `msg` is +used as the error message for the `AssertionError`. + +### nodeProcessAborted(exitCode, signal) +* `exitCode` [<Number>] +* `signal` [<String>] +* return [<Boolean>] + +Returns `true` if the exit code `exitCode` and/or signal name `signal` represent +the exit code and/or signal name of a node process that aborted, `false` +otherwise. + +### opensslCli +* [<Boolean>] + +Indicates whether 'opensslCli' is supported. + +### platformTimeout(ms) +* `ms` [<Number>] +* return [<Number>] + +Platform normalizes timeout. + +### PIPE +* [<String>] + +Path to the test socket. + +### PORT +* [<Number>] + +A port number for tests to use if one is needed. + +### printSkipMessage(msg) +* `msg` [<String>] + +Logs '1..0 # Skipped: ' + `msg` + +### refreshTmpDir() +* return [<String>] + +Deletes the testing 'tmp' directory and recreates it. + +### restoreStderr() + +Restore the original `process.stderr.write`. Used to restore `stderr` to its +original state after calling [`common.hijackStdErr()`][]. + +### restoreStdout() + +Restore the original `process.stdout.write`. Used to restore `stdout` to its +original state after calling [`common.hijackStdOut()`][]. + +### rootDir +* [<String>] + +Path to the 'root' directory. either `/` or `c:\\` (windows) + +### projectDir +* [<String>] + +Path to the project directory. + +### skip(msg) +* `msg` [<String>] + +Logs '1..0 # Skipped: ' + `msg` and exits with exit code `0`. + +### skipIfInspectorDisabled() + +Skip the rest of the tests in the current file when the Inspector +was disabled at compile time. + +### skipIf32Bits() + +Skip the rest of the tests in the current file when the Node.js executable +was compiled with a pointer size smaller than 64 bits. + +### spawnPwd(options) +* `options` [<Object>] +* return [<Object>] + +Platform normalizes the `pwd` command. + +### spawnSyncPwd(options) +* `options` [<Object>] +* return [<Object>] + +Synchronous version of `spawnPwd`. + +### tmpDir +* [<String>] + +The realpath of the 'tmp' directory. + +## Countdown Module + +The `Countdown` module provides a simple countdown mechanism for tests that +require a particular action to be taken after a given number of completed +tasks (for instance, shutting down an HTTP server after a specific number of +requests). + + +```js +const Countdown = require('../common/countdown'); + +function doSomething() { + console.log('.'); +} + +const countdown = new Countdown(2, doSomething); +countdown.dec(); +countdown.dec(); +``` + +### new Countdown(limit, callback) + +* `limit` {number} +* `callback` {function} + +Creates a new `Countdown` instance. + +### Countdown.prototype.dec() + +Decrements the `Countdown` counter. + +### Countdown.prototype.remaining + +Specifies the remaining number of times `Countdown.prototype.dec()` must be +called before the callback is invoked. + +## DNS Module + +The `DNS` module provides a naïve DNS parser/serializer. + +### readDomainFromPacket(buffer, offset) + +* `buffer` [<Buffer>] +* `offset` [<Number>] +* return [<Object>] + +Reads the domain string from a packet and returns an object containing the +number of bytes read and the domain. + +### parseDNSPacket(buffer) + +* `buffer` [<Buffer>] +* return [<Object>] + +Parses a DNS packet. Returns an object with the values of the various flags of +the packet depending on the type of packet. + +### writeIPv6(ip) + +* `ip` [<String>] +* return [<Buffer>] + +Reads an IPv6 String and returns a Buffer containing the parts. + +### writeDomainName(domain) + +* `domain` [<String>] +* return [<Buffer>] + +Reads a Domain String and returns a Buffer containing the domain. + +### writeDNSPacket(parsed) + +* `parsed` [<Object>] +* return [<Buffer>] + +Takes in a parsed Object and writes its fields to a DNS packet as a Buffer +object. + +## Duplex pair helper + +The `common/duplexpair` module exports a single function `makeDuplexPair`, +which returns an object `{ clientSide, serverSide }` where each side is a +`Duplex` stream connected to the other side. + +There is no difference between client or server side beyond their names. + +## Fixtures Module + +The `common/fixtures` module provides convenience methods for working with +files in the `test/fixtures` directory. + +### fixtures.fixturesDir + +* [<String>] + +The absolute path to the `test/fixtures/` directory. + +### fixtures.path(...args) + +* `...args` [<String>] + +Returns the result of `path.join(fixtures.fixturesDir, ...args)`. + +### fixtures.readSync(args[, enc]) + +* `args` [<String>] | [<Array>] + +Returns the result of +`fs.readFileSync(path.join(fixtures.fixturesDir, ...args), 'enc')`. + +### fixtures.readKey(arg[, enc]) + +* `arg` [<String>] + +Returns the result of +`fs.readFileSync(path.join(fixtures.fixturesDir, 'keys', arg), 'enc')`. + +## WPT Module + +The wpt.js module is a port of parts of +[W3C testharness.js](https://github.com/w3c/testharness.js) for testing the +Node.js +[WHATWG URL API](https://nodejs.org/api/url.html#url_the_whatwg_url_api) +implementation with tests from +[W3C Web Platform Tests](https://github.com/w3c/web-platform-tests). + +[<Array>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array +[<ArrayBufferView[]>]: https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView +[<Boolean>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type +[<Buffer>]: https://nodejs.org/api/buffer.html#buffer_class_buffer +[<Function>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function +[<Number>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type +[<Object>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object +[<RegExp>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp +[<String>]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type +[`common.hijackStdErr()`]: #hijackstderrlistener +[`common.hijackStdOut()`]: #hijackstdoutlistener +[internationalization]: https://github.com/nodejs/node/wiki/Intl + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} diff --git a/test/common/benchmark.js b/test/common/benchmark.js new file mode 100644 index 0000000000..555dc620f4 --- /dev/null +++ b/test/common/benchmark.js @@ -0,0 +1,62 @@ +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ + +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var assert = require('assert'); +var fork = require('child_process').fork; +var path = require('path'); + +var runjs = path.join(__dirname, '..', '..', 'benchmark', 'run.js'); + +function runBenchmark(name, args, env) { + var argv = []; + + for (var _i = 0; _i < args.length; _i++) { + argv.push('--set'); + argv.push(args[_i]); + } + + argv.push(name); + + var mergedEnv = Object.assign({}, process.env, env); + + var child = fork(runjs, argv, { env: mergedEnv }); + child.on('exit', function (code, signal) { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + }); +} + +module.exports = runBenchmark; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common/countdown.js b/test/common/countdown.js new file mode 100644 index 0000000000..411fb69d2e --- /dev/null +++ b/test/common/countdown.js @@ -0,0 +1,70 @@ +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var assert = require('assert'); +var kLimit = Symbol('limit'); +var kCallback = Symbol('callback'); + +var Countdown = function () { + function Countdown(limit, cb) { + _classCallCheck(this, Countdown); + + assert.strictEqual(typeof limit, 'number'); + assert.strictEqual(typeof cb, 'function'); + this[kLimit] = limit; + this[kCallback] = cb; + } + + Countdown.prototype.dec = function dec() { + assert(this[kLimit] > 0, 'Countdown expired'); + if (--this[kLimit] === 0) this[kCallback](); + return this[kLimit]; + }; + + _createClass(Countdown, [{ + key: 'remaining', + get: function () { + return this[kLimit]; + } + }]); + + return Countdown; +}(); + +module.exports = Countdown; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common/dns.js b/test/common/dns.js new file mode 100644 index 0000000000..388c8df83d --- /dev/null +++ b/test/common/dns.js @@ -0,0 +1,418 @@ +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +// Naïve DNS parser/serializer. + +var assert = require('assert'); +var os = require('os'); + +var types = { + A: 1, + AAAA: 28, + NS: 2, + CNAME: 5, + SOA: 6, + PTR: 12, + MX: 15, + TXT: 16, + ANY: 255 +}; + +var classes = { + IN: 1 +}; + +function readDomainFromPacket(buffer, offset) { + assert.ok(offset < buffer.length); + var length = buffer[offset]; + if (length === 0) { + return { nread: 1, domain: '' }; + } else if ((length & 0xC0) === 0) { + offset += 1; + var chunk = buffer.toString('ascii', offset, offset + length); + // Read the rest of the domain. + + var _readDomainFromPacket = readDomainFromPacket(buffer, offset + length), + nread = _readDomainFromPacket.nread, + domain = _readDomainFromPacket.domain; + + return { + nread: 1 + length + nread, + domain: domain ? chunk + '.' + domain : chunk + }; + } else { + // Pointer to another part of the packet. + assert.strictEqual(length & 0xC0, 0xC0); + // eslint-disable-next-line + var pointeeOffset = buffer.readUInt16BE(offset) & ~0xC000; + return { + nread: 2, + domain: readDomainFromPacket(buffer, pointeeOffset) + }; + } +} + +function parseDNSPacket(buffer) { + assert.ok(buffer.length > 12); + + var parsed = { + id: buffer.readUInt16BE(0), + flags: buffer.readUInt16BE(2) + }; + + var counts = [['questions', buffer.readUInt16BE(4)], ['answers', buffer.readUInt16BE(6)], ['authorityAnswers', buffer.readUInt16BE(8)], ['additionalRecords', buffer.readUInt16BE(10)]]; + + var offset = 12; + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = counts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var _step$value = _slicedToArray(_step.value, 2), + sectionName = _step$value[0], + count = _step$value[1]; + + parsed[sectionName] = []; + for (var _i = 0; _i < count; ++_i) { + var _readDomainFromPacket2 = readDomainFromPacket(buffer, offset), + nread = _readDomainFromPacket2.nread, + domain = _readDomainFromPacket2.domain; + + offset += nread; + + var type = buffer.readUInt16BE(offset); + + var rr = { + domain: domain, + cls: buffer.readUInt16BE(offset + 2) + }; + offset += 4; + + for (var name in types) { + if (types[name] === type) rr.type = name; + } + + if (sectionName !== 'questions') { + rr.ttl = buffer.readInt32BE(offset); + var dataLength = buffer.readUInt16BE(offset); + offset += 6; + + switch (type) { + case types.A: + assert.strictEqual(dataLength, 4); + rr.address = buffer[offset + 0] + '.' + buffer[offset + 1] + '.' + (buffer[offset + 2] + '.' + buffer[offset + 3]); + break; + case types.AAAA: + assert.strictEqual(dataLength, 16); + rr.address = buffer.toString('hex', offset, offset + 16).replace(/(.{4}(?!$))/g, '$1:'); + break; + case types.TXT: + { + var position = offset; + rr.entries = []; + while (position < offset + dataLength) { + var txtLength = buffer[offset]; + rr.entries.push(buffer.toString('utf8', position + 1, position + 1 + txtLength)); + position += 1 + txtLength; + } + assert.strictEqual(position, offset + dataLength); + break; + } + case types.MX: + { + rr.priority = buffer.readInt16BE(buffer, offset); + offset += 2; + + var _readDomainFromPacket3 = readDomainFromPacket(buffer, offset), + _nread = _readDomainFromPacket3.nread, + _domain = _readDomainFromPacket3.domain; + + rr.exchange = _domain; + assert.strictEqual(_nread, dataLength); + break; + } + case types.NS: + case types.CNAME: + case types.PTR: + { + var _readDomainFromPacket4 = readDomainFromPacket(buffer, offset), + _nread2 = _readDomainFromPacket4.nread, + _domain2 = _readDomainFromPacket4.domain; + + rr.value = _domain2; + assert.strictEqual(_nread2, dataLength); + break; + } + case types.SOA: + { + var mname = readDomainFromPacket(buffer, offset); + var rname = readDomainFromPacket(buffer, offset + mname.nread); + rr.nsname = mname.domain; + rr.hostmaster = rname.domain; + var trailerOffset = offset + mname.nread + rname.nread; + rr.serial = buffer.readUInt32BE(trailerOffset); + rr.refresh = buffer.readUInt32BE(trailerOffset + 4); + rr.retry = buffer.readUInt32BE(trailerOffset + 8); + rr.expire = buffer.readUInt32BE(trailerOffset + 12); + rr.minttl = buffer.readUInt32BE(trailerOffset + 16); + + assert.strictEqual(trailerOffset + 20, dataLength); + break; + } + default: + throw new Error('Unknown RR type ' + rr.type); + } + offset += dataLength; + } + + parsed[sectionName].push(rr); + + assert.ok(offset <= buffer.length); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + assert.strictEqual(offset, buffer.length); + return parsed; +} + +function writeIPv6(ip) { + var parts = ip.replace(/^:|:$/g, '').split(':'); + var buf = Buffer.alloc(16); + + var offset = 0; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = parts[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var part = _step2.value; + + if (part === '') { + offset += 16 - 2 * (parts.length - 1); + } else { + buf.writeUInt16BE(parseInt(part, 16), offset); + offset += 2; + } + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + return buf; +} + +function writeDomainName(domain) { + return Buffer.concat(domain.split('.').map(function (label) { + assert(label.length < 64); + return Buffer.concat([Buffer.from([label.length]), Buffer.from(label, 'ascii')]); + }).concat([Buffer.alloc(1)])); +} + +function writeDNSPacket(parsed) { + var buffers = []; + var kStandardResponseFlags = 0x8180; + + buffers.push(new Uint16Array([parsed.id, parsed.flags === undefined ? kStandardResponseFlags : parsed.flags, parsed.questions && parsed.questions.length, parsed.answers && parsed.answers.length, parsed.authorityAnswers && parsed.authorityAnswers.length, parsed.additionalRecords && parsed.additionalRecords.length])); + + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = parsed.questions[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var q = _step3.value; + + assert(types[q.type]); + buffers.push(writeDomainName(q.domain)); + buffers.push(new Uint16Array([types[q.type], q.cls === undefined ? classes.IN : q.cls])); + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + var _iteratorNormalCompletion4 = true; + var _didIteratorError4 = false; + var _iteratorError4 = undefined; + + try { + for (var _iterator4 = [].concat(parsed.answers, parsed.authorityAnswers, parsed.additionalRecords)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { + var rr = _step4.value; + + if (!rr) continue; + + assert(types[rr.type]); + buffers.push(writeDomainName(rr.domain)); + buffers.push(new Uint16Array([types[rr.type], rr.cls === undefined ? classes.IN : rr.cls])); + buffers.push(new Int32Array([rr.ttl])); + + var rdLengthBuf = new Uint16Array(1); + buffers.push(rdLengthBuf); + + switch (rr.type) { + case 'A': + rdLengthBuf[0] = 4; + buffers.push(new Uint8Array(rr.address.split('.'))); + break; + case 'AAAA': + rdLengthBuf[0] = 16; + buffers.push(writeIPv6(rr.address)); + break; + case 'TXT': + var total = rr.entries.map(function (s) { + return s.length; + }).reduce(function (a, b) { + return a + b; + }); + // Total length of all strings + 1 byte each for their lengths. + rdLengthBuf[0] = rr.entries.length + total; + var _iteratorNormalCompletion5 = true; + var _didIteratorError5 = false; + var _iteratorError5 = undefined; + + try { + for (var _iterator5 = rr.entries[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { + var txt = _step5.value; + + buffers.push(new Uint8Array([Buffer.byteLength(txt)])); + buffers.push(Buffer.from(txt)); + } + } catch (err) { + _didIteratorError5 = true; + _iteratorError5 = err; + } finally { + try { + if (!_iteratorNormalCompletion5 && _iterator5.return) { + _iterator5.return(); + } + } finally { + if (_didIteratorError5) { + throw _iteratorError5; + } + } + } + + break; + case 'MX': + rdLengthBuf[0] = 2; + buffers.push(new Uint16Array([rr.priority])); + // fall through + case 'NS': + case 'CNAME': + case 'PTR': + { + var domain = writeDomainName(rr.exchange || rr.value); + rdLengthBuf[0] += domain.length; + buffers.push(domain); + break; + } + case 'SOA': + { + var mname = writeDomainName(rr.nsname); + var rname = writeDomainName(rr.hostmaster); + rdLengthBuf[0] = mname.length + rname.length + 20; + buffers.push(mname, rname); + buffers.push(new Uint32Array([rr.serial, rr.refresh, rr.retry, rr.expire, rr.minttl])); + break; + } + default: + throw new Error('Unknown RR type ' + rr.type); + } + } + } catch (err) { + _didIteratorError4 = true; + _iteratorError4 = err; + } finally { + try { + if (!_iteratorNormalCompletion4 && _iterator4.return) { + _iterator4.return(); + } + } finally { + if (_didIteratorError4) { + throw _iteratorError4; + } + } + } + + return Buffer.concat(buffers.map(function (typedArray) { + var buf = Buffer.from(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength); + if (os.endianness() === 'LE') { + if (typedArray.BYTES_PER_ELEMENT === 2) buf.swap16(); + if (typedArray.BYTES_PER_ELEMENT === 4) buf.swap32(); + } + return buf; + })); +} + +module.exports = { types: types, classes: classes, writeDNSPacket: writeDNSPacket, parseDNSPacket: parseDNSPacket }; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common/duplexpair.js b/test/common/duplexpair.js new file mode 100644 index 0000000000..b4b9577e9c --- /dev/null +++ b/test/common/duplexpair.js @@ -0,0 +1,94 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var _require = require('../../'), + Duplex = _require.Duplex; + +var assert = require('assert'); + +var kCallback = Symbol('Callback'); +var kOtherSide = Symbol('Other'); + +var DuplexSocket = function (_Duplex) { + _inherits(DuplexSocket, _Duplex); + + function DuplexSocket() { + _classCallCheck(this, DuplexSocket); + + var _this = _possibleConstructorReturn(this, _Duplex.call(this)); + + _this[kCallback] = null; + _this[kOtherSide] = null; + return _this; + } + + DuplexSocket.prototype._read = function _read() { + var callback = this[kCallback]; + if (callback) { + this[kCallback] = null; + callback(); + } + }; + + DuplexSocket.prototype._write = function _write(chunk, encoding, callback) { + assert.notStrictEqual(this[kOtherSide], null); + assert.strictEqual(this[kOtherSide][kCallback], null); + this[kOtherSide][kCallback] = callback; + this[kOtherSide].push(chunk); + }; + + DuplexSocket.prototype._final = function _final(callback) { + this[kOtherSide].on('end', callback); + this[kOtherSide].push(null); + }; + + return DuplexSocket; +}(Duplex); + +function makeDuplexPair() { + var clientSide = new DuplexSocket(); + var serverSide = new DuplexSocket(); + clientSide[kOtherSide] = serverSide; + serverSide[kOtherSide] = clientSide; + return { clientSide: clientSide, serverSide: serverSide }; +} + +module.exports = makeDuplexPair; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common/fixtures.js b/test/common/fixtures.js new file mode 100644 index 0000000000..75f170d8c1 --- /dev/null +++ b/test/common/fixtures.js @@ -0,0 +1,65 @@ +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var path = require('path'); +var fs = require('fs'); + +var fixturesDir = path.join(__dirname, '..', 'fixtures'); + +function fixturesPath() { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + return path.join.apply(path, [fixturesDir].concat(args)); +} + +function readFixtureSync(args, enc) { + if (Array.isArray(args)) return fs.readFileSync(fixturesPath.apply(undefined, _toConsumableArray(args)), enc); + return fs.readFileSync(fixturesPath(args), enc); +} + +function readFixtureKey(name, enc) { + return fs.readFileSync(fixturesPath('keys', name), enc); +} + +module.exports = { + fixturesDir: fixturesDir, + path: fixturesPath, + readSync: readFixtureSync, + readKey: readFixtureKey +}; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common.js b/test/common/index.js similarity index 75% rename from test/common.js rename to test/common/index.js index 5eaf4e757c..61a5510754 100644 --- a/test/common.js +++ b/test/common/index.js @@ -1,5 +1,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } + /**/ require('babel-polyfill'); var util = require('util'); @@ -38,7 +40,7 @@ if (!global.clearImmediate) { // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. -/* eslint-disable required-modules */ +/* eslint-disable required-modules, crypto-check */ 'use strict'; /**/ @@ -54,9 +56,14 @@ var path = require('path'); var fs = require('fs'); var assert = require('assert'); var os = require('os'); -var child_process = require('child_process'); -var stream = require('../'); -var buffer = require('buffer'); + +var _require = require('child_process'), + exec = _require.exec, + execSync = _require.execSync, + spawn = _require.spawn, + spawnSync = _require.spawnSync; + +var stream = require('../../'); /**/ var util = require('core-util-is'); @@ -64,41 +71,55 @@ util.inherits = require('inherits'); /**/ var Timer = { now: function () {} }; -var execSync = require('child_process').execSync; + +var _require2 = require('./fixtures'), + fixturesDir = _require2.fixturesDir; var testRoot = process.env.NODE_TEST_DIR ? fs.realpathSync(process.env.NODE_TEST_DIR) : path.resolve(__dirname, '..'); var noop = function () {}; -exports.noop = noop; -exports.fixturesDir = path.join(__dirname, '..', 'fixtures'); -exports.tmpDirName = 'tmp'; +// Using a `.` prefixed name, which is the convention for "hidden" on POSIX, +// gets tools to ignore it by default or by simple rules, especially eslint. +var tmpDirName = '.tmp'; // PORT should match the definition in test/testpy/__init__.py. exports.PORT = +process.env.NODE_COMMON_PORT || 12346; exports.isWindows = process.platform === 'win32'; exports.isWOW64 = exports.isWindows && process.env.PROCESSOR_ARCHITEW6432 !== undefined; -exports.isAix = process.platform === 'aix'; +exports.isAIX = process.platform === 'aix'; exports.isLinuxPPCBE = process.platform === 'linux' && process.arch === 'ppc64' && os.endianness() === 'BE'; exports.isSunOS = process.platform === 'sunos'; exports.isFreeBSD = process.platform === 'freebsd'; exports.isLinux = process.platform === 'linux'; exports.isOSX = process.platform === 'darwin'; -exports.enoughTestMem = os.totalmem() > 0x40000000; /* 1 Gb */ -exports.bufferMaxSizeMsg = new RegExp('^RangeError: "size" argument must not be larger than ' + buffer.kMaxLength + '$'); +exports.enoughTestMem = os.totalmem() > 0x70000000; /* 1.75 Gb */ var cpus = os.cpus(); /*exports.enoughTestCpu = Array.isArray(cpus) && (cpus.length > 1 || cpus[0].speed > 999);*/ exports.rootDir = exports.isWindows ? 'c:\\' : '/'; +exports.projectDir = path.resolve(__dirname, '..', '..'); + //exports.buildType = process.config.target_defaults.default_configuration; +// Always enable async_hooks checks in tests +{ + // const async_wrap = process.binding('async_wrap'); + // const kCheck = async_wrap.constants.kCheck; + // async_wrap.async_hook_fields[kCheck] += 1; + + exports.revert_force_async_hooks_checks = function () { + async_wrap.async_hook_fields[kCheck] -= 1; + }; +} + // If env var is set then enable async_hook hooks for all tests. if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { var destroydIdsList = {}; var destroyListList = {}; var initHandles = {}; - //const async_wrap = process.binding('async_wrap'); + var _async_wrap = process.binding('async_wrap'); process.on('exit', function () { // itterate through handles to make sure nothing crashes @@ -107,23 +128,26 @@ if (process.env.NODE_TEST_WITH_ASYNC_HOOKS) { } }); - var _addIdToDestroyList = async_wrap.addIdToDestroyList; - async_wrap.addIdToDestroyList = function addIdToDestroyList(id) { + var _queueDestroyAsyncId = _async_wrap.queueDestroyAsyncId; + _async_wrap.queueDestroyAsyncId = function queueDestroyAsyncId(id) { if (destroyListList[id] !== undefined) { process._rawDebug(destroyListList[id]); process._rawDebug(); - throw new Error('same id added twice (' + id + ')'); + throw new Error('same id added to destroy list twice (' + id + ')'); } destroyListList[id] = new Error().stack; - _addIdToDestroyList(id); + _queueDestroyAsyncId(id); }; /*require('async_hooks').createHook({ - init(id, ty, tr, h) { + init(id, ty, tr, r) { if (initHandles[id]) { + process._rawDebug( + `Is same resource: ${r === initHandles[id].resource}`); + process._rawDebug(`Previous stack:\n${initHandles[id].stack}\n`); throw new Error(`init called twice for same id (${id})`); } - initHandles[id] = h; + initHandles[id] = { resource: r, stack: new Error().stack.substr(6) }; }, before() { }, after() { }, @@ -163,7 +187,7 @@ function rmdirSync(p, originalEr) { if (e.code === 'ENOTDIR') throw originalEr; if (e.code === 'ENOTEMPTY' || e.code === 'EEXIST' || e.code === 'EPERM') { var enc = exports.isLinux ? 'buffer' : 'utf8'; - fs.readdirSync(p, forEach(enc), function (f) { + forEach(fs.readdirSync(p, enc), function (f) { if (f instanceof Buffer) { var buf = Buffer.concat([Buffer.from(p), Buffer.from(path.sep), f]); rimrafSync(buf); @@ -183,9 +207,9 @@ exports.refreshTmpDir = function () { if (process.env.TEST_THREAD_ID) { exports.PORT += process.env.TEST_THREAD_ID * 100; - exports.tmpDirName += '.' + process.env.TEST_THREAD_ID; + tmpDirName += '.' + process.env.TEST_THREAD_ID; } -exports.tmpDir = path.join(testRoot, exports.tmpDirName); +exports.tmpDir = path.join(testRoot, tmpDirName); var opensslCli = null; var inFreeBSDJail = null; @@ -209,7 +233,7 @@ if (exports.isLinux) { get: function () { if (inFreeBSDJail !== null) return inFreeBSDJail; - if (exports.isFreeBSD && child_process.execSync('sysctl -n security.jail.jailed').toString() === '1\n') { + if (exports.isFreeBSD && execSync('sysctl -n security.jail.jailed').toString() === '1\n') { inFreeBSDJail = true; } else { inFreeBSDJail = false; @@ -257,7 +281,7 @@ if (exports.isLinux) { if (exports.isWindows) opensslCli += '.exe'; - var opensslCmd = child_process.spawnSync(opensslCli, ['version']); + var opensslCmd = spawnSync(opensslCli, ['version']); if (opensslCmd.status !== 0 || opensslCmd.error !== undefined) { // openssl command cannot be executed opensslCli = false; @@ -269,7 +293,7 @@ if (exports.isLinux) { /**/if (!process.browser) { Object.defineProperty(exports, 'hasCrypto', { get: function () { - return process.versions.openssl ? true : false; + return Boolean(process.versions.openssl); } }); } /**/ @@ -282,22 +306,22 @@ if (exports.isLinux) { }); } /**/ -if (exports.isWindows) { - exports.PIPE = '\\\\.\\pipe\\libuv-test'; - if (process.env.TEST_THREAD_ID) { - exports.PIPE += '.' + process.env.TEST_THREAD_ID; - } -} else { - exports.PIPE = exports.tmpDir + '/test.sock'; +{ + var localRelative = path.relative(process.cwd(), exports.tmpDir + '/'); + var pipePrefix = exports.isWindows ? '\\\\.\\pipe\\' : localRelative; + var pipeName = 'node-test.' + process.pid + '.sock'; + exports.PIPE = path.join(pipePrefix, pipeName); } -var ifaces = os.networkInterfaces(); -var re = /lo/; -exports.hasIPv6 = objectKeys(ifaces).some(function (name) { - return re.test(name) && ifaces[name].some(function (info) { - return info.family === 'IPv6'; +{ + var iFaces = os.networkInterfaces(); + var re = exports.isWindows ? /Loopback Pseudo-Interface/ : /lo/; + exports.hasIPv6 = objectKeys(iFaces).some(function (name) { + return re.test(name) && iFaces[name].some(function (info) { + return info.family === 'IPv6'; + }); }); -}); +} /* * Check that when running a test with @@ -313,7 +337,7 @@ exports.childShouldThrowAndAbort = function () { } testCmd += '"' + process.argv[0] + '" --abort-on-uncaught-exception '; testCmd += '"' + process.argv[1] + '" child'; - var child = child_process.exec(testCmd); + var child = exec(testCmd); child.on('exit', function onExit(exitCode, signal) { var errMsg = 'Test should have aborted ' + ('but instead exited with exit code ' + exitCode) + (' and signal ' + signal); assert(exports.nodeProcessAborted(exitCode, signal), errMsg); @@ -322,7 +346,7 @@ exports.childShouldThrowAndAbort = function () { exports.ddCommand = function (filename, kilobytes) { if (exports.isWindows) { - var p = path.resolve(exports.fixturesDir, 'create-file.js'); + var p = path.resolve(fixturesDir, 'create-file.js'); return '"' + process.argv[0] + '" "' + p + '" "' + filename + '" ' + kilobytes * 1024; } else { return 'dd if=/dev/zero of="' + filename + '" bs=1024 count=' + kilobytes; @@ -330,8 +354,6 @@ exports.ddCommand = function (filename, kilobytes) { }; exports.spawnPwd = function (options) { - var spawn = require('child_process').spawn; - if (exports.isWindows) { return spawn('cmd.exe', ['/d', '/c', 'cd'], options); } else { @@ -340,8 +362,6 @@ exports.spawnPwd = function (options) { }; exports.spawnSyncPwd = function (options) { - var spawnSync = require('child_process').spawnSync; - if (exports.isWindows) { return spawnSync('cmd.exe', ['/d', '/c', 'cd'], options); } else { @@ -350,11 +370,11 @@ exports.spawnSyncPwd = function (options) { }; exports.platformTimeout = function (ms) { - if (process.config.target_defaults.default_configuration === 'Debug') ms = 2 * ms; + if (process.features.debug) ms = 2 * ms; if (global.__coverage__) ms = 4 * ms; - if (exports.isAix) return 2 * ms; // default localhost speed is slower on AIX + if (exports.isAIX) return 2 * ms; // default localhost speed is slower on AIX if (process.arch !== 'arm') return ms; @@ -426,6 +446,11 @@ if (global.Symbol) { knownGlobals.push(Symbol); } +if (process.env.NODE_TEST_KNOWN_GLOBALS) { + var knownFromEnv = process.env.NODE_TEST_KNOWN_GLOBALS.split(','); + allowGlobals.apply(undefined, _toConsumableArray(knownFromEnv)); +} + function allowGlobals() { for (var _len = arguments.length, whitelist = Array(_len), _key = 0; _key < _len; _key++) { whitelist[_key] = arguments[_key]; @@ -449,10 +474,13 @@ if (global.__coverage__) knownGlobals.push(__coverage__); function leakedGlobals() { var leaked = []; - // eslint-disable-next-line no-var for (var val in global) { - if (!knownGlobals.includes(global[val])) leaked.push(val); - }if (global.__coverage__) { + if (!knownGlobals.includes(global[val])) { + leaked.push(val); + } + } + + if (global.__coverage__) { return leaked.filter(function (varname) { return !/^(?:cov_|__cov)/.test(varname); }); @@ -504,9 +532,13 @@ exports.mustCallAtLeast = function (fn, minimum) { return _mustCallInner(fn, minimum, 'minimum'); }; -function _mustCallInner(fn, criteria, field) { +function _mustCallInner(fn) { var _context; + var criteria = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; + var field = arguments[2]; + + if (process._exiting) throw new Error('Cannot use common.mustCall*() in process exit handler'); if (typeof fn === 'number') { criteria = fn; fn = noop; @@ -514,7 +546,7 @@ function _mustCallInner(fn, criteria, field) { fn = noop; } - if (criteria === undefined) criteria = 1;else if (typeof criteria !== 'number') throw new TypeError('Invalid ' + field + ' value: ' + criteria); + if (typeof criteria !== 'number') throw new TypeError('Invalid ' + field + ' value: ' + criteria); var context = (_context = {}, _defineProperty(_context, field, criteria), _defineProperty(_context, 'actual', 0), _defineProperty(_context, 'stack', new Error().stack), _defineProperty(_context, 'name', fn.name || ''), _context); @@ -532,7 +564,7 @@ function _mustCallInner(fn, criteria, field) { exports.hasMultiLocalhost = function hasMultiLocalhost() { var TCP = process.binding('tcp_wrap').TCP; var t = new TCP(); - var ret = t.bind('127.0.0.2', exports.PORT); + var ret = t.bind('127.0.0.2', 0); t.close(); return ret === 0; }; @@ -573,16 +605,35 @@ exports.canCreateSymLink = function () { return true; }; +exports.getCallSite = function getCallSite(top) { + var originalStackFormatter = Error.prepareStackTrace; + Error.prepareStackTrace = function (err, stack) { + return stack[0].getFileName() + ':' + stack[0].getLineNumber(); + }; + var err = new Error(); + Error.captureStackTrace(err, top); + // with the V8 Error API, the stack is not formatted until it is accessed + err.stack; + Error.prepareStackTrace = originalStackFormatter; + return err.stack; +}; + exports.mustNotCall = function (msg) { + var callSite = exports.getCallSite(exports.mustNotCall); return function mustNotCall() { - assert.fail(msg || 'function should not have been called'); + assert.fail((msg || 'function should not have been called') + ' at ' + callSite); }; }; -exports.skip = function (msg) { +exports.printSkipMessage = function (msg) { console.log('1..0 # Skipped: ' + msg); }; +exports.skip = function (msg) { + exports.printSkipMessage(msg); + process.exit(0); +}; + // A stream to push an array into a REPL function ArrayStream() { this.run = function (data) { @@ -712,27 +763,59 @@ exports.expectWarning = function (nameOrMap, expected) { } /**/ // Useful for testing expected internal/error objects -exports.expectsError = function expectsError(_ref) { - var code = _ref.code, - type = _ref.type, - message = _ref.message; - - return function (error) { - assert.strictEqual(error.code, code); - if (type !== undefined) assert(error instanceof type, error + ' is not the expected type ' + type); - if (message instanceof RegExp) { - assert(message.test(error.message), error.message + ' does not match ' + message); - } else if (typeof message === 'string') { - assert.strictEqual(error.message, message); +exports.expectsError = function expectsError(fn, settings, exact) { + if (typeof fn !== 'function') { + exact = settings; + settings = fn; + fn = undefined; + } + var innerFn = exports.mustCall(function (error) { + assert.strictEqual(error.code, settings.code); + if ('type' in settings) { + var type = settings.type; + if (type !== Error && !Error.isPrototypeOf(type)) { + throw new TypeError('`settings.type` must inherit from `Error`'); + } + assert(error instanceof type, error.name + ' is not instance of ' + type.name); + } + if ('message' in settings) { + var message = settings.message; + if (typeof message === 'string') { + assert.strictEqual(error.message, message); + } else { + assert(message.test(error.message), error.message + ' does not match ' + message); + } + } + if ('name' in settings) { + assert.strictEqual(error.name, settings.name); + } + if (error.constructor.name === 'AssertionError') { + forEach(['generatedMessage', 'actual', 'expected', 'operator'], function (key) { + if (key in settings) { + var actual = error[key]; + var expected = settings[key]; + assert.strictEqual(actual, expected, key + ': expected ' + expected + ', not ' + actual); + } + }); } return true; - }; + }, exact); + if (fn) { + assert.throws(fn, innerFn); + return; + } + return innerFn; }; exports.skipIfInspectorDisabled = function skipIfInspectorDisabled() { if (process.config.variables.v8_enable_inspector === 0) { exports.skip('V8 inspector is disabled'); - process.exit(0); + } +}; + +exports.skipIf32Bits = function skipIf32Bits() { + if (process.binding('config').bits < 64) { + exports.skip('The tested feature is not available in 32bit builds'); } }; @@ -789,11 +872,13 @@ exports.crashOnUnhandledRejection = function () { exports.getTTYfd = function getTTYfd() { var tty = require('tty'); var tty_fd = 0; - if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else try { - tty_fd = require('fs').openSync('/dev/tty'); - } catch (e) { - // There aren't any tty fd's available to use. - return -1; + if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else if (!tty.isatty(tty_fd)) tty_fd++;else { + try { + tty_fd = fs.openSync('/dev/tty'); + } catch (e) { + // There aren't any tty fd's available to use. + return -1; + } } return tty_fd; }; @@ -806,7 +891,14 @@ function hijackStdWritable(name, listener) { stream.writeTimes = 0; stream.write = function (data, callback) { - listener(data); + try { + listener(data); + } catch (e) { + process.nextTick(function () { + throw e; + }); + } + _write.call(stream, data, callback); stream.writeTimes++; }; @@ -817,11 +909,62 @@ function restoreWritable(name) { delete process[name].writeTimes; } +function onResolvedOrRejected(promise, callback) { + return promise.then(function (result) { + callback(); + return result; + }, function (error) { + callback(); + throw error; + }); +} + +function timeoutPromise(error, timeoutMs) { + var clearCallback = null; + var done = false; + var promise = onResolvedOrRejected(new Promise(function (resolve, reject) { + var timeout = setTimeout(function () { + return reject(error); + }, timeoutMs); + clearCallback = function () { + if (done) return; + clearTimeout(timeout); + resolve(); + }; + }), function () { + return done = true; + }); + promise.clear = clearCallback; + return promise; +} + exports.hijackStdout = hijackStdWritable.bind(null, 'stdout'); exports.hijackStderr = hijackStdWritable.bind(null, 'stderr'); exports.restoreStdout = restoreWritable.bind(null, 'stdout'); exports.restoreStderr = restoreWritable.bind(null, 'stderr'); +var fd = 2; +exports.firstInvalidFD = function firstInvalidFD() { + // Get first known bad file descriptor. + try { + while (fs.fstatSync(++fd)) {} + } catch (e) {} + return fd; +}; + +exports.fires = function fires(promise, error, timeoutMs) { + if (!timeoutMs && util.isNumber(error)) { + timeoutMs = error; + error = null; + } + if (!error) error = 'timeout'; + if (!timeoutMs) timeoutMs = 100; + var timeout = timeoutPromise(error, timeoutMs); + return Promise.race([onResolvedOrRejected(promise, function () { + return timeout.clear(); + }), timeout]); +}; + function forEach(xs, f) { for (var i = 0, l = xs.length; i < l; i++) { f(xs[i], i); diff --git a/test/common/index.mjs b/test/common/index.mjs new file mode 100644 index 0000000000..ad89e9dc7d --- /dev/null +++ b/test/common/index.mjs @@ -0,0 +1,131 @@ +/**/ + require('babel-polyfill'); + var util = require('util'); + for (var i in util) exports[i] = util[i]; + /**//**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +// Flags: --experimental-modules +/* eslint-disable required-modules */ + +import assert from 'assert'; + +let knownGlobals = [ + Buffer, + clearImmediate, + clearInterval, + clearTimeout, + console, + constructor, // Enumerable in V8 3.21. + global, + process, + setImmediate, + setInterval, + setTimeout +]; + +if (process.env.NODE_TEST_KNOWN_GLOBALS) { + const knownFromEnv = process.env.NODE_TEST_KNOWN_GLOBALS.split(','); + allowGlobals(...knownFromEnv); +} + +export function allowGlobals(...whitelist) { + knownGlobals = knownGlobals.concat(whitelist); +} + +export function leakedGlobals() { + //add possible expected globals + if (global.gc) { + knownGlobals.push(global.gc); + } + + if (global.DTRACE_HTTP_SERVER_RESPONSE) { + knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE); + knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST); + knownGlobals.push(DTRACE_HTTP_CLIENT_RESPONSE); + knownGlobals.push(DTRACE_HTTP_CLIENT_REQUEST); + knownGlobals.push(DTRACE_NET_STREAM_END); + knownGlobals.push(DTRACE_NET_SERVER_CONNECTION); + } + + if (global.COUNTER_NET_SERVER_CONNECTION) { + knownGlobals.push(COUNTER_NET_SERVER_CONNECTION); + knownGlobals.push(COUNTER_NET_SERVER_CONNECTION_CLOSE); + knownGlobals.push(COUNTER_HTTP_SERVER_REQUEST); + knownGlobals.push(COUNTER_HTTP_SERVER_RESPONSE); + knownGlobals.push(COUNTER_HTTP_CLIENT_REQUEST); + knownGlobals.push(COUNTER_HTTP_CLIENT_RESPONSE); + } + + if (global.LTTNG_HTTP_SERVER_RESPONSE) { + knownGlobals.push(LTTNG_HTTP_SERVER_RESPONSE); + knownGlobals.push(LTTNG_HTTP_SERVER_REQUEST); + knownGlobals.push(LTTNG_HTTP_CLIENT_RESPONSE); + knownGlobals.push(LTTNG_HTTP_CLIENT_REQUEST); + knownGlobals.push(LTTNG_NET_STREAM_END); + knownGlobals.push(LTTNG_NET_SERVER_CONNECTION); + } + + if (global.ArrayBuffer) { + knownGlobals.push(ArrayBuffer); + knownGlobals.push(Int8Array); + knownGlobals.push(Uint8Array); + knownGlobals.push(Uint8ClampedArray); + knownGlobals.push(Int16Array); + knownGlobals.push(Uint16Array); + knownGlobals.push(Int32Array); + knownGlobals.push(Uint32Array); + knownGlobals.push(Float32Array); + knownGlobals.push(Float64Array); + knownGlobals.push(DataView); + } + + // Harmony features. + if (global.Proxy) { + knownGlobals.push(Proxy); + } + + if (global.Symbol) { + knownGlobals.push(Symbol); + } + + const leaked = []; + + for (const val in global) { + if (!knownGlobals.includes(global[val])) { + leaked.push(val); + } + } + + if (global.__coverage__) { + return leaked.filter((varname) => !/^(?:cov_|__cov)/.test(varname)); + } else { + return leaked; + } +} + +// Turn this off if the test should not check for global leaks. +export let globalCheck = true; // eslint-disable-line + +process.on('exit', function() { + if (!globalCheck) return; + const leaked = leakedGlobals(); + if (leaked.length > 0) { + assert.fail(`Unexpected global(s) found: ${leaked.join(', ')}`); + } +}); + +function forEach (xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} diff --git a/test/common/inspector-helper.js b/test/common/inspector-helper.js new file mode 100644 index 0000000000..6f3e818df5 --- /dev/null +++ b/test/common/inspector-helper.js @@ -0,0 +1,521 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var common = require('../common'); +var assert = require('assert'); +var fs = require('fs'); +var http = require('http'); +var fixtures = require('../common/fixtures'); + +var _require = require('child_process'), + spawn = _require.spawn; + +var url = require('url'); + +var _MAINSCRIPT = fixtures.path('loop.js'); +var DEBUG = false; +var TIMEOUT = common.platformTimeout(15 * 1000); + +function spawnChildProcess(inspectorFlags, scriptContents, scriptFile) { + var args = [].concat(inspectorFlags); + if (scriptContents) { + args.push('-e', scriptContents); + } else { + args.push(scriptFile); + } + var child = spawn(process.execPath, args); + + var handler = tearDown.bind(null, child); + process.on('exit', handler); + process.on('uncaughtException', handler); + process.on('unhandledRejection', handler); + process.on('SIGINT', handler); + + return child; +} + +function makeBufferingDataCallback(dataCallback) { + var buffer = Buffer.alloc(0); + return function (data) { + var newData = Buffer.concat([buffer, data]); + var str = newData.toString('utf8'); + var lines = str.replace(/\r/g, '').split('\n'); + if (str.endsWith('\n')) buffer = Buffer.alloc(0);else buffer = Buffer.from(lines.pop(), 'utf8'); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = lines[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var line = _step.value; + + dataCallback(line); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + }; +} + +function tearDown(child, err) { + child.kill(); + if (err) { + console.error(err); + process.exit(1); + } +} + +function parseWSFrame(buffer) { + // Protocol described in https://tools.ietf.org/html/rfc6455#section-5 + var message = null; + if (buffer.length < 2) return { length: 0, message: message }; + if (buffer[0] === 0x88 && buffer[1] === 0x00) { + return { length: 2, message: message, closed: true }; + } + assert.strictEqual(0x81, buffer[0]); + var dataLen = 0x7F & buffer[1]; + var bodyOffset = 2; + if (buffer.length < bodyOffset + dataLen) return 0; + if (dataLen === 126) { + dataLen = buffer.readUInt16BE(2); + bodyOffset = 4; + } else if (dataLen === 127) { + assert(buffer[2] === 0 && buffer[3] === 0, 'Inspector message too big'); + dataLen = buffer.readUIntBE(4, 6); + bodyOffset = 10; + } + if (buffer.length < bodyOffset + dataLen) return { length: 0, message: message }; + var jsonPayload = buffer.slice(bodyOffset, bodyOffset + dataLen).toString('utf8'); + try { + message = JSON.parse(jsonPayload); + } catch (e) { + console.error('JSON.parse() failed for: ' + jsonPayload); + throw e; + } + if (DEBUG) console.log('[received]', JSON.stringify(message)); + return { length: bodyOffset + dataLen, message: message }; +} + +function formatWSFrame(message) { + var messageBuf = Buffer.from(JSON.stringify(message)); + + var wsHeaderBuf = Buffer.allocUnsafe(16); + wsHeaderBuf.writeUInt8(0x81, 0); + var byte2 = 0x80; + var bodyLen = messageBuf.length; + + var maskOffset = 2; + if (bodyLen < 126) { + byte2 = 0x80 + bodyLen; + } else if (bodyLen < 65536) { + byte2 = 0xFE; + wsHeaderBuf.writeUInt16BE(bodyLen, 2); + maskOffset = 4; + } else { + byte2 = 0xFF; + wsHeaderBuf.writeUInt32BE(bodyLen, 2); + wsHeaderBuf.writeUInt32BE(0, 6); + maskOffset = 10; + } + wsHeaderBuf.writeUInt8(byte2, 1); + wsHeaderBuf.writeUInt32BE(0x01020408, maskOffset); + + for (var _i = 0; _i < messageBuf.length; _i++) { + messageBuf[_i] = messageBuf[_i] ^ 1 << _i % 4; + }return Buffer.concat([wsHeaderBuf.slice(0, maskOffset + 4), messageBuf]); +} + +var InspectorSession = function () { + function InspectorSession(socket, instance) { + var _this = this; + + _classCallCheck(this, InspectorSession); + + this._instance = instance; + this._socket = socket; + this._nextId = 1; + this._commandResponsePromises = new Map(); + this._unprocessedNotifications = []; + this._notificationCallback = null; + this._scriptsIdsByUrl = new Map(); + + var buffer = Buffer.alloc(0); + socket.on('data', function (data) { + buffer = Buffer.concat([buffer, data]); + do { + var _parseWSFrame = parseWSFrame(buffer), + length = _parseWSFrame.length, + message = _parseWSFrame.message, + closed = _parseWSFrame.closed; + + if (!length) break; + + if (closed) { + socket.write(Buffer.from([0x88, 0x00])); // WS close frame + } + buffer = buffer.slice(length); + if (message) _this._onMessage(message); + } while (true); + }); + this._terminationPromise = new Promise(function (resolve) { + socket.once('close', resolve); + }); + } + + InspectorSession.prototype.waitForServerDisconnect = function waitForServerDisconnect() { + return this._terminationPromise; + }; + + InspectorSession.prototype.disconnect = function disconnect() { + this._socket.destroy(); + }; + + InspectorSession.prototype._onMessage = function _onMessage(message) { + if (message.id) { + var _commandResponsePromi = this._commandResponsePromises.get(message.id), + resolve = _commandResponsePromi.resolve, + reject = _commandResponsePromi.reject; + + this._commandResponsePromises.delete(message.id); + if (message.result) resolve(message.result);else reject(message.error); + } else { + if (message.method === 'Debugger.scriptParsed') { + var script = message['params']; + var scriptId = script['scriptId']; + var _url = script['url']; + this._scriptsIdsByUrl.set(scriptId, _url); + if (_url === _MAINSCRIPT) this.mainScriptId = scriptId; + } + + if (this._notificationCallback) { + // In case callback needs to install another + var callback = this._notificationCallback; + this._notificationCallback = null; + callback(message); + } else { + this._unprocessedNotifications.push(message); + } + } + }; + + InspectorSession.prototype._sendMessage = function _sendMessage(message) { + var _this2 = this; + + var msg = JSON.parse(JSON.stringify(message)); // Clone! + msg['id'] = this._nextId++; + if (DEBUG) console.log('[sent]', JSON.stringify(msg)); + + var responsePromise = new Promise(function (resolve, reject) { + _this2._commandResponsePromises.set(msg['id'], { resolve: resolve, reject: reject }); + }); + + return new Promise(function (resolve) { + return _this2._socket.write(formatWSFrame(msg), resolve); + }).then(function () { + return responsePromise; + }); + }; + + InspectorSession.prototype.send = function send(commands) { + var _this3 = this; + + if (Array.isArray(commands)) { + // Multiple commands means the response does not matter. There might even + // never be a response. + return Promise.all(commands.map(function (command) { + return _this3._sendMessage(command); + })).then(function () {}); + } else { + return this._sendMessage(commands); + } + }; + + InspectorSession.prototype.waitForNotification = function waitForNotification(methodOrPredicate, description) { + var desc = description || methodOrPredicate; + var message = 'Timed out waiting for matching notification (' + desc + '))'; + return common.fires(this._asyncWaitForNotification(methodOrPredicate), message, TIMEOUT); + }; + + InspectorSession.prototype._asyncWaitForNotification = async function _asyncWaitForNotification(methodOrPredicate) { + var _this4 = this; + + function matchMethod(notification) { + return notification.method === methodOrPredicate; + } + var predicate = typeof methodOrPredicate === 'string' ? matchMethod : methodOrPredicate; + var notification = null; + do { + if (this._unprocessedNotifications.length) { + notification = this._unprocessedNotifications.shift(); + } else { + notification = await new Promise(function (resolve) { + return _this4._notificationCallback = resolve; + }); + } + } while (!predicate(notification)); + return notification; + }; + + InspectorSession.prototype._isBreakOnLineNotification = function _isBreakOnLineNotification(message, line, url) { + if ('Debugger.paused' === message['method']) { + var callFrame = message['params']['callFrames'][0]; + var location = callFrame['location']; + assert.strictEqual(url, this._scriptsIdsByUrl.get(location['scriptId'])); + assert.strictEqual(line, location['lineNumber']); + return true; + } + }; + + InspectorSession.prototype.waitForBreakOnLine = function waitForBreakOnLine(line, url) { + var _this5 = this; + + return this.waitForNotification(function (notification) { + return _this5._isBreakOnLineNotification(notification, line, url); + }, 'break on ' + url + ':' + line); + }; + + InspectorSession.prototype._matchesConsoleOutputNotification = function _matchesConsoleOutputNotification(notification, type, values) { + if (!Array.isArray(values)) values = [values]; + if ('Runtime.consoleAPICalled' === notification['method']) { + var params = notification['params']; + if (params['type'] === type) { + var _i2 = 0; + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = params['args'][Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var value = _step2.value; + + if (value['value'] !== values[_i2++]) return false; + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + return _i2 === values.length; + } + } + }; + + InspectorSession.prototype.waitForConsoleOutput = function waitForConsoleOutput(type, values) { + var _this6 = this; + + var desc = 'Console output matching ' + JSON.stringify(values); + return this.waitForNotification(function (notification) { + return _this6._matchesConsoleOutputNotification(notification, type, values); + }, desc); + }; + + InspectorSession.prototype.runToCompletion = async function runToCompletion() { + console.log('[test]', 'Verify node waits for the frontend to disconnect'); + await this.send({ 'method': 'Debugger.resume' }); + await this.waitForNotification(function (notification) { + return notification.method === 'Runtime.executionContextDestroyed' && notification.params.executionContextId === 1; + }); + while ((await this._instance.nextStderrString()) !== 'Waiting for the debugger to disconnect...') {} + await this.disconnect(); + }; + + return InspectorSession; +}(); + +var NodeInstance = function () { + function NodeInstance() { + var inspectorFlags = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['--inspect-brk=0']; + + var _this7 = this; + + var scriptContents = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + var scriptFile = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _MAINSCRIPT; + + _classCallCheck(this, NodeInstance); + + this._portCallback = null; + this.portPromise = new Promise(function (resolve) { + return _this7._portCallback = resolve; + }); + this._process = spawnChildProcess(inspectorFlags, scriptContents, scriptFile); + this._running = true; + this._stderrLineCallback = null; + this._unprocessedStderrLines = []; + + this._process.stdout.on('data', makeBufferingDataCallback(function (line) { + return console.log('[out]', line); + })); + + this._process.stderr.on('data', makeBufferingDataCallback(function (message) { + return _this7.onStderrLine(message); + })); + + this._shutdownPromise = new Promise(function (resolve) { + _this7._process.once('exit', function (exitCode, signal) { + resolve({ exitCode: exitCode, signal: signal }); + _this7._running = false; + }); + }); + } + + NodeInstance.startViaSignal = async function startViaSignal(scriptContents) { + var instance = new NodeInstance([], scriptContents + '\nprocess._rawDebug(\'started\');', undefined); + var msg = 'Timed out waiting for process to start'; + while ((await common.fires(instance.nextStderrString(), msg, TIMEOUT)) !== 'started') {} + process._debugProcess(instance._process.pid); + return instance; + }; + + NodeInstance.prototype.onStderrLine = function onStderrLine(line) { + console.log('[err]', line); + if (this._portCallback) { + var matches = line.match(/Debugger listening on ws:\/\/.+:(\d+)\/.+/); + if (matches) { + this._portCallback(matches[1]); + this._portCallback = null; + } + } + if (this._stderrLineCallback) { + this._stderrLineCallback(line); + this._stderrLineCallback = null; + } else { + this._unprocessedStderrLines.push(line); + } + }; + + NodeInstance.prototype.httpGet = function httpGet(host, path) { + console.log('[test]', 'Testing ' + path); + return this.portPromise.then(function (port) { + return new Promise(function (resolve, reject) { + var req = http.get({ host: host, port: port, path: path }, function (res) { + var response = ''; + res.setEncoding('utf8'); + res.on('data', function (data) { + return response += data.toString(); + }).on('end', function () { + resolve(response); + }); + }); + req.on('error', reject); + }); + }).then(function (response) { + try { + return JSON.parse(response); + } catch (e) { + e.body = response; + throw e; + } + }); + }; + + NodeInstance.prototype.wsHandshake = function wsHandshake(devtoolsUrl) { + var _this8 = this; + + return this.portPromise.then(function (port) { + return new Promise(function (resolve) { + http.get({ + port: port, + path: url.parse(devtoolsUrl).path, + headers: { + 'Connection': 'Upgrade', + 'Upgrade': 'websocket', + 'Sec-WebSocket-Version': 13, + 'Sec-WebSocket-Key': 'key==' + } + }).on('upgrade', function (message, socket) { + resolve(new InspectorSession(socket, _this8)); + }).on('response', common.mustNotCall('Upgrade was not received')); + }); + }); + }; + + NodeInstance.prototype.connectInspectorSession = async function connectInspectorSession() { + console.log('[test]', 'Connecting to a child Node process'); + var response = await this.httpGet(null, '/json/list'); + var url = response[0]['webSocketDebuggerUrl']; + return this.wsHandshake(url); + }; + + NodeInstance.prototype.expectShutdown = function expectShutdown() { + return this._shutdownPromise; + }; + + NodeInstance.prototype.nextStderrString = function nextStderrString() { + var _this9 = this; + + if (this._unprocessedStderrLines.length) return Promise.resolve(this._unprocessedStderrLines.shift()); + return new Promise(function (resolve) { + return _this9._stderrLineCallback = resolve; + }); + }; + + NodeInstance.prototype.kill = function kill() { + this._process.kill(); + }; + + return NodeInstance; +}(); + +function readMainScriptSource() { + return fs.readFileSync(_MAINSCRIPT, 'utf8'); +} + +module.exports = { + mainScriptPath: _MAINSCRIPT, + readMainScriptSource: readMainScriptSource, + NodeInstance: NodeInstance +}; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/common/wpt.js b/test/common/wpt.js new file mode 100644 index 0000000000..22a5c89709 --- /dev/null +++ b/test/common/wpt.js @@ -0,0 +1,64 @@ +/**/ +require('babel-polyfill'); +var util = require('util'); +for (var i in util) { + exports[i] = util[i]; +} /**/ /**/ +if (!global.setImmediate) { + global.setImmediate = function setImmediate(fn) { + return setTimeout(fn.bind.apply(fn, arguments), 4); + }; +} +if (!global.clearImmediate) { + global.clearImmediate = function clearImmediate(i) { + return clearTimeout(i); + }; +} +/**/ +/* eslint-disable required-modules */ +'use strict'; + +/**/ +var objectKeys = objectKeys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +var assert = require('assert'); + +// https://github.com/w3c/testharness.js/blob/master/testharness.js +module.exports = { + test: function (fn, desc) { + try { + fn(); + } catch (err) { + console.error('In ' + desc + ':'); + throw err; + } + }, + assert_equals: assert.strictEqual, + assert_true: function (value, message) { + return assert.strictEqual(value, true, message); + }, + assert_false: function (value, message) { + return assert.strictEqual(value, false, message); + }, + assert_throws: function (code, func, desc) { + assert.throws(func, function (err) { + return typeof err === 'object' && 'name' in err && err.name.startsWith(code.name); + }, desc); + }, + assert_array_equals: assert.deepStrictEqual, + assert_unreached: function (desc) { + assert.fail('Reached unreachable code: ' + desc); + } +}; + +function forEach(xs, f) { + for (var i = 0, l = xs.length; i < l; i++) { + f(xs[i], i); + } +} \ No newline at end of file diff --git a/test/parallel/test-stream-big-packet.js b/test/parallel/test-stream-big-packet.js index cebf5fece2..19a86498c7 100644 --- a/test/parallel/test-stream-big-packet.js +++ b/test/parallel/test-stream-big-packet.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -24,34 +30,32 @@ var bufferShim = require('safe-buffer').Buffer; /**/ require('../common'); var assert = require('assert/'); -var util = require('util'); var stream = require('../../'); var passed = false; -function PassThrough() { - stream.Transform.call(this); -} -util.inherits(PassThrough, stream.Transform); -PassThrough.prototype._transform = function (chunk, encoding, done) { - this.push(chunk); - done(); -}; - -function TestStream() { - stream.Transform.call(this); -} -util.inherits(TestStream, stream.Transform); -TestStream.prototype._transform = function (chunk, encoding, done) { - if (!passed) { - // Char 'a' only exists in the last write - passed = chunk.toString().includes('a'); +var TestStream = function (_stream$Transform) { + _inherits(TestStream, _stream$Transform); + + function TestStream() { + _classCallCheck(this, TestStream); + + return _possibleConstructorReturn(this, _stream$Transform.apply(this, arguments)); } - done(); -}; -var s1 = new PassThrough(); -var s2 = new PassThrough(); + TestStream.prototype._transform = function _transform(chunk, encoding, done) { + if (!passed) { + // Char 'a' only exists in the last write + passed = chunk.toString().includes('a'); + } + done(); + }; + + return TestStream; +}(stream.Transform); + +var s1 = new stream.PassThrough(); +var s2 = new stream.PassThrough(); var s3 = new TestStream(); s1.pipe(s3); // Don't let s2 auto close which may close s3 diff --git a/test/parallel/test-stream-decoder-objectmode.js b/test/parallel/test-stream-decoder-objectmode.js index 52f9cde046..b875a0f07d 100644 --- a/test/parallel/test-stream-decoder-objectmode.js +++ b/test/parallel/test-stream-decoder-objectmode.js @@ -2,12 +2,12 @@ var bufferShim = require('safe-buffer').Buffer; /**/ -var common = require('../common'); +require('../common'); var stream = require('../../'); var assert = require('assert/'); var readable = new stream.Readable({ - read: common.noop, + read: function () {}, encoding: 'utf16le', objectMode: true }); diff --git a/test/parallel/test-stream-duplex.js b/test/parallel/test-stream-duplex.js index 8491111986..9b121ca2ac 100644 --- a/test/parallel/test-stream-duplex.js +++ b/test/parallel/test-stream-duplex.js @@ -22,7 +22,7 @@ var bufferShim = require('safe-buffer').Buffer; /**/ -var common = require('../common'); +require('../common'); var assert = require('assert/'); var Duplex = require('../../').Duplex; @@ -40,7 +40,7 @@ stream._write = function (obj, _, cb) { cb(); }; -stream._read = common.noop; +stream._read = function () {}; stream.on('data', function (obj) { read = obj; diff --git a/test/parallel/test-stream-events-prepend.js b/test/parallel/test-stream-events-prepend.js index 097ae2ad69..b6d36d219f 100644 --- a/test/parallel/test-stream-events-prepend.js +++ b/test/parallel/test-stream-events-prepend.js @@ -1,28 +1,49 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + /**/ var bufferShim = require('safe-buffer').Buffer; /**/ var common = require('../common'); var stream = require('../../'); -var util = require('util'); - -function Writable() { - this.writable = true; - stream.Writable.call(this); - this.prependListener = undefined; -} -util.inherits(Writable, stream.Writable); -Writable.prototype._write = function (chunk, end, cb) { - cb(); -}; - -function Readable() { - this.readable = true; - stream.Readable.call(this); -} -util.inherits(Readable, stream.Readable); -Readable.prototype._read = function () { - this.push(null); -}; + +var Writable = function (_stream$Writable) { + _inherits(Writable, _stream$Writable); + + function Writable() { + _classCallCheck(this, Writable); + + var _this = _possibleConstructorReturn(this, _stream$Writable.call(this)); + + _this.prependListener = undefined; + return _this; + } + + Writable.prototype._write = function _write(chunk, end, cb) { + cb(); + }; + + return Writable; +}(stream.Writable); + +var Readable = function (_stream$Readable) { + _inherits(Readable, _stream$Readable); + + function Readable() { + _classCallCheck(this, Readable); + + return _possibleConstructorReturn(this, _stream$Readable.apply(this, arguments)); + } + + Readable.prototype._read = function _read() { + this.push(null); + }; + + return Readable; +}(stream.Readable); var w = new Writable(); w.on('pipe', common.mustCall()); diff --git a/test/parallel/test-stream-pipe-after-end.js b/test/parallel/test-stream-pipe-after-end.js index 6bbd0bd823..c9ed1aa721 100644 --- a/test/parallel/test-stream-pipe-after-end.js +++ b/test/parallel/test-stream-pipe-after-end.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -26,34 +32,51 @@ var common = require('../common'); var assert = require('assert/'); var Readable = require('../../lib/_stream_readable'); var Writable = require('../../lib/_stream_writable'); -var util = require('util'); - -util.inherits(TestReadable, Readable); -function TestReadable(opt) { - if (!(this instanceof TestReadable)) return new TestReadable(opt); - Readable.call(this, opt); - this._ended = false; -} - -TestReadable.prototype._read = function () { - if (this._ended) this.emit('error', new Error('_read called twice')); - this._ended = true; - this.push(null); -}; - -util.inherits(TestWritable, Writable); -function TestWritable(opt) { - if (!(this instanceof TestWritable)) return new TestWritable(opt); - Writable.call(this, opt); - this._written = []; -} - -TestWritable.prototype._write = function (chunk, encoding, cb) { - this._written.push(chunk); - cb(); -}; + +var TestReadable = function (_Readable) { + _inherits(TestReadable, _Readable); + + function TestReadable(opt) { + _classCallCheck(this, TestReadable); + + var _this = _possibleConstructorReturn(this, _Readable.call(this, opt)); + + _this._ended = false; + return _this; + } + + TestReadable.prototype._read = function _read() { + if (this._ended) this.emit('error', new Error('_read called twice')); + this._ended = true; + this.push(null); + }; + + return TestReadable; +}(Readable); + +var TestWritable = function (_Writable) { + _inherits(TestWritable, _Writable); + + function TestWritable(opt) { + _classCallCheck(this, TestWritable); + + var _this2 = _possibleConstructorReturn(this, _Writable.call(this, opt)); + + _this2._written = []; + return _this2; + } + + TestWritable.prototype._write = function _write(chunk, encoding, cb) { + this._written.push(chunk); + cb(); + }; + + return TestWritable; +}(Writable); // this one should not emit 'end' until we read() from it later. + + var ender = new TestReadable(); // what happens when you pipe() a Readable that's already ended? diff --git a/test/parallel/test-stream-pipe-await-drain-manual-resume.js b/test/parallel/test-stream-pipe-await-drain-manual-resume.js index 07f9635935..3475d3528e 100644 --- a/test/parallel/test-stream-pipe-await-drain-manual-resume.js +++ b/test/parallel/test-stream-pipe-await-drain-manual-resume.js @@ -26,16 +26,17 @@ var readable = new stream.Readable({ readable.pipe(writable); readable.once('pause', common.mustCall(function () { - assert.strictEqual(readable._readableState.awaitDrain, 1, 'awaitDrain doesn\'t increase'); + assert.strictEqual(readable._readableState.awaitDrain, 1, 'Expected awaitDrain to equal 1 but instead got ' + ('' + readable._readableState.awaitDrain)); // First pause, resume manually. The next write() to writable will still // return false, because chunks are still being buffered, so it will increase // the awaitDrain counter again. + process.nextTick(common.mustCall(function () { readable.resume(); })); readable.once('pause', common.mustCall(function () { - assert.strictEqual(readable._readableState.awaitDrain, 1, '.resume() does not reset counter'); + assert.strictEqual(readable._readableState.awaitDrain, 1, '.resume() should not reset the counter but instead got ' + ('' + readable._readableState.awaitDrain)); // Second pause, handle all chunks from now on. Once all callbacks that // are currently queued up are handled, the awaitDrain drain counter should // fall back to 0 and all chunks that are pending on the readable side @@ -74,6 +75,6 @@ readable.push(bufferShim.alloc(100)); // Should get through to the writable. readable.push(null); writable.on('finish', common.mustCall(function () { - assert.strictEqual(readable._readableState.awaitDrain, 0, 'awaitDrain not 0 after all chunks are written'); + assert.strictEqual(readable._readableState.awaitDrain, 0, 'awaitDrain should equal 0 after all chunks are written but instead got' + ('' + readable._readableState.awaitDrain)); // Everything okay, all chunks were written. })); \ No newline at end of file diff --git a/test/parallel/test-stream-pipe-await-drain.js b/test/parallel/test-stream-pipe-await-drain.js index 5becd4c1c8..55cc714489 100644 --- a/test/parallel/test-stream-pipe-await-drain.js +++ b/test/parallel/test-stream-pipe-await-drain.js @@ -17,7 +17,7 @@ var writer3 = new stream.Writable(); // See: https://github.com/nodejs/node/issues/5820 var buffer = bufferShim.allocUnsafe(560000); -reader._read = common.noop; +reader._read = function () {}; writer1._write = common.mustCall(function (chunk, encoding, cb) { this.emit('chunk-received'); diff --git a/test/parallel/test-stream-pipe-cleanup-pause.js b/test/parallel/test-stream-pipe-cleanup-pause.js index b5cc25bbbc..6aad21ed15 100644 --- a/test/parallel/test-stream-pipe-cleanup-pause.js +++ b/test/parallel/test-stream-pipe-cleanup-pause.js @@ -13,7 +13,7 @@ var writer2 = new stream.Writable(); // See: https://github.com/nodejs/node/issues/2323 var buffer = bufferShim.allocUnsafe(560000); -reader._read = common.noop; +reader._read = function () {}; writer1._write = common.mustCall(function (chunk, encoding, cb) { this.emit('chunk-received'); diff --git a/test/parallel/test-stream-pipe-error-handling.js b/test/parallel/test-stream-pipe-error-handling.js index 80a4ff2aae..f6040812c9 100644 --- a/test/parallel/test-stream-pipe-error-handling.js +++ b/test/parallel/test-stream-pipe-error-handling.js @@ -103,10 +103,10 @@ var Stream = require('stream').Stream; }); _w.on('error', common.mustCall()); - _w._write = common.noop; + _w._write = function () {}; _r.pipe(_w); // Removing some OTHER random listener should not do anything - _w.removeListener('error', common.noop); + _w.removeListener('error', function () {}); _removed = true; } \ No newline at end of file diff --git a/test/parallel/test-stream-pipe-multiple-pipes.js b/test/parallel/test-stream-pipe-multiple-pipes.js index d0bb949165..21abfcf18e 100644 --- a/test/parallel/test-stream-pipe-multiple-pipes.js +++ b/test/parallel/test-stream-pipe-multiple-pipes.js @@ -6,7 +6,7 @@ var stream = require('../../'); var assert = require('assert/'); var readable = new stream.Readable({ - read: common.noop + read: function () {} }); var writables = []; diff --git a/test/parallel/test-stream-pipe-unpipe-streams.js b/test/parallel/test-stream-pipe-unpipe-streams.js index 0e9ff3367e..6cc3a10491 100644 --- a/test/parallel/test-stream-pipe-unpipe-streams.js +++ b/test/parallel/test-stream-pipe-unpipe-streams.js @@ -8,9 +8,9 @@ var _require = require('../../'), Readable = _require.Readable, Writable = _require.Writable; -var source = Readable({ read: common.noop }); -var dest1 = Writable({ write: common.noop }); -var dest2 = Writable({ write: common.noop }); +var source = Readable({ read: function () {} }); +var dest1 = Writable({ write: function () {} }); +var dest2 = Writable({ write: function () {} }); source.pipe(dest1); source.pipe(dest2); diff --git a/test/parallel/test-stream-push-strings.js b/test/parallel/test-stream-push-strings.js index 33b5630813..00a6e8354c 100644 --- a/test/parallel/test-stream-push-strings.js +++ b/test/parallel/test-stream-push-strings.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -26,32 +32,42 @@ require('../common'); var assert = require('assert/'); var Readable = require('../../').Readable; -var util = require('util'); -util.inherits(MyStream, Readable); -function MyStream(options) { - Readable.call(this, options); - this._chunks = 3; -} +var MyStream = function (_Readable) { + _inherits(MyStream, _Readable); + + function MyStream(options) { + _classCallCheck(this, MyStream); -MyStream.prototype._read = function (n) { - switch (this._chunks--) { - case 0: - return this.push(null); - case 1: - return setTimeout(function () { - this.push('last chunk'); - }.bind(this), 100); - case 2: - return this.push('second to last chunk'); - case 3: - return process.nextTick(function () { - this.push('first chunk'); - }.bind(this)); - default: - throw new Error('?'); + var _this = _possibleConstructorReturn(this, _Readable.call(this, options)); + + _this._chunks = 3; + return _this; } -}; + + MyStream.prototype._read = function _read(n) { + var _this2 = this; + + switch (this._chunks--) { + case 0: + return this.push(null); + case 1: + return setTimeout(function () { + _this2.push('last chunk'); + }, 100); + case 2: + return this.push('second to last chunk'); + case 3: + return process.nextTick(function () { + _this2.push('first chunk'); + }); + default: + throw new Error('?'); + } + }; + + return MyStream; +}(Readable); var ms = new MyStream(); var results = []; diff --git a/test/parallel/test-stream-readable-emittedReadable.js b/test/parallel/test-stream-readable-emittedReadable.js index f25a41b00b..13695547f7 100644 --- a/test/parallel/test-stream-readable-emittedReadable.js +++ b/test/parallel/test-stream-readable-emittedReadable.js @@ -6,7 +6,7 @@ var assert = require('assert/'); var Readable = require('../../').Readable; var readable = new Readable({ - read: common.noop + read: function () {} }); // Initialized to false. @@ -39,7 +39,7 @@ process.nextTick(common.mustCall(function () { })); var noRead = new Readable({ - read: common.noop + read: function () {} }); noRead.on('readable', common.mustCall(function () { @@ -54,7 +54,7 @@ noRead.push('foo'); noRead.push(null); var flowing = new Readable({ - read: common.noop + read: function () {} }); flowing.on('data', common.mustCall(function () { diff --git a/test/parallel/test-stream-readable-invalid-chunk.js b/test/parallel/test-stream-readable-invalid-chunk.js index 75c3acb4a7..81f0eed852 100644 --- a/test/parallel/test-stream-readable-invalid-chunk.js +++ b/test/parallel/test-stream-readable-invalid-chunk.js @@ -2,12 +2,12 @@ var bufferShim = require('safe-buffer').Buffer; /**/ -var common = require('../common'); +require('../common'); var stream = require('../../'); var assert = require('assert/'); var readable = new stream.Readable({ - read: common.noop + read: function () {} }); var errMessage = /Invalid non-string\/buffer chunk/; diff --git a/test/parallel/test-stream-readable-needReadable.js b/test/parallel/test-stream-readable-needReadable.js index d837c9445d..b7e1d5ec7f 100644 --- a/test/parallel/test-stream-readable-needReadable.js +++ b/test/parallel/test-stream-readable-needReadable.js @@ -6,7 +6,7 @@ var assert = require('assert/'); var Readable = require('../../').Readable; var readable = new Readable({ - read: common.noop + read: function () {} }); // Initialized to false. @@ -30,7 +30,7 @@ readable.on('end', common.mustCall(function () { })); var asyncReadable = new Readable({ - read: common.noop + read: function () {} }); asyncReadable.on('readable', common.mustCall(function () { @@ -53,7 +53,7 @@ process.nextTick(common.mustCall(function () { })); var flowing = new Readable({ - read: common.noop + read: function () {} }); // Notice this must be above the on('data') call. @@ -71,7 +71,7 @@ flowing.on('data', common.mustCall(function (data) { }, 3)); var slowProducer = new Readable({ - read: common.noop + read: function () {} }); slowProducer.on('readable', common.mustCall(function () { diff --git a/test/parallel/test-stream-readableListening-state.js b/test/parallel/test-stream-readableListening-state.js index ae42e8711e..08e552145f 100644 --- a/test/parallel/test-stream-readableListening-state.js +++ b/test/parallel/test-stream-readableListening-state.js @@ -7,7 +7,7 @@ var assert = require('assert/'); var stream = require('../../'); var r = new stream.Readable({ - read: common.noop + read: function () {} }); // readableListening state should start in `false`. @@ -21,7 +21,7 @@ r.on('readable', common.mustCall(function () { r.push(bufferShim.from('Testing readableListening state')); var r2 = new stream.Readable({ - read: common.noop + read: function () {} }); // readableListening state should start in `false`. diff --git a/test/parallel/test-stream-transform-split-highwatermark.js b/test/parallel/test-stream-transform-split-highwatermark.js new file mode 100644 index 0000000000..2c3b034a81 --- /dev/null +++ b/test/parallel/test-stream-transform-split-highwatermark.js @@ -0,0 +1,76 @@ +/**/ +var bufferShim = require('safe-buffer').Buffer; +/**/ +require('../common'); +var assert = require('assert/'); + +var _require = require('../../'), + Transform = _require.Transform, + Readable = _require.Readable, + Writable = _require.Writable; + +var DEFAULT = 16 * 1024; + +function testTransform(expectedReadableHwm, expectedWritableHwm, options) { + var t = new Transform(options); + assert.strictEqual(t._readableState.highWaterMark, expectedReadableHwm); + assert.strictEqual(t._writableState.highWaterMark, expectedWritableHwm); +} + +// test overriding defaultHwm +testTransform(666, DEFAULT, { readableHighWaterMark: 666 }); +testTransform(DEFAULT, 777, { writableHighWaterMark: 777 }); +testTransform(666, 777, { + readableHighWaterMark: 666, + writableHighWaterMark: 777 +}); + +// test 0 overriding defaultHwm +testTransform(0, DEFAULT, { readableHighWaterMark: 0 }); +testTransform(DEFAULT, 0, { writableHighWaterMark: 0 }); + +// test highWaterMark overriding +testTransform(555, 555, { + highWaterMark: 555, + readableHighWaterMark: 666 +}); +testTransform(555, 555, { + highWaterMark: 555, + writableHighWaterMark: 777 +}); +testTransform(555, 555, { + highWaterMark: 555, + readableHighWaterMark: 666, + writableHighWaterMark: 777 +}); + +// test highWaterMark = 0 overriding +testTransform(0, 0, { + highWaterMark: 0, + readableHighWaterMark: 666 +}); +testTransform(0, 0, { + highWaterMark: 0, + writableHighWaterMark: 777 +}); +testTransform(0, 0, { + highWaterMark: 0, + readableHighWaterMark: 666, + writableHighWaterMark: 777 +}); + +// test undefined, null, NaN +[undefined, null, NaN].forEach(function (v) { + testTransform(DEFAULT, DEFAULT, { readableHighWaterMark: v }); + testTransform(DEFAULT, DEFAULT, { writableHighWaterMark: v }); + testTransform(666, DEFAULT, { highWaterMark: v, readableHighWaterMark: 666 }); + testTransform(DEFAULT, 777, { highWaterMark: v, writableHighWaterMark: 777 }); +}); + +// test non Duplex streams ignore the options +{ + var r = new Readable({ readableHighWaterMark: 666 }); + assert.strictEqual(r._readableState.highWaterMark, DEFAULT); + var w = new Writable({ writableHighWaterMark: 777 }); + assert.strictEqual(w._writableState.highWaterMark, DEFAULT); +} \ No newline at end of file diff --git a/test/parallel/test-stream-uint8array.js b/test/parallel/test-stream-uint8array.js index 9351aa3794..def15cd61a 100644 --- a/test/parallel/test-stream-uint8array.js +++ b/test/parallel/test-stream-uint8array.js @@ -5,7 +5,6 @@ var bufferShim = require('safe-buffer').Buffer; /**/ var common = require('../common'); var assert = require('assert/'); -var Buffer = require('buffer').Buffer; var _require = require('../../'), Readable = _require.Readable, diff --git a/test/parallel/test-stream-writable-change-default-encoding.js b/test/parallel/test-stream-writable-change-default-encoding.js index 9b555ee854..05f37cc014 100644 --- a/test/parallel/test-stream-writable-change-default-encoding.js +++ b/test/parallel/test-stream-writable-change-default-encoding.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -26,19 +32,26 @@ require('../common'); var assert = require('assert/'); var stream = require('../../'); -var util = require('util'); -function MyWritable(fn, options) { - stream.Writable.call(this, options); - this.fn = fn; -} +var MyWritable = function (_stream$Writable) { + _inherits(MyWritable, _stream$Writable); + + function MyWritable(fn, options) { + _classCallCheck(this, MyWritable); + + var _this = _possibleConstructorReturn(this, _stream$Writable.call(this, options)); + + _this.fn = fn; + return _this; + } -util.inherits(MyWritable, stream.Writable); + MyWritable.prototype._write = function _write(chunk, encoding, callback) { + this.fn(Buffer.isBuffer(chunk), typeof chunk, encoding); + callback(); + }; -MyWritable.prototype._write = function (chunk, encoding, callback) { - this.fn(Buffer.isBuffer(chunk), typeof chunk, encoding); - callback(); -}; + return MyWritable; +}(stream.Writable); (function defaultCondingIsUtf8() { var m = new MyWritable(function (isBuffer, type, enc) { @@ -62,7 +75,7 @@ assert.throws(function changeDefaultEncodingToInvalidValue() { m.setDefaultEncoding({}); m.write('bar'); m.end(); -}, TypeError); +}, /^TypeError: Unknown encoding: \[object Object\]$/); (function checkVairableCaseEncoding() { var m = new MyWritable(function (isBuffer, type, enc) { diff --git a/test/parallel/test-stream-writable-decoded-encoding.js b/test/parallel/test-stream-writable-decoded-encoding.js index 85912beaec..e9c71ffa39 100644 --- a/test/parallel/test-stream-writable-decoded-encoding.js +++ b/test/parallel/test-stream-writable-decoded-encoding.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -26,19 +32,26 @@ require('../common'); var assert = require('assert/'); var stream = require('../../'); -var util = require('util'); -function MyWritable(fn, options) { - stream.Writable.call(this, options); - this.fn = fn; -} +var MyWritable = function (_stream$Writable) { + _inherits(MyWritable, _stream$Writable); + + function MyWritable(fn, options) { + _classCallCheck(this, MyWritable); + + var _this = _possibleConstructorReturn(this, _stream$Writable.call(this, options)); + + _this.fn = fn; + return _this; + } -util.inherits(MyWritable, stream.Writable); + MyWritable.prototype._write = function _write(chunk, encoding, callback) { + this.fn(Buffer.isBuffer(chunk), typeof chunk, encoding); + callback(); + }; -MyWritable.prototype._write = function (chunk, encoding, callback) { - this.fn(Buffer.isBuffer(chunk), typeof chunk, encoding); - callback(); -}; + return MyWritable; +}(stream.Writable); { var m = new MyWritable(function (isBuffer, type, enc) { diff --git a/test/parallel/test-stream-writable-null.js b/test/parallel/test-stream-writable-null.js index f770f89e3b..bfafc7ff55 100644 --- a/test/parallel/test-stream-writable-null.js +++ b/test/parallel/test-stream-writable-null.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + /**/ var bufferShim = require('safe-buffer').Buffer; /**/ @@ -5,25 +11,30 @@ require('../common'); var assert = require('assert/'); var stream = require('../../'); -var util = require('util'); -function MyWritable(options) { - stream.Writable.call(this, options); -} +var MyWritable = function (_stream$Writable) { + _inherits(MyWritable, _stream$Writable); + + function MyWritable(opt) { + _classCallCheck(this, MyWritable); + + return _possibleConstructorReturn(this, _stream$Writable.call(this, opt)); + } -util.inherits(MyWritable, stream.Writable); + MyWritable.prototype._write = function _write(chunk, encoding, callback) { + assert.notStrictEqual(chunk, null); + callback(); + }; -MyWritable.prototype._write = function (chunk, encoding, callback) { - assert.notStrictEqual(chunk, null); - callback(); -}; + return MyWritable; +}(stream.Writable); assert.throws(function () { var m = new MyWritable({ objectMode: true }); m.write(null, function (err) { return assert.ok(err); }); -}, TypeError, 'May not write null values to stream'); +}, /^TypeError: May not write null values to stream$/); assert.doesNotThrow(function () { var m = new MyWritable({ objectMode: true }).on('error', function (e) { assert.ok(e); @@ -38,7 +49,7 @@ assert.throws(function () { m.write(false, function (err) { return assert.ok(err); }); -}, TypeError, 'Invalid non-string/buffer chunk'); +}, /^TypeError: Invalid non-string\/buffer chunk$/); assert.doesNotThrow(function () { var m = new MyWritable().on('error', function (e) { assert.ok(e); diff --git a/test/parallel/test-stream2-basic.js b/test/parallel/test-stream2-basic.js index 00875cf56a..0a0b364ed3 100644 --- a/test/parallel/test-stream2-basic.js +++ b/test/parallel/test-stream2-basic.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -27,66 +33,83 @@ var common = require('../common'); var R = require('../../lib/_stream_readable'); var assert = require('assert/'); -var util = require('util'); var EE = require('events').EventEmitter; -function TestReader(n) { - R.apply(this); - this._buffer = bufferShim.alloc(n || 100, 'x'); - this._pos = 0; - this._bufs = 10; -} +var TestReader = function (_R) { + _inherits(TestReader, _R); -util.inherits(TestReader, R); + function TestReader(n) { + _classCallCheck(this, TestReader); -TestReader.prototype._read = function (n) { - var max = this._buffer.length - this._pos; - n = Math.max(n, 0); - var toRead = Math.min(n, max); - if (toRead === 0) { - // simulate the read buffer filling up with some more bytes some time - // in the future. - setTimeout(function () { - this._pos = 0; - this._bufs -= 1; - if (this._bufs <= 0) { - // read them all! - if (!this.ended) this.push(null); - } else { - // now we have more. - // kinda cheating by calling _read, but whatever, - // it's just fake anyway. - this._read(n); - } - }.bind(this), 10); - return; + var _this = _possibleConstructorReturn(this, _R.call(this)); + + _this._buffer = bufferShim.alloc(n || 100, 'x'); + _this._pos = 0; + _this._bufs = 10; + return _this; } - var ret = this._buffer.slice(this._pos, this._pos + toRead); - this._pos += toRead; - this.push(ret); -}; + TestReader.prototype._read = function _read(n) { + var _this2 = this; + + var max = this._buffer.length - this._pos; + n = Math.max(n, 0); + var toRead = Math.min(n, max); + if (toRead === 0) { + // simulate the read buffer filling up with some more bytes some time + // in the future. + setTimeout(function () { + _this2._pos = 0; + _this2._bufs -= 1; + if (_this2._bufs <= 0) { + // read them all! + if (!_this2.ended) _this2.push(null); + } else { + // now we have more. + // kinda cheating by calling _read, but whatever, + // it's just fake anyway. + _this2._read(n); + } + }, 10); + return; + } + + var ret = this._buffer.slice(this._pos, this._pos + toRead); + this._pos += toRead; + this.push(ret); + }; + + return TestReader; +}(R); ///// -function TestWriter() { - EE.apply(this); - this.received = []; - this.flush = false; -} +var TestWriter = function (_EE) { + _inherits(TestWriter, _EE); + + function TestWriter() { + _classCallCheck(this, TestWriter); + + var _this3 = _possibleConstructorReturn(this, _EE.call(this)); -util.inherits(TestWriter, EE); + _this3.received = []; + _this3.flush = false; + return _this3; + } + + TestWriter.prototype.write = function write(c) { + this.received.push(c.toString()); + this.emit('write', c); + return true; + }; -TestWriter.prototype.write = function (c) { - this.received.push(c.toString()); - this.emit('write', c); - return true; -}; + TestWriter.prototype.end = function end(c) { + if (c) this.write(c); + this.emit('end', this.received); + }; -TestWriter.prototype.end = function (c) { - if (c) this.write(c); - this.emit('end', this.received); -}; + return TestWriter; +}(EE); { // Test basic functionality diff --git a/test/parallel/test-stream2-compatibility.js b/test/parallel/test-stream2-compatibility.js index 2debe5b206..4737f9a282 100644 --- a/test/parallel/test-stream2-compatibility.js +++ b/test/parallel/test-stream2-compatibility.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -27,25 +33,31 @@ var R = require('../../lib/_stream_readable'); var W = require('../../lib/_stream_writable'); var assert = require('assert/'); -var util = require('util'); - var ondataCalled = 0; -function TestReader() { - R.apply(this); - this._buffer = bufferShim.alloc(100, 'x'); +var TestReader = function (_R) { + _inherits(TestReader, _R); + + function TestReader() { + _classCallCheck(this, TestReader); - this.on('data', function () { - ondataCalled++; - }); -} + var _this = _possibleConstructorReturn(this, _R.call(this)); -util.inherits(TestReader, R); + _this._buffer = bufferShim.alloc(100, 'x'); -TestReader.prototype._read = function (n) { - this.push(this._buffer); - this._buffer = bufferShim.alloc(0); -}; + _this.on('data', function () { + ondataCalled++; + }); + return _this; + } + + TestReader.prototype._read = function _read(n) { + this.push(this._buffer); + this._buffer = bufferShim.alloc(0); + }; + + return TestReader; +}(R); var reader = new TestReader(); setImmediate(function () { @@ -54,17 +66,25 @@ setImmediate(function () { reader.push(null); }); -function TestWriter() { - W.apply(this); - this.write('foo'); - this.end(); -} +var TestWriter = function (_W) { + _inherits(TestWriter, _W); + + function TestWriter() { + _classCallCheck(this, TestWriter); + + var _this2 = _possibleConstructorReturn(this, _W.call(this)); + + _this2.write('foo'); + _this2.end(); + return _this2; + } -util.inherits(TestWriter, W); + TestWriter.prototype._write = function _write(chunk, enc, cb) { + cb(); + }; -TestWriter.prototype._write = function (chunk, enc, cb) { - cb(); -}; + return TestWriter; +}(W); var writer = new TestWriter(); diff --git a/test/parallel/test-stream2-finish-pipe.js b/test/parallel/test-stream2-finish-pipe.js index 5f0490f4c2..1566ee3652 100644 --- a/test/parallel/test-stream2-finish-pipe.js +++ b/test/parallel/test-stream2-finish-pipe.js @@ -24,7 +24,6 @@ var bufferShim = require('safe-buffer').Buffer; /**/ require('../common'); var stream = require('../../'); -var Buffer = require('buffer').Buffer; var r = new stream.Readable(); r._read = function (size) { diff --git a/test/parallel/test-stream2-pipe-error-once-listener.js b/test/parallel/test-stream2-pipe-error-once-listener.js index 83f05b769b..2b8e467cf3 100644 --- a/test/parallel/test-stream2-pipe-error-once-listener.js +++ b/test/parallel/test-stream2-pipe-error-once-listener.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -23,34 +29,47 @@ var bufferShim = require('safe-buffer').Buffer; /**/ -var common = require('../common'); -var util = require('util'); +require('../common'); var stream = require('../../'); -function Read() { - stream.Readable.call(this); -} -util.inherits(Read, stream.Readable); +var Read = function (_stream$Readable) { + _inherits(Read, _stream$Readable); + + function Read() { + _classCallCheck(this, Read); + + return _possibleConstructorReturn(this, _stream$Readable.apply(this, arguments)); + } + + Read.prototype._read = function _read(size) { + this.push('x'); + this.push(null); + }; + + return Read; +}(stream.Readable); + +var Write = function (_stream$Writable) { + _inherits(Write, _stream$Writable); + + function Write() { + _classCallCheck(this, Write); -Read.prototype._read = function (size) { - this.push('x'); - this.push(null); -}; + return _possibleConstructorReturn(this, _stream$Writable.apply(this, arguments)); + } -function Write() { - stream.Writable.call(this); -} -util.inherits(Write, stream.Writable); + Write.prototype._write = function _write(buffer, encoding, cb) { + this.emit('error', new Error('boom')); + this.emit('alldone'); + }; -Write.prototype._write = function (buffer, encoding, cb) { - this.emit('error', new Error('boom')); - this.emit('alldone'); -}; + return Write; +}(stream.Writable); var read = new Read(); var write = new Write(); -write.once('error', common.noop); +write.once('error', function () {}); write.once('alldone', function (err) { console.log('ok'); }); diff --git a/test/parallel/test-stream2-push.js b/test/parallel/test-stream2-push.js index 4c0bc87594..197a37ffd9 100644 --- a/test/parallel/test-stream2-push.js +++ b/test/parallel/test-stream2-push.js @@ -23,10 +23,12 @@ var bufferShim = require('safe-buffer').Buffer; /**/ require('../common'); -var Readable = require('../../').Readable; -var Writable = require('../../').Writable; var assert = require('assert/'); +var _require = require('../../'), + Readable = _require.Readable, + Writable = _require.Writable; + var EE = require('events').EventEmitter; // a mock thing a bit like the net.Socket/tcp_wrap.handle interaction diff --git a/test/parallel/test-stream2-readable-wrap-empty.js b/test/parallel/test-stream2-readable-wrap-empty.js index be5daf5386..165af42be5 100644 --- a/test/parallel/test-stream2-readable-wrap-empty.js +++ b/test/parallel/test-stream2-readable-wrap-empty.js @@ -28,11 +28,11 @@ var Readable = require('../../lib/_stream_readable'); var EE = require('events').EventEmitter; var oldStream = new EE(); -oldStream.pause = common.noop; -oldStream.resume = common.noop; +oldStream.pause = function () {}; +oldStream.resume = function () {}; var newStream = new Readable().wrap(oldStream); -newStream.on('readable', common.noop).on('end', common.mustCall()); +newStream.on('readable', function () {}).on('end', common.mustCall()); oldStream.emit('end'); \ No newline at end of file diff --git a/test/parallel/test-stream2-set-encoding.js b/test/parallel/test-stream2-set-encoding.js index 355a095f40..ebf1fd3f0e 100644 --- a/test/parallel/test-stream2-set-encoding.js +++ b/test/parallel/test-stream2-set-encoding.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -25,39 +31,46 @@ var bufferShim = require('safe-buffer').Buffer; var common = require('../common'); var assert = require('assert/'); var R = require('../../lib/_stream_readable'); -var util = require('util'); -util.inherits(TestReader, R); +var TestReader = function (_R) { + _inherits(TestReader, _R); -function TestReader(n, opts) { - R.call(this, opts); + function TestReader(n, opts) { + _classCallCheck(this, TestReader); - this.pos = 0; - this.len = n || 100; -} + var _this = _possibleConstructorReturn(this, _R.call(this, opts)); -TestReader.prototype._read = function (n) { - setTimeout(function () { + _this.pos = 0; + _this.len = n || 100; + return _this; + } - if (this.pos >= this.len) { - // double push(null) to test eos handling - this.push(null); - return this.push(null); - } + TestReader.prototype._read = function _read(n) { + var _this2 = this; - n = Math.min(n, this.len - this.pos); - if (n <= 0) { - // double push(null) to test eos handling - this.push(null); - return this.push(null); - } + setTimeout(function () { + if (_this2.pos >= _this2.len) { + // double push(null) to test eos handling + _this2.push(null); + return _this2.push(null); + } + + n = Math.min(n, _this2.len - _this2.pos); + if (n <= 0) { + // double push(null) to test eos handling + _this2.push(null); + return _this2.push(null); + } + + _this2.pos += n; + var ret = bufferShim.alloc(n, 'a'); - this.pos += n; - var ret = bufferShim.alloc(n, 'a'); + return _this2.push(ret); + }, 1); + }; - return this.push(ret); - }.bind(this), 1); -}; + return TestReader; +}(R); { // Verify utf8 encoding diff --git a/test/parallel/test-stream2-transform.js b/test/parallel/test-stream2-transform.js index 098c9040f5..62aa1d2bdb 100644 --- a/test/parallel/test-stream2-transform.js +++ b/test/parallel/test-stream2-transform.js @@ -98,158 +98,167 @@ var Transform = require('../../lib/_stream_transform'); assert(_pt2 instanceof PassThrough); } +{ + // Verify transform constructor behavior + var _pt3 = Transform(); + + assert(_pt3 instanceof Transform); +} + { // Perform a simple transform - var _pt3 = new Transform(); - _pt3._transform = function (c, e, cb) { + var _pt4 = new Transform(); + _pt4._transform = function (c, e, cb) { var ret = bufferShim.alloc(c.length, 'x'); - _pt3.push(ret); + _pt4.push(ret); cb(); }; - _pt3.write(bufferShim.from('foog')); - _pt3.write(bufferShim.from('bark')); - _pt3.write(bufferShim.from('bazy')); - _pt3.write(bufferShim.from('kuel')); - _pt3.end(); + _pt4.write(bufferShim.from('foog')); + _pt4.write(bufferShim.from('bark')); + _pt4.write(bufferShim.from('bazy')); + _pt4.write(bufferShim.from('kuel')); + _pt4.end(); - assert.strictEqual(_pt3.read(5).toString(), 'xxxxx'); - assert.strictEqual(_pt3.read(5).toString(), 'xxxxx'); - assert.strictEqual(_pt3.read(5).toString(), 'xxxxx'); - assert.strictEqual(_pt3.read(5).toString(), 'x'); + assert.strictEqual(_pt4.read(5).toString(), 'xxxxx'); + assert.strictEqual(_pt4.read(5).toString(), 'xxxxx'); + assert.strictEqual(_pt4.read(5).toString(), 'xxxxx'); + assert.strictEqual(_pt4.read(5).toString(), 'x'); } { // Verify simple object transform - var _pt4 = new Transform({ objectMode: true }); - _pt4._transform = function (c, e, cb) { - _pt4.push(JSON.stringify(c)); + var _pt5 = new Transform({ objectMode: true }); + _pt5._transform = function (c, e, cb) { + _pt5.push(JSON.stringify(c)); cb(); }; - _pt4.write(1); - _pt4.write(true); - _pt4.write(false); - _pt4.write(0); - _pt4.write('foo'); - _pt4.write(''); - _pt4.write({ a: 'b' }); - _pt4.end(); + _pt5.write(1); + _pt5.write(true); + _pt5.write(false); + _pt5.write(0); + _pt5.write('foo'); + _pt5.write(''); + _pt5.write({ a: 'b' }); + _pt5.end(); - assert.strictEqual(_pt4.read(), '1'); - assert.strictEqual(_pt4.read(), 'true'); - assert.strictEqual(_pt4.read(), 'false'); - assert.strictEqual(_pt4.read(), '0'); - assert.strictEqual(_pt4.read(), '"foo"'); - assert.strictEqual(_pt4.read(), '""'); - assert.strictEqual(_pt4.read(), '{"a":"b"}'); + assert.strictEqual(_pt5.read(), '1'); + assert.strictEqual(_pt5.read(), 'true'); + assert.strictEqual(_pt5.read(), 'false'); + assert.strictEqual(_pt5.read(), '0'); + assert.strictEqual(_pt5.read(), '"foo"'); + assert.strictEqual(_pt5.read(), '""'); + assert.strictEqual(_pt5.read(), '{"a":"b"}'); } { // Verify async passthrough - var _pt5 = new Transform(); - _pt5._transform = function (chunk, encoding, cb) { + var _pt6 = new Transform(); + _pt6._transform = function (chunk, encoding, cb) { setTimeout(function () { - _pt5.push(chunk); + _pt6.push(chunk); cb(); }, 10); }; - _pt5.write(bufferShim.from('foog')); - _pt5.write(bufferShim.from('bark')); - _pt5.write(bufferShim.from('bazy')); - _pt5.write(bufferShim.from('kuel')); - _pt5.end(); + _pt6.write(bufferShim.from('foog')); + _pt6.write(bufferShim.from('bark')); + _pt6.write(bufferShim.from('bazy')); + _pt6.write(bufferShim.from('kuel')); + _pt6.end(); - _pt5.on('finish', common.mustCall(function () { - assert.strictEqual(_pt5.read(5).toString(), 'foogb'); - assert.strictEqual(_pt5.read(5).toString(), 'arkba'); - assert.strictEqual(_pt5.read(5).toString(), 'zykue'); - assert.strictEqual(_pt5.read(5).toString(), 'l'); + _pt6.on('finish', common.mustCall(function () { + assert.strictEqual(_pt6.read(5).toString(), 'foogb'); + assert.strictEqual(_pt6.read(5).toString(), 'arkba'); + assert.strictEqual(_pt6.read(5).toString(), 'zykue'); + assert.strictEqual(_pt6.read(5).toString(), 'l'); })); } { // Verify assymetric transform (expand) - var _pt6 = new Transform(); + var _pt7 = new Transform(); // emit each chunk 2 times. - _pt6._transform = function (chunk, encoding, cb) { + _pt7._transform = function (chunk, encoding, cb) { setTimeout(function () { - _pt6.push(chunk); + _pt7.push(chunk); setTimeout(function () { - _pt6.push(chunk); + _pt7.push(chunk); cb(); }, 10); }, 10); }; - _pt6.write(bufferShim.from('foog')); - _pt6.write(bufferShim.from('bark')); - _pt6.write(bufferShim.from('bazy')); - _pt6.write(bufferShim.from('kuel')); - _pt6.end(); + _pt7.write(bufferShim.from('foog')); + _pt7.write(bufferShim.from('bark')); + _pt7.write(bufferShim.from('bazy')); + _pt7.write(bufferShim.from('kuel')); + _pt7.end(); - _pt6.on('finish', common.mustCall(function () { - assert.strictEqual(_pt6.read(5).toString(), 'foogf'); - assert.strictEqual(_pt6.read(5).toString(), 'oogba'); - assert.strictEqual(_pt6.read(5).toString(), 'rkbar'); - assert.strictEqual(_pt6.read(5).toString(), 'kbazy'); - assert.strictEqual(_pt6.read(5).toString(), 'bazyk'); - assert.strictEqual(_pt6.read(5).toString(), 'uelku'); - assert.strictEqual(_pt6.read(5).toString(), 'el'); + _pt7.on('finish', common.mustCall(function () { + assert.strictEqual(_pt7.read(5).toString(), 'foogf'); + assert.strictEqual(_pt7.read(5).toString(), 'oogba'); + assert.strictEqual(_pt7.read(5).toString(), 'rkbar'); + assert.strictEqual(_pt7.read(5).toString(), 'kbazy'); + assert.strictEqual(_pt7.read(5).toString(), 'bazyk'); + assert.strictEqual(_pt7.read(5).toString(), 'uelku'); + assert.strictEqual(_pt7.read(5).toString(), 'el'); })); } { // Verify assymetric trasform (compress) - var _pt7 = new Transform(); + var _pt8 = new Transform(); // each output is the first char of 3 consecutive chunks, // or whatever's left. - _pt7.state = ''; + _pt8.state = ''; + + _pt8._transform = function (chunk, encoding, cb) { + var _this = this; - _pt7._transform = function (chunk, encoding, cb) { if (!chunk) chunk = ''; var s = chunk.toString(); setTimeout(function () { - this.state += s.charAt(0); - if (this.state.length === 3) { - _pt7.push(bufferShim.from(this.state)); - this.state = ''; + _this.state += s.charAt(0); + if (_this.state.length === 3) { + _pt8.push(bufferShim.from(_this.state)); + _this.state = ''; } cb(); - }.bind(this), 10); + }, 10); }; - _pt7._flush = function (cb) { + _pt8._flush = function (cb) { // just output whatever we have. - _pt7.push(bufferShim.from(this.state)); + _pt8.push(bufferShim.from(this.state)); this.state = ''; cb(); }; - _pt7.write(bufferShim.from('aaaa')); - _pt7.write(bufferShim.from('bbbb')); - _pt7.write(bufferShim.from('cccc')); - _pt7.write(bufferShim.from('dddd')); - _pt7.write(bufferShim.from('eeee')); - _pt7.write(bufferShim.from('aaaa')); - _pt7.write(bufferShim.from('bbbb')); - _pt7.write(bufferShim.from('cccc')); - _pt7.write(bufferShim.from('dddd')); - _pt7.write(bufferShim.from('eeee')); - _pt7.write(bufferShim.from('aaaa')); - _pt7.write(bufferShim.from('bbbb')); - _pt7.write(bufferShim.from('cccc')); - _pt7.write(bufferShim.from('dddd')); - _pt7.end(); + _pt8.write(bufferShim.from('aaaa')); + _pt8.write(bufferShim.from('bbbb')); + _pt8.write(bufferShim.from('cccc')); + _pt8.write(bufferShim.from('dddd')); + _pt8.write(bufferShim.from('eeee')); + _pt8.write(bufferShim.from('aaaa')); + _pt8.write(bufferShim.from('bbbb')); + _pt8.write(bufferShim.from('cccc')); + _pt8.write(bufferShim.from('dddd')); + _pt8.write(bufferShim.from('eeee')); + _pt8.write(bufferShim.from('aaaa')); + _pt8.write(bufferShim.from('bbbb')); + _pt8.write(bufferShim.from('cccc')); + _pt8.write(bufferShim.from('dddd')); + _pt8.end(); // 'abcdeabcdeabcd' - _pt7.on('finish', common.mustCall(function () { - assert.strictEqual(_pt7.read(5).toString(), 'abcde'); - assert.strictEqual(_pt7.read(5).toString(), 'abcde'); - assert.strictEqual(_pt7.read(5).toString(), 'abcd'); + _pt8.on('finish', common.mustCall(function () { + assert.strictEqual(_pt8.read(5).toString(), 'abcde'); + assert.strictEqual(_pt8.read(5).toString(), 'abcde'); + assert.strictEqual(_pt8.read(5).toString(), 'abcd'); })); } @@ -259,121 +268,121 @@ var Transform = require('../../lib/_stream_transform'); // Verify compex transform behavior var count = 0; var saved = null; - var _pt8 = new Transform({ highWaterMark: 3 }); - _pt8._transform = function (c, e, cb) { + var _pt9 = new Transform({ highWaterMark: 3 }); + _pt9._transform = function (c, e, cb) { if (count++ === 1) saved = c;else { if (saved) { - _pt8.push(saved); + _pt9.push(saved); saved = null; } - _pt8.push(c); + _pt9.push(c); } cb(); }; - _pt8.once('readable', function () { + _pt9.once('readable', function () { process.nextTick(function () { - _pt8.write(bufferShim.from('d')); - _pt8.write(bufferShim.from('ef'), common.mustCall(function () { - _pt8.end(); + _pt9.write(bufferShim.from('d')); + _pt9.write(bufferShim.from('ef'), common.mustCall(function () { + _pt9.end(); })); - assert.strictEqual(_pt8.read().toString(), 'abcdef'); - assert.strictEqual(_pt8.read(), null); + assert.strictEqual(_pt9.read().toString(), 'abcdef'); + assert.strictEqual(_pt9.read(), null); }); }); - _pt8.write(bufferShim.from('abc')); + _pt9.write(bufferShim.from('abc')); } { // Verify passthrough event emission - var _pt9 = new PassThrough(); + var _pt10 = new PassThrough(); var emits = 0; - _pt9.on('readable', function () { + _pt10.on('readable', function () { emits++; }); - _pt9.write(bufferShim.from('foog')); - _pt9.write(bufferShim.from('bark')); + _pt10.write(bufferShim.from('foog')); + _pt10.write(bufferShim.from('bark')); assert.strictEqual(emits, 1); - assert.strictEqual(_pt9.read(5).toString(), 'foogb'); - assert.strictEqual(String(_pt9.read(5)), 'null'); + assert.strictEqual(_pt10.read(5).toString(), 'foogb'); + assert.strictEqual(String(_pt10.read(5)), 'null'); - _pt9.write(bufferShim.from('bazy')); - _pt9.write(bufferShim.from('kuel')); + _pt10.write(bufferShim.from('bazy')); + _pt10.write(bufferShim.from('kuel')); assert.strictEqual(emits, 2); - assert.strictEqual(_pt9.read(5).toString(), 'arkba'); - assert.strictEqual(_pt9.read(5).toString(), 'zykue'); - assert.strictEqual(_pt9.read(5), null); + assert.strictEqual(_pt10.read(5).toString(), 'arkba'); + assert.strictEqual(_pt10.read(5).toString(), 'zykue'); + assert.strictEqual(_pt10.read(5), null); - _pt9.end(); + _pt10.end(); assert.strictEqual(emits, 3); - assert.strictEqual(_pt9.read(5).toString(), 'l'); - assert.strictEqual(_pt9.read(5), null); + assert.strictEqual(_pt10.read(5).toString(), 'l'); + assert.strictEqual(_pt10.read(5), null); assert.strictEqual(emits, 3); } { // Verify passthrough event emission reordering - var _pt10 = new PassThrough(); + var _pt11 = new PassThrough(); var _emits = 0; - _pt10.on('readable', function () { + _pt11.on('readable', function () { _emits++; }); - _pt10.write(bufferShim.from('foog')); - _pt10.write(bufferShim.from('bark')); + _pt11.write(bufferShim.from('foog')); + _pt11.write(bufferShim.from('bark')); assert.strictEqual(_emits, 1); - assert.strictEqual(_pt10.read(5).toString(), 'foogb'); - assert.strictEqual(_pt10.read(5), null); - - _pt10.once('readable', common.mustCall(function () { - assert.strictEqual(_pt10.read(5).toString(), 'arkba'); - assert.strictEqual(_pt10.read(5), null); - - _pt10.once('readable', common.mustCall(function () { - assert.strictEqual(_pt10.read(5).toString(), 'zykue'); - assert.strictEqual(_pt10.read(5), null); - _pt10.once('readable', common.mustCall(function () { - assert.strictEqual(_pt10.read(5).toString(), 'l'); - assert.strictEqual(_pt10.read(5), null); + assert.strictEqual(_pt11.read(5).toString(), 'foogb'); + assert.strictEqual(_pt11.read(5), null); + + _pt11.once('readable', common.mustCall(function () { + assert.strictEqual(_pt11.read(5).toString(), 'arkba'); + assert.strictEqual(_pt11.read(5), null); + + _pt11.once('readable', common.mustCall(function () { + assert.strictEqual(_pt11.read(5).toString(), 'zykue'); + assert.strictEqual(_pt11.read(5), null); + _pt11.once('readable', common.mustCall(function () { + assert.strictEqual(_pt11.read(5).toString(), 'l'); + assert.strictEqual(_pt11.read(5), null); assert.strictEqual(_emits, 4); })); - _pt10.end(); + _pt11.end(); })); - _pt10.write(bufferShim.from('kuel')); + _pt11.write(bufferShim.from('kuel')); })); - _pt10.write(bufferShim.from('bazy')); + _pt11.write(bufferShim.from('bazy')); } { // Verify passthrough facade - var _pt11 = new PassThrough(); + var _pt12 = new PassThrough(); var datas = []; - _pt11.on('data', function (chunk) { + _pt12.on('data', function (chunk) { datas.push(chunk.toString()); }); - _pt11.on('end', common.mustCall(function () { + _pt12.on('end', common.mustCall(function () { assert.deepStrictEqual(datas, ['foog', 'bark', 'bazy', 'kuel']); })); - _pt11.write(bufferShim.from('foog')); + _pt12.write(bufferShim.from('foog')); setTimeout(function () { - _pt11.write(bufferShim.from('bark')); + _pt12.write(bufferShim.from('bark')); setTimeout(function () { - _pt11.write(bufferShim.from('bazy')); + _pt12.write(bufferShim.from('bazy')); setTimeout(function () { - _pt11.write(bufferShim.from('kuel')); + _pt12.write(bufferShim.from('kuel')); setTimeout(function () { - _pt11.end(); + _pt12.end(); }, 10); }, 10); }, 10); diff --git a/test/parallel/test-stream2-unpipe-drain.js b/test/parallel/test-stream2-unpipe-drain.js index 07ea71ef3d..160ded4f06 100644 --- a/test/parallel/test-stream2-unpipe-drain.js +++ b/test/parallel/test-stream2-unpipe-drain.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + (function () { // Copyright Joyent, Inc. and other Node contributors. // @@ -27,30 +33,45 @@ var assert = require('assert/'); var stream = require('../../'); - var util = require('util'); - function TestWriter() { - stream.Writable.call(this); - } - util.inherits(TestWriter, stream.Writable); + var TestWriter = function (_stream$Writable) { + _inherits(TestWriter, _stream$Writable); + + function TestWriter() { + _classCallCheck(this, TestWriter); + + return _possibleConstructorReturn(this, _stream$Writable.apply(this, arguments)); + } - TestWriter.prototype._write = function (buffer, encoding, callback) { - console.log('write called'); - // super slow write stream (callback never called) - }; + TestWriter.prototype._write = function _write(buffer, encoding, callback) { + console.log('write called'); + // super slow write stream (callback never called) + }; + + return TestWriter; + }(stream.Writable); var dest = new TestWriter(); - function TestReader(id) { - stream.Readable.call(this); - this.reads = 0; - } - util.inherits(TestReader, stream.Readable); + var TestReader = function (_stream$Readable) { + _inherits(TestReader, _stream$Readable); + + function TestReader() { + _classCallCheck(this, TestReader); + + var _this2 = _possibleConstructorReturn(this, _stream$Readable.call(this)); + + _this2.reads = 0; + return _this2; + } + + TestReader.prototype._read = function _read(size) { + this.reads += 1; + this.push(bufferShim.alloc(size)); + }; - TestReader.prototype._read = function (size) { - this.reads += 1; - this.push(bufferShim.alloc(size)); - }; + return TestReader; + }(stream.Readable); var src1 = new TestReader(); var src2 = new TestReader(); diff --git a/test/parallel/test-stream2-unpipe-leak.js b/test/parallel/test-stream2-unpipe-leak.js index fae8ece7c0..b50160a886 100644 --- a/test/parallel/test-stream2-unpipe-leak.js +++ b/test/parallel/test-stream2-unpipe-leak.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -28,29 +34,44 @@ var stream = require('../../'); var chunk = bufferShim.from('hallo'); -var util = require('util'); +var TestWriter = function (_stream$Writable) { + _inherits(TestWriter, _stream$Writable); -function TestWriter() { - stream.Writable.call(this); -} -util.inherits(TestWriter, stream.Writable); + function TestWriter() { + _classCallCheck(this, TestWriter); + + return _possibleConstructorReturn(this, _stream$Writable.apply(this, arguments)); + } + + TestWriter.prototype._write = function _write(buffer, encoding, callback) { + callback(null); + }; -TestWriter.prototype._write = function (buffer, encoding, callback) { - callback(null); -}; + return TestWriter; +}(stream.Writable); var dest = new TestWriter(); // Set this high so that we'd trigger a nextTick warning // and/or RangeError if we do maybeReadMore wrong. -function TestReader() { - stream.Readable.call(this, { highWaterMark: 0x10000 }); -} -util.inherits(TestReader, stream.Readable); -TestReader.prototype._read = function (size) { - this.push(chunk); -}; +var TestReader = function (_stream$Readable) { + _inherits(TestReader, _stream$Readable); + + function TestReader() { + _classCallCheck(this, TestReader); + + return _possibleConstructorReturn(this, _stream$Readable.call(this, { + highWaterMark: 0x10000 + })); + } + + TestReader.prototype._read = function _read(size) { + this.push(chunk); + }; + + return TestReader; +}(stream.Readable); var src = new TestReader(); diff --git a/test/parallel/test-stream2-writable.js b/test/parallel/test-stream2-writable.js index f7921dd538..d5d23d28bb 100644 --- a/test/parallel/test-stream2-writable.js +++ b/test/parallel/test-stream2-writable.js @@ -1,3 +1,9 @@ +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a @@ -28,23 +34,32 @@ var W = require('../../lib/_stream_writable'); var D = require('../../lib/_stream_duplex'); var assert = require('assert/'); -var util = require('util'); -util.inherits(TestWriter, W); +var TestWriter = function (_W) { + _inherits(TestWriter, _W); -function TestWriter() { - W.apply(this, arguments); - this.buffer = []; - this.written = 0; -} + function TestWriter(opts) { + _classCallCheck(this, TestWriter); -TestWriter.prototype._write = function (chunk, encoding, cb) { - // simulate a small unpredictable latency - setTimeout(function () { - this.buffer.push(chunk.toString()); - this.written += chunk.length; - cb(); - }.bind(this), Math.floor(Math.random() * 10)); -}; + var _this = _possibleConstructorReturn(this, _W.call(this, opts)); + + _this.buffer = []; + _this.written = 0; + return _this; + } + + TestWriter.prototype._write = function _write(chunk, encoding, cb) { + var _this2 = this; + + // simulate a small unpredictable latency + setTimeout(function () { + _this2.buffer.push(chunk.toString()); + _this2.written += chunk.length; + cb(); + }, Math.floor(Math.random() * 10)); + }; + + return TestWriter; +}(W); var chunks = new Array(50); for (var i = 0; i < chunks.length; i++) {