2 var Buffer = require("buffer").Buffer;
3 // Note: not polyfilled with safer-buffer on a purpose, as overrides Buffer
5 // == Extend Node primitives to use iconv-lite =================================
7 module.exports = function (iconv) {
8 var original = undefined; // Place to keep original methods.
10 // Node authors rewrote Buffer internals to make it compatible with
11 // Uint8Array and we cannot patch key functions since then.
12 // Note: this does use older Buffer API on a purpose
13 iconv.supportsNodeEncodingsExtension = !(Buffer.from || new Buffer(0) instanceof Uint8Array);
15 iconv.extendNodeEncodings = function extendNodeEncodings() {
19 if (!iconv.supportsNodeEncodingsExtension) {
20 console.error("ACTION NEEDED: require('iconv-lite').extendNodeEncodings() is not supported in your version of Node");
21 console.error("See more info at https://github.com/ashtuchkin/iconv-lite/wiki/Node-v4-compatibility");
25 var nodeNativeEncodings = {
26 'hex': true, 'utf8': true, 'utf-8': true, 'ascii': true, 'binary': true,
27 'base64': true, 'ucs2': true, 'ucs-2': true, 'utf16le': true, 'utf-16le': true,
30 Buffer.isNativeEncoding = function(enc) {
31 return enc && nodeNativeEncodings[enc.toLowerCase()];
34 // -- SlowBuffer -----------------------------------------------------------
35 var SlowBuffer = require('buffer').SlowBuffer;
37 original.SlowBufferToString = SlowBuffer.prototype.toString;
38 SlowBuffer.prototype.toString = function(encoding, start, end) {
39 encoding = String(encoding || 'utf8').toLowerCase();
41 // Use native conversion when possible
42 if (Buffer.isNativeEncoding(encoding))
43 return original.SlowBufferToString.call(this, encoding, start, end);
45 // Otherwise, use our decoding method.
46 if (typeof start == 'undefined') start = 0;
47 if (typeof end == 'undefined') end = this.length;
48 return iconv.decode(this.slice(start, end), encoding);
51 original.SlowBufferWrite = SlowBuffer.prototype.write;
52 SlowBuffer.prototype.write = function(string, offset, length, encoding) {
53 // Support both (string, offset, length, encoding)
54 // and the legacy (string, encoding, offset, length)
55 if (isFinite(offset)) {
56 if (!isFinite(length)) {
67 offset = +offset || 0;
68 var remaining = this.length - offset;
73 if (length > remaining) {
77 encoding = String(encoding || 'utf8').toLowerCase();
79 // Use native conversion when possible
80 if (Buffer.isNativeEncoding(encoding))
81 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
83 if (string.length > 0 && (length < 0 || offset < 0))
84 throw new RangeError('attempt to write beyond buffer bounds');
86 // Otherwise, use our encoding method.
87 var buf = iconv.encode(string, encoding);
88 if (buf.length < length) length = buf.length;
89 buf.copy(this, offset, 0, length);
93 // -- Buffer ---------------------------------------------------------------
95 original.BufferIsEncoding = Buffer.isEncoding;
96 Buffer.isEncoding = function(encoding) {
97 return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
100 original.BufferByteLength = Buffer.byteLength;
101 Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
102 encoding = String(encoding || 'utf8').toLowerCase();
104 // Use native conversion when possible
105 if (Buffer.isNativeEncoding(encoding))
106 return original.BufferByteLength.call(this, str, encoding);
108 // Slow, I know, but we don't have a better way yet.
109 return iconv.encode(str, encoding).length;
112 original.BufferToString = Buffer.prototype.toString;
113 Buffer.prototype.toString = function(encoding, start, end) {
114 encoding = String(encoding || 'utf8').toLowerCase();
116 // Use native conversion when possible
117 if (Buffer.isNativeEncoding(encoding))
118 return original.BufferToString.call(this, encoding, start, end);
120 // Otherwise, use our decoding method.
121 if (typeof start == 'undefined') start = 0;
122 if (typeof end == 'undefined') end = this.length;
123 return iconv.decode(this.slice(start, end), encoding);
126 original.BufferWrite = Buffer.prototype.write;
127 Buffer.prototype.write = function(string, offset, length, encoding) {
128 var _offset = offset, _length = length, _encoding = encoding;
129 // Support both (string, offset, length, encoding)
130 // and the legacy (string, encoding, offset, length)
131 if (isFinite(offset)) {
132 if (!isFinite(length)) {
143 encoding = String(encoding || 'utf8').toLowerCase();
145 // Use native conversion when possible
146 if (Buffer.isNativeEncoding(encoding))
147 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
149 offset = +offset || 0;
150 var remaining = this.length - offset;
155 if (length > remaining) {
160 if (string.length > 0 && (length < 0 || offset < 0))
161 throw new RangeError('attempt to write beyond buffer bounds');
163 // Otherwise, use our encoding method.
164 var buf = iconv.encode(string, encoding);
165 if (buf.length < length) length = buf.length;
166 buf.copy(this, offset, 0, length);
169 // TODO: Set _charsWritten.
173 // -- Readable -------------------------------------------------------------
174 if (iconv.supportsStreams) {
175 var Readable = require('stream').Readable;
177 original.ReadableSetEncoding = Readable.prototype.setEncoding;
178 Readable.prototype.setEncoding = function setEncoding(enc, options) {
179 // Use our own decoder, it has the same interface.
180 // We cannot use original function as it doesn't handle BOM-s.
181 this._readableState.decoder = iconv.getDecoder(enc, options);
182 this._readableState.encoding = enc;
185 Readable.prototype.collect = iconv._collect;
189 // Remove iconv-lite Node primitive extensions.
190 iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
191 if (!iconv.supportsNodeEncodingsExtension)
194 throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
196 delete Buffer.isNativeEncoding;
198 var SlowBuffer = require('buffer').SlowBuffer;
200 SlowBuffer.prototype.toString = original.SlowBufferToString;
201 SlowBuffer.prototype.write = original.SlowBufferWrite;
203 Buffer.isEncoding = original.BufferIsEncoding;
204 Buffer.byteLength = original.BufferByteLength;
205 Buffer.prototype.toString = original.BufferToString;
206 Buffer.prototype.write = original.BufferWrite;
208 if (iconv.supportsStreams) {
209 var Readable = require('stream').Readable;
211 Readable.prototype.setEncoding = original.ReadableSetEncoding;
212 delete Readable.prototype.collect;
215 original = undefined;