├── .airtap.yml ├── .github └── FUNDING.yml ├── .gitignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── index.js ├── package.json ├── readme.markdown ├── security.md └── test ├── buf.js ├── index.js ├── pipeline.js └── use-stream.js /.airtap.yml: -------------------------------------------------------------------------------- 1 | sauce_connect: true 2 | loopback: airtap.local 3 | browsers: 4 | - name: chrome 5 | version: latest 6 | - name: firefox 7 | # extended support releases 52, 60, 68 8 | version: [52, 60, 68, latest] 9 | - name: safari 10 | version: 9..latest 11 | - name: iphone 12 | version: latest 13 | - name: ie 14 | version: 9..latest 15 | - name: microsoftedge 16 | version: 13..latest 17 | browserify: 18 | - plugin: ./test/use-stream.js 19 | - require: tape 20 | expose: tape 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: npm/stream-browserify 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: linux 2 | dist: bionic 3 | language: node_js 4 | jobs: 5 | include: 6 | - name: Run browser tests with airtap 7 | node_js: stable 8 | script: npm run test:browsers 9 | addons: 10 | sauce_connect: true 11 | hosts: 12 | - airtap.local 13 | - name: Test on stable Node.js 14 | node_js: stable 15 | - name: Test on Node.js 12.x 16 | node_js: 12 17 | - name: Test on Node.js 10.x 18 | node_js: 10 19 | - name: Test on Node.js 8.x 20 | node_js: 8 21 | - name: Test on Node.js 6.x 22 | node_js: 6 23 | - name: Test on Node.js 4.x 24 | node_js: 4 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # stream-browserify change log 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | This project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## 3.0.0 8 | * Upgrade to `readable-stream` 3. For breaking changes, see the [readable-stream notes](https://github.com/nodejs/readable-stream#version-3xx). 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) James Halliday 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | // Copyright Joyent, Inc. and other Node contributors. 2 | // 3 | // Permission is hereby granted, free of charge, to any person obtaining a 4 | // copy of this software and associated documentation files (the 5 | // "Software"), to deal in the Software without restriction, including 6 | // without limitation the rights to use, copy, modify, merge, publish, 7 | // distribute, sublicense, and/or sell copies of the Software, and to permit 8 | // persons to whom the Software is furnished to do so, subject to the 9 | // following conditions: 10 | // 11 | // The above copyright notice and this permission notice shall be included 12 | // in all copies or substantial portions of the Software. 13 | // 14 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 | // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | module.exports = Stream; 23 | 24 | var EE = require('events').EventEmitter; 25 | var inherits = require('inherits'); 26 | 27 | inherits(Stream, EE); 28 | Stream.Readable = require('readable-stream/lib/_stream_readable.js'); 29 | Stream.Writable = require('readable-stream/lib/_stream_writable.js'); 30 | Stream.Duplex = require('readable-stream/lib/_stream_duplex.js'); 31 | Stream.Transform = require('readable-stream/lib/_stream_transform.js'); 32 | Stream.PassThrough = require('readable-stream/lib/_stream_passthrough.js'); 33 | Stream.finished = require('readable-stream/lib/internal/streams/end-of-stream.js') 34 | Stream.pipeline = require('readable-stream/lib/internal/streams/pipeline.js') 35 | 36 | // Backwards-compat with node 0.4.x 37 | Stream.Stream = Stream; 38 | 39 | 40 | 41 | // old-style streams. Note that the pipe method (the only relevant 42 | // part of this class) is overridden in the Readable class. 43 | 44 | function Stream() { 45 | EE.call(this); 46 | } 47 | 48 | Stream.prototype.pipe = function(dest, options) { 49 | var source = this; 50 | 51 | function ondata(chunk) { 52 | if (dest.writable) { 53 | if (false === dest.write(chunk) && source.pause) { 54 | source.pause(); 55 | } 56 | } 57 | } 58 | 59 | source.on('data', ondata); 60 | 61 | function ondrain() { 62 | if (source.readable && source.resume) { 63 | source.resume(); 64 | } 65 | } 66 | 67 | dest.on('drain', ondrain); 68 | 69 | // If the 'end' option is not supplied, dest.end() will be called when 70 | // source gets the 'end' or 'close' events. Only dest.end() once. 71 | if (!dest._isStdio && (!options || options.end !== false)) { 72 | source.on('end', onend); 73 | source.on('close', onclose); 74 | } 75 | 76 | var didOnEnd = false; 77 | function onend() { 78 | if (didOnEnd) return; 79 | didOnEnd = true; 80 | 81 | dest.end(); 82 | } 83 | 84 | 85 | function onclose() { 86 | if (didOnEnd) return; 87 | didOnEnd = true; 88 | 89 | if (typeof dest.destroy === 'function') dest.destroy(); 90 | } 91 | 92 | // don't leave dangling pipes when there are errors. 93 | function onerror(er) { 94 | cleanup(); 95 | if (EE.listenerCount(this, 'error') === 0) { 96 | throw er; // Unhandled stream error in pipe. 97 | } 98 | } 99 | 100 | source.on('error', onerror); 101 | dest.on('error', onerror); 102 | 103 | // remove all the event listeners that were added. 104 | function cleanup() { 105 | source.removeListener('data', ondata); 106 | dest.removeListener('drain', ondrain); 107 | 108 | source.removeListener('end', onend); 109 | source.removeListener('close', onclose); 110 | 111 | source.removeListener('error', onerror); 112 | dest.removeListener('error', onerror); 113 | 114 | source.removeListener('end', cleanup); 115 | source.removeListener('close', cleanup); 116 | 117 | dest.removeListener('close', cleanup); 118 | } 119 | 120 | source.on('end', cleanup); 121 | source.on('close', cleanup); 122 | 123 | dest.on('close', cleanup); 124 | 125 | dest.emit('pipe', source); 126 | 127 | // Allow for unix-like usage: A.pipe(B).pipe(C) 128 | return dest; 129 | }; 130 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stream-browserify", 3 | "version": "3.0.0", 4 | "description": "the stream module from node core for browsers", 5 | "main": "index.js", 6 | "dependencies": { 7 | "inherits": "~2.0.4", 8 | "readable-stream": "^3.5.0" 9 | }, 10 | "devDependencies": { 11 | "airtap": "^1.0.2", 12 | "safe-buffer": "^5.1.2", 13 | "tape": "^4.13.0", 14 | "through": "^2.3.8" 15 | }, 16 | "scripts": { 17 | "test": "node test", 18 | "test:browsers": "airtap -- test/index.js" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git://github.com/browserify/stream-browserify.git" 23 | }, 24 | "homepage": "https://github.com/browserify/stream-browserify", 25 | "keywords": [ 26 | "stream", 27 | "browser", 28 | "browserify" 29 | ], 30 | "author": { 31 | "name": "James Halliday", 32 | "email": "mail@substack.net", 33 | "url": "http://substack.net" 34 | }, 35 | "license": "MIT", 36 | "testling": { 37 | "files": "test/*.js", 38 | "browsers": [ 39 | "ie/8..latest", 40 | "firefox/3.5", 41 | "firefox/10", 42 | "firefox/nightly", 43 | "chrome/10", 44 | "chrome/latest", 45 | "chrome/canary", 46 | "opera/12..latest", 47 | "opera/next", 48 | "safari/5.1..latest", 49 | "ipad/6.0..latest", 50 | "iphone/6.0..latest", 51 | "android-browser/4.2..latest" 52 | ] 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /readme.markdown: -------------------------------------------------------------------------------- 1 | # stream-browserify 2 | 3 | the stream module from node core, for browsers! 4 | 5 | This module uses [`readable-stream`](https://github.com/nodejs/readable-stream), with additions for compatibility with npm packages that use old Node.js stream APIs. 6 | 7 | [![build status](https://secure.travis-ci.org/browserify/stream-browserify.svg?branch=master)](http://travis-ci.org/browserify/stream-browserify) 8 | 9 | ## Install 10 | 11 | You usually do not have to install `stream-browserify` yourself! If your code runs in Node.js, `stream` is built in, or `readable-stream` can be used. If your code runs in the browser, bundlers like [browserify](https://github.com/browserify/browserify) also include the `stream-browserify` module. 12 | 13 | But if none of those apply, with [npm](https://npmjs.org) do: 14 | 15 | ```bash 16 | npm install stream-browserify 17 | ``` 18 | 19 | ## API 20 | 21 | Consult the node core 22 | [documentation on streams](http://nodejs.org/docs/latest/api/stream.html). 23 | 24 | ## Browser Support 25 | 26 | Cross-browser testing generously provided by [Sauce Labs](https://saucelabs.com). 27 | 28 | [![Sauce Test Status](https://saucelabs.com/browser-matrix/stream-browserify.svg)](https://saucelabs.com/u/stream-browserify) 29 | 30 | ## License 31 | 32 | [MIT](./LICENSE) 33 | -------------------------------------------------------------------------------- /security.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | Only the latest major version is supported at any given time. 5 | 6 | ## Reporting a Vulnerability 7 | 8 | To report a security vulnerability, please use the 9 | [Tidelift security contact](https://tidelift.com/security). 10 | Tidelift will coordinate the fix and disclosure. 11 | -------------------------------------------------------------------------------- /test/buf.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var test = require('tape'); 3 | var Buffer = require('safe-buffer').Buffer; 4 | 5 | var Writable = require('..').Writable; 6 | var inherits = require('inherits'); 7 | 8 | inherits(TestWritable, Writable); 9 | 10 | function TestWritable(opt) { 11 | if (!(this instanceof TestWritable)) 12 | return new TestWritable(opt); 13 | Writable.call(this, opt); 14 | this._written = []; 15 | } 16 | 17 | TestWritable.prototype._write = function(chunk, encoding, cb) { 18 | this._written.push(chunk); 19 | cb(); 20 | }; 21 | 22 | var buf = Buffer.from([ 88 ]); 23 | 24 | test('.writable writing ArrayBuffer', function(t) { 25 | var writable = new TestWritable(); 26 | 27 | writable.write(buf); 28 | writable.end(); 29 | 30 | t.equal(writable._written.length, 1); 31 | t.equal(writable._written[0].toString(), 'X') 32 | t.end() 33 | }); 34 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | require('./buf'); 2 | require('./pipeline'); 3 | -------------------------------------------------------------------------------- /test/pipeline.js: -------------------------------------------------------------------------------- 1 | var test = require('tape'); 2 | var pipeline = require('..').pipeline; 3 | var stream = require('..'); 4 | var Buffer = require('safe-buffer').Buffer; 5 | 6 | test('supports pipeline', function(t) { 7 | t.plan(4); 8 | var readable = new stream.Readable({ 9 | read: function () { 10 | this.push(Buffer.from('chunk', 'ascii')); 11 | } 12 | }); 13 | var transform1 = new stream.Transform({ 14 | transform: function (chunk, enc, cb) { 15 | cb(new Error('fail')); 16 | } 17 | }); 18 | var transform2 = new stream.PassThrough(); 19 | transform2.on('close', function () { 20 | t.pass('transform2.close called'); 21 | }); 22 | var writable = new stream.Writable({ 23 | write: function (chunk, enc, cb) { cb(); } 24 | }); 25 | writable.on('close', function () { 26 | t.pass('writable.close called'); 27 | }); 28 | 29 | pipeline( 30 | readable, 31 | transform1, 32 | transform2, 33 | writable, 34 | function(err) { 35 | t.ok(err); 36 | t.equal(err.message, 'fail'); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/use-stream.js: -------------------------------------------------------------------------------- 1 | // browserify plugin to swap out the `stream` builtin node shim with the stream-browserify version in this repo. 2 | module.exports = function (b) { 3 | b._mdeps.options.modules.stream = require.resolve('../index.js'); 4 | }; 5 | --------------------------------------------------------------------------------