aboutsummaryrefslogtreecommitdiff
path: root/node_modules/cloneable-readable
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2016-10-10 03:43:44 +0200
committerFlorian Dold <florian.dold@gmail.com>2016-10-10 03:43:44 +0200
commitabd94a7f5a50f43c797a11b53549ae48fff667c3 (patch)
treeab8ed457f65cdd72e13e0571d2975729428f1551 /node_modules/cloneable-readable
parenta0247c6a3fd6a09a41a7e35a3441324c4dcb58be (diff)
downloadwallet-core-abd94a7f5a50f43c797a11b53549ae48fff667c3.tar.xz
add node_modules to address #4364
Diffstat (limited to 'node_modules/cloneable-readable')
-rw-r--r--node_modules/cloneable-readable/.npmignore33
-rw-r--r--node_modules/cloneable-readable/.travis.yml8
-rw-r--r--node_modules/cloneable-readable/LICENSE21
-rw-r--r--node_modules/cloneable-readable/README.md52
-rw-r--r--node_modules/cloneable-readable/example.js14
-rw-r--r--node_modules/cloneable-readable/index.js110
-rw-r--r--node_modules/cloneable-readable/package.json102
-rw-r--r--node_modules/cloneable-readable/test.js576
8 files changed, 916 insertions, 0 deletions
diff --git a/node_modules/cloneable-readable/.npmignore b/node_modules/cloneable-readable/.npmignore
new file mode 100644
index 000000000..e920c1671
--- /dev/null
+++ b/node_modules/cloneable-readable/.npmignore
@@ -0,0 +1,33 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+node_modules
+
+# Optional npm cache directory
+.npm
+
+# Optional REPL history
+.node_repl_history
diff --git a/node_modules/cloneable-readable/.travis.yml b/node_modules/cloneable-readable/.travis.yml
new file mode 100644
index 000000000..3e4281a78
--- /dev/null
+++ b/node_modules/cloneable-readable/.travis.yml
@@ -0,0 +1,8 @@
+language: node_js
+sudo: false
+node_js:
+ - "0.10"
+ - "0.12"
+ - "4"
+ - "5"
+ - "6"
diff --git a/node_modules/cloneable-readable/LICENSE b/node_modules/cloneable-readable/LICENSE
new file mode 100644
index 000000000..ecf624507
--- /dev/null
+++ b/node_modules/cloneable-readable/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Matteo Collina
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/cloneable-readable/README.md b/node_modules/cloneable-readable/README.md
new file mode 100644
index 000000000..b62fd1d3a
--- /dev/null
+++ b/node_modules/cloneable-readable/README.md
@@ -0,0 +1,52 @@
+# cloneable-readable
+
+[![Build Status](https://travis-ci.org/mcollina/cloneable-readable.svg?branch=master)](https://travis-ci.org/mcollina/cloneable-readable)
+
+Clone a Readable stream, safely.
+
+```js
+'use strict'
+
+var cloneable = require('cloneable-readable')
+var fs = require('fs')
+var pump = require('pump')
+
+var stream = cloneable(fs.createReadStream('./package.json'))
+
+pump(stream.clone(), fs.createWriteStream('./out1'))
+
+// simulate some asynchronicity
+setImmediate(function () {
+ pump(stream, fs.createWriteStream('./out2'))
+})
+```
+
+**cloneable-readable** automatically handles `objectMode: true`.
+
+This module comes out of an healthy discussion on the 'right' way to
+clone a Readable in https://github.com/gulpjs/vinyl/issues/85
+and https://github.com/nodejs/readable-stream/issues/202. This is my take.
+
+**YOU MUST PIPE ALL CLONES TO START THE FLOW**
+
+You can also attach `'data'` and `'readable'` events to them.
+
+## API
+
+### cloneable(stream)
+
+Create a `Cloneable` stream.
+A Cloneable has a `clone()` method to create more clones.
+All clones must be resumed/piped to start the flow.
+
+### cloneable.isCloneable(stream)
+
+Check if `stream` needs to be wrapped in a `Cloneable` or not.
+
+## Acknowledgements
+
+This project was kindly sponsored by [nearForm](http://nearform.com).
+
+## License
+
+MIT
diff --git a/node_modules/cloneable-readable/example.js b/node_modules/cloneable-readable/example.js
new file mode 100644
index 000000000..e980b9795
--- /dev/null
+++ b/node_modules/cloneable-readable/example.js
@@ -0,0 +1,14 @@
+'use strict'
+
+var cloneable = require('./')
+var fs = require('fs')
+var pump = require('pump')
+
+var stream = cloneable(fs.createReadStream('./package.json'))
+
+pump(stream.clone(), fs.createWriteStream('./out1'))
+
+// simulate some asynchronicity
+setImmediate(function () {
+ pump(stream, fs.createWriteStream('./out2'))
+})
diff --git a/node_modules/cloneable-readable/index.js b/node_modules/cloneable-readable/index.js
new file mode 100644
index 000000000..7696886dd
--- /dev/null
+++ b/node_modules/cloneable-readable/index.js
@@ -0,0 +1,110 @@
+'use strict'
+
+var through2 = require('through2')
+var inherits = require('inherits')
+var nextTick = require('process-nextick-args')
+var Ctor = through2.ctor()
+
+function Cloneable (stream, opts) {
+ if (!(this instanceof Cloneable)) {
+ return new Cloneable(stream, opts)
+ }
+
+ var objectMode = stream._readableState.objectMode
+ this._original = stream
+ this._clonesCount = 1
+
+ opts = opts || {}
+ opts.objectMode = objectMode
+
+ Ctor.call(this, opts)
+
+ forwardDestroy(stream, this)
+
+ this.on('newListener', onData)
+}
+
+inherits(Cloneable, Ctor)
+
+function onData (event, listener) {
+ if (event === 'data' || event === 'readable') {
+ this.removeListener('newListener', onData)
+ nextTick(clonePiped, this)
+ }
+}
+
+Cloneable.prototype.clone = function () {
+ if (!this._original) {
+ throw new Error('already started')
+ }
+
+ this._clonesCount++
+
+ // the events added by the clone should not count
+ // for starting the flow
+ this.removeListener('newListener', onData)
+ var clone = new Clone(this)
+ this.on('newListener', onData)
+
+ return clone
+}
+
+function forwardDestroy (src, dest) {
+ src.on('error', destroy)
+ src.on('close', destroy)
+
+ function destroy (err) {
+ dest.destroy(err)
+ }
+}
+
+function clonePiped (that) {
+ if (--that._clonesCount === 0 && !that._destroyed) {
+ that._original.pipe(that)
+ that._original = undefined
+ }
+}
+
+function Clone (parent, opts) {
+ if (!(this instanceof Clone)) {
+ return new Clone(parent, opts)
+ }
+
+ var objectMode = parent._readableState.objectMode
+
+ opts = opts || {}
+ opts.objectMode = objectMode
+
+ this.parent = parent
+
+ Ctor.call(this, opts)
+
+ forwardDestroy(this.parent, this)
+
+ parent.pipe(this)
+
+ // the events added by the clone should not count
+ // for starting the flow
+ // so we add the newListener handle after we are done
+ this.on('newListener', onDataClone)
+}
+
+function onDataClone (event, listener) {
+ // We start the flow once all clones are piped or destroyed
+ if (event === 'data' || event === 'readable' || event === 'close') {
+ nextTick(clonePiped, this.parent)
+ this.removeListener('newListener', onDataClone)
+ }
+}
+
+inherits(Clone, Ctor)
+
+Clone.prototype.clone = function () {
+ return this.parent.clone()
+}
+
+Cloneable.isCloneable = function (stream) {
+ return stream instanceof Cloneable || stream instanceof Clone
+}
+
+module.exports = Cloneable
diff --git a/node_modules/cloneable-readable/package.json b/node_modules/cloneable-readable/package.json
new file mode 100644
index 000000000..f799200c9
--- /dev/null
+++ b/node_modules/cloneable-readable/package.json
@@ -0,0 +1,102 @@
+{
+ "_args": [
+ [
+ {
+ "raw": "cloneable-readable@^0.5.0",
+ "scope": null,
+ "escapedName": "cloneable-readable",
+ "name": "cloneable-readable",
+ "rawSpec": "^0.5.0",
+ "spec": ">=0.5.0 <0.6.0",
+ "type": "range"
+ },
+ "/home/dold/repos/taler/wallet-webex/node_modules/vinyl"
+ ]
+ ],
+ "_from": "cloneable-readable@>=0.5.0 <0.6.0",
+ "_id": "cloneable-readable@0.5.0",
+ "_inCache": true,
+ "_location": "/cloneable-readable",
+ "_nodeVersion": "4.5.0",
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/cloneable-readable-0.5.0.tgz_1474440194518_0.9048315470572561"
+ },
+ "_npmUser": {
+ "name": "matteo.collina",
+ "email": "hello@matteocollina.com"
+ },
+ "_npmVersion": "2.15.9",
+ "_phantomChildren": {},
+ "_requested": {
+ "raw": "cloneable-readable@^0.5.0",
+ "scope": null,
+ "escapedName": "cloneable-readable",
+ "name": "cloneable-readable",
+ "rawSpec": "^0.5.0",
+ "spec": ">=0.5.0 <0.6.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/vinyl"
+ ],
+ "_resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-0.5.0.tgz",
+ "_shasum": "ad47421f05a8a8ee64fbd21b02b2244409d43510",
+ "_shrinkwrap": null,
+ "_spec": "cloneable-readable@^0.5.0",
+ "_where": "/home/dold/repos/taler/wallet-webex/node_modules/vinyl",
+ "author": {
+ "name": "Matteo Collina",
+ "email": "hello@matteocollina.com"
+ },
+ "bugs": {
+ "url": "https://github.com/mcollina/cloneable-readable/issues"
+ },
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "process-nextick-args": "^1.0.6",
+ "through2": "^2.0.1"
+ },
+ "description": "Clone a Readable stream, safely",
+ "devDependencies": {
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.1",
+ "pre-commit": "^1.1.2",
+ "readable-stream": "^2.1.0",
+ "standard": "^8.0.0",
+ "tap-spec": "^4.1.1",
+ "tape": "^4.6.0"
+ },
+ "directories": {},
+ "dist": {
+ "shasum": "ad47421f05a8a8ee64fbd21b02b2244409d43510",
+ "tarball": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-0.5.0.tgz"
+ },
+ "gitHead": "eeacbed40312015c09c3a2805e860d0cb7336c66",
+ "homepage": "https://github.com/mcollina/cloneable-readable#readme",
+ "keywords": [
+ "readable",
+ "stream",
+ "clone"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "maintainers": [
+ {
+ "name": "matteo.collina",
+ "email": "hello@matteocollina.com"
+ }
+ ],
+ "name": "cloneable-readable",
+ "optionalDependencies": {},
+ "precommit": "test",
+ "readme": "ERROR: No README data found!",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/mcollina/cloneable-readable.git"
+ },
+ "scripts": {
+ "test": "standard && tape test.js | tap-spec"
+ },
+ "version": "0.5.0"
+}
diff --git a/node_modules/cloneable-readable/test.js b/node_modules/cloneable-readable/test.js
new file mode 100644
index 000000000..e1d88d4d9
--- /dev/null
+++ b/node_modules/cloneable-readable/test.js
@@ -0,0 +1,576 @@
+'use strict'
+
+var test = require('tape').test
+var from = require('from2')
+var sink = require('flush-write-stream')
+var cloneable = require('./')
+
+test('basic passthrough', function (t) {
+ t.plan(2)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+})
+
+test('clone sync', function (t) {
+ t.plan(4)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var cloned = instance.clone()
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+
+ cloned.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+})
+
+test('clone async', function (t) {
+ t.plan(4)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var cloned = instance.clone()
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+
+ setImmediate(function () {
+ cloned.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+ })
+})
+
+test('basic passthrough in obj mode', function (t) {
+ t.plan(2)
+
+ var read = false
+ var source = from.obj(function (size, next) {
+ if (read) {
+ return this.push(null)
+ } else {
+ read = true
+ this.push({ hello: 'world' })
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink.obj(function (chunk, enc, cb) {
+ t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
+ cb()
+ }))
+})
+
+test('multiple clone in object mode', function (t) {
+ t.plan(4)
+
+ var read = false
+ var source = from.obj(function (size, next) {
+ if (read) {
+ return this.push(null)
+ } else {
+ read = true
+ this.push({ hello: 'world' })
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var cloned = instance.clone()
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink.obj(function (chunk, enc, cb) {
+ t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
+ cb()
+ }))
+
+ setImmediate(function () {
+ cloned.pipe(sink.obj(function (chunk, enc, cb) {
+ t.deepEqual(chunk, { hello: 'world' }, 'chunk matches')
+ cb()
+ }))
+ })
+})
+
+test('basic passthrough with data event', function (t) {
+ t.plan(2)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var data = ''
+ instance.on('data', function (chunk) {
+ data += chunk.toString()
+ })
+
+ instance.on('end', function () {
+ t.equal(data, 'hello world', 'chunk matches')
+ })
+})
+
+test('basic passthrough with data event on clone', function (t) {
+ t.plan(3)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ var cloned = instance.clone()
+
+ t.notOk(read, 'stream not started')
+
+ var data = ''
+ cloned.on('data', function (chunk) {
+ data += chunk.toString()
+ })
+
+ cloned.on('end', function () {
+ t.equal(data, 'hello world', 'chunk matches in clone')
+ })
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches in instance')
+ cb()
+ }))
+})
+
+test('errors if cloned after start', function (t) {
+ t.plan(2)
+
+ var source = from(function (size, next) {
+ this.push('hello world')
+ this.push(null)
+ next()
+ })
+
+ var instance = cloneable(source)
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ t.throws(function () {
+ instance.clone()
+ }, 'throws if cloned after start')
+ cb()
+ }))
+})
+
+test('basic passthrough with readable event', function (t) {
+ t.plan(2)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var data = ''
+ instance.on('readable', function () {
+ var chunk
+ while ((chunk = this.read()) !== null) {
+ data += chunk.toString()
+ }
+ })
+
+ instance.on('end', function () {
+ t.equal(data, 'hello world', 'chunk matches')
+ })
+})
+
+test('basic passthrough with readable event on clone', function (t) {
+ t.plan(3)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ var cloned = instance.clone()
+
+ t.notOk(read, 'stream not started')
+
+ var data = ''
+ cloned.on('readable', function () {
+ var chunk
+ while ((chunk = this.read()) !== null) {
+ data += chunk.toString()
+ }
+ })
+
+ cloned.on('end', function () {
+ t.equal(data, 'hello world', 'chunk matches in clone')
+ })
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches in instance')
+ cb()
+ }))
+})
+
+test('source error destroys all', function (t) {
+ t.plan(5)
+
+ var source = from()
+ var instance = cloneable(source)
+ var clone = instance.clone()
+
+ source.on('error', function (err) {
+ t.ok(err, 'source errors')
+
+ instance.on('error', function (err2) {
+ t.ok(err === err2, 'instance receives same error')
+ })
+
+ instance.on('close', function () {
+ t.pass('instance is closed')
+ })
+
+ clone.on('error', function (err3) {
+ t.ok(err === err3, 'clone receives same error')
+ })
+
+ clone.on('close', function () {
+ t.pass('clone is closed')
+ })
+ })
+
+ source.emit('error', new Error())
+})
+
+test('source destroy destroys all', function (t) {
+ t.plan(2)
+
+ var source = from()
+ var instance = cloneable(source)
+ var clone = instance.clone()
+
+ instance.on('close', function () {
+ t.pass('instance is closed')
+ })
+
+ clone.on('close', function () {
+ t.pass('clone is closed')
+ })
+
+ source.destroy()
+})
+
+test('instance error destroys all but the source', function (t) {
+ t.plan(4)
+
+ var source = from()
+ var instance = cloneable(source)
+ var clone = instance.clone()
+
+ source.on('close', function () {
+ t.fail('source should not be closed')
+ })
+
+ instance.on('error', function (err) {
+ t.is(err.message, 'beep', 'instance errors')
+
+ instance.on('close', function () {
+ t.pass('instance is closed')
+ })
+
+ clone.on('error', function (err3) {
+ t.ok(err === err3, 'clone receives same error')
+ })
+
+ clone.on('close', function () {
+ t.pass('clone is closed')
+ })
+ })
+
+ instance.destroy(new Error('beep'))
+})
+
+test('instance destroy destroys all but the source', function (t) {
+ t.plan(2)
+
+ var source = from()
+ var instance = cloneable(source)
+ var clone = instance.clone()
+
+ source.on('close', function () {
+ t.fail('source should not be closed')
+ })
+
+ instance.on('close', function () {
+ t.pass('instance is closed')
+ })
+
+ clone.on('close', function () {
+ t.pass('clone is closed')
+ })
+
+ instance.destroy()
+})
+
+test('clone destroy does not affect other clones, cloneable or source', function (t) {
+ t.plan(1)
+
+ var source = from()
+ var instance = cloneable(source)
+ var clone = instance.clone()
+ var other = instance.clone()
+
+ source.on('close', function () {
+ t.fail('source should not be closed')
+ })
+
+ instance.on('close', function () {
+ t.fail('instance should not be closed')
+ })
+
+ other.on('close', function () {
+ t.fail('other clone should not be closed')
+ })
+
+ clone.on('close', function () {
+ t.pass('clone is closed')
+ })
+
+ clone.destroy()
+})
+
+test('clone remains readable if other is destroyed', function (t) {
+ t.plan(3)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ var clone = instance.clone()
+ var other = instance.clone()
+
+ instance.pipe(sink.obj(function (chunk, enc, cb) {
+ t.deepEqual(chunk.toString(), 'hello', 'instance chunk matches')
+ cb()
+ }))
+
+ clone.pipe(sink.obj(function (chunk, enc, cb) {
+ t.deepEqual(chunk.toString(), 'hello', 'clone chunk matches')
+ cb()
+ }))
+
+ clone.on('close', function () {
+ t.fail('clone should not be closed')
+ })
+
+ instance.on('close', function () {
+ t.fail('instance should not be closed')
+ })
+
+ other.on('close', function () {
+ t.pass('other is closed')
+ })
+
+ other.destroy()
+})
+
+test('clone of clone', function (t) {
+ t.plan(6)
+
+ var read = false
+ var source = from(function (size, next) {
+ if (read) {
+ this.push(null)
+ } else {
+ read = true
+ this.push('hello world')
+ }
+ next()
+ })
+
+ var instance = cloneable(source)
+ t.notOk(read, 'stream not started')
+
+ var cloned = instance.clone()
+ t.notOk(read, 'stream not started')
+
+ var replica = cloned.clone()
+ t.notOk(read, 'stream not started')
+
+ instance.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+
+ cloned.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+
+ replica.pipe(sink(function (chunk, enc, cb) {
+ t.equal(chunk.toString(), 'hello world', 'chunk matches')
+ cb()
+ }))
+})
+
+test('from vinyl', function (t) {
+ t.plan(3)
+
+ var source = from(['wa', 'dup'])
+
+ var instance = cloneable(source)
+ var clone = instance.clone()
+
+ var data = ''
+ var data2 = ''
+ var ends = 2
+
+ function latch () {
+ if (--ends === 0) {
+ t.equal(data, data2)
+ }
+ }
+
+ instance.on('data', function (chunk) {
+ data += chunk.toString()
+ })
+
+ process.nextTick(function () {
+ t.equal('', data, 'nothing was written yet')
+ t.equal('', data2, 'nothing was written yet')
+
+ clone.on('data', function (chunk) {
+ data2 += chunk.toString()
+ })
+ })
+
+ instance.on('end', latch)
+ clone.on('end', latch)
+})
+
+test('waits till all are flowing', function (t) {
+ t.plan(1)
+
+ var source = from(['wa', 'dup'])
+
+ var instance = cloneable(source)
+
+ // we create a clone
+ instance.clone()
+
+ instance.on('data', function (chunk) {
+ t.fail('this should never happen')
+ })
+
+ process.nextTick(function () {
+ t.pass('wait till nextTick')
+ })
+})
+
+test('isCloneable', function (t) {
+ t.plan(4)
+
+ var source = from(['hello', ' ', 'world'])
+ t.notOk(cloneable.isCloneable(source), 'a generic readable is not cloneable')
+
+ var instance = cloneable(source)
+ t.ok(cloneable.isCloneable(instance), 'a cloneable is cloneable')
+
+ var clone = instance.clone()
+ t.ok(cloneable.isCloneable(clone), 'a clone is cloneable')
+
+ var cloneClone = clone.clone()
+ t.ok(cloneable.isCloneable(cloneClone), 'a clone of a clone is cloneable')
+})