twitst4tz

twitter statistics web application
Log | Files | Refs | README | LICENSE

extend-node.js (8701B)


      1 "use strict";
      2 var Buffer = require("buffer").Buffer;
      3 // Note: not polyfilled with safer-buffer on a purpose, as overrides Buffer
      4 
      5 // == Extend Node primitives to use iconv-lite =================================
      6 
      7 module.exports = function (iconv) {
      8     var original = undefined; // Place to keep original methods.
      9 
     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);
     14 
     15     iconv.extendNodeEncodings = function extendNodeEncodings() {
     16         if (original) return;
     17         original = {};
     18 
     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");
     22             return;
     23         }
     24 
     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,
     28         };
     29 
     30         Buffer.isNativeEncoding = function(enc) {
     31             return enc && nodeNativeEncodings[enc.toLowerCase()];
     32         }
     33 
     34         // -- SlowBuffer -----------------------------------------------------------
     35         var SlowBuffer = require('buffer').SlowBuffer;
     36 
     37         original.SlowBufferToString = SlowBuffer.prototype.toString;
     38         SlowBuffer.prototype.toString = function(encoding, start, end) {
     39             encoding = String(encoding || 'utf8').toLowerCase();
     40 
     41             // Use native conversion when possible
     42             if (Buffer.isNativeEncoding(encoding))
     43                 return original.SlowBufferToString.call(this, encoding, start, end);
     44 
     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);
     49         }
     50 
     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)) {
     57                     encoding = length;
     58                     length = undefined;
     59                 }
     60             } else {  // legacy
     61                 var swap = encoding;
     62                 encoding = offset;
     63                 offset = length;
     64                 length = swap;
     65             }
     66 
     67             offset = +offset || 0;
     68             var remaining = this.length - offset;
     69             if (!length) {
     70                 length = remaining;
     71             } else {
     72                 length = +length;
     73                 if (length > remaining) {
     74                     length = remaining;
     75                 }
     76             }
     77             encoding = String(encoding || 'utf8').toLowerCase();
     78 
     79             // Use native conversion when possible
     80             if (Buffer.isNativeEncoding(encoding))
     81                 return original.SlowBufferWrite.call(this, string, offset, length, encoding);
     82 
     83             if (string.length > 0 && (length < 0 || offset < 0))
     84                 throw new RangeError('attempt to write beyond buffer bounds');
     85 
     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);
     90             return length;
     91         }
     92 
     93         // -- Buffer ---------------------------------------------------------------
     94 
     95         original.BufferIsEncoding = Buffer.isEncoding;
     96         Buffer.isEncoding = function(encoding) {
     97             return Buffer.isNativeEncoding(encoding) || iconv.encodingExists(encoding);
     98         }
     99 
    100         original.BufferByteLength = Buffer.byteLength;
    101         Buffer.byteLength = SlowBuffer.byteLength = function(str, encoding) {
    102             encoding = String(encoding || 'utf8').toLowerCase();
    103 
    104             // Use native conversion when possible
    105             if (Buffer.isNativeEncoding(encoding))
    106                 return original.BufferByteLength.call(this, str, encoding);
    107 
    108             // Slow, I know, but we don't have a better way yet.
    109             return iconv.encode(str, encoding).length;
    110         }
    111 
    112         original.BufferToString = Buffer.prototype.toString;
    113         Buffer.prototype.toString = function(encoding, start, end) {
    114             encoding = String(encoding || 'utf8').toLowerCase();
    115 
    116             // Use native conversion when possible
    117             if (Buffer.isNativeEncoding(encoding))
    118                 return original.BufferToString.call(this, encoding, start, end);
    119 
    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);
    124         }
    125 
    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)) {
    133                     encoding = length;
    134                     length = undefined;
    135                 }
    136             } else {  // legacy
    137                 var swap = encoding;
    138                 encoding = offset;
    139                 offset = length;
    140                 length = swap;
    141             }
    142 
    143             encoding = String(encoding || 'utf8').toLowerCase();
    144 
    145             // Use native conversion when possible
    146             if (Buffer.isNativeEncoding(encoding))
    147                 return original.BufferWrite.call(this, string, _offset, _length, _encoding);
    148 
    149             offset = +offset || 0;
    150             var remaining = this.length - offset;
    151             if (!length) {
    152                 length = remaining;
    153             } else {
    154                 length = +length;
    155                 if (length > remaining) {
    156                     length = remaining;
    157                 }
    158             }
    159 
    160             if (string.length > 0 && (length < 0 || offset < 0))
    161                 throw new RangeError('attempt to write beyond buffer bounds');
    162 
    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);
    167             return length;
    168 
    169             // TODO: Set _charsWritten.
    170         }
    171 
    172 
    173         // -- Readable -------------------------------------------------------------
    174         if (iconv.supportsStreams) {
    175             var Readable = require('stream').Readable;
    176 
    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;
    183             }
    184 
    185             Readable.prototype.collect = iconv._collect;
    186         }
    187     }
    188 
    189     // Remove iconv-lite Node primitive extensions.
    190     iconv.undoExtendNodeEncodings = function undoExtendNodeEncodings() {
    191         if (!iconv.supportsNodeEncodingsExtension)
    192             return;
    193         if (!original)
    194             throw new Error("require('iconv-lite').undoExtendNodeEncodings(): Nothing to undo; extendNodeEncodings() is not called.")
    195 
    196         delete Buffer.isNativeEncoding;
    197 
    198         var SlowBuffer = require('buffer').SlowBuffer;
    199 
    200         SlowBuffer.prototype.toString = original.SlowBufferToString;
    201         SlowBuffer.prototype.write = original.SlowBufferWrite;
    202 
    203         Buffer.isEncoding = original.BufferIsEncoding;
    204         Buffer.byteLength = original.BufferByteLength;
    205         Buffer.prototype.toString = original.BufferToString;
    206         Buffer.prototype.write = original.BufferWrite;
    207 
    208         if (iconv.supportsStreams) {
    209             var Readable = require('stream').Readable;
    210 
    211             Readable.prototype.setEncoding = original.ReadableSetEncoding;
    212             delete Readable.prototype.collect;
    213         }
    214 
    215         original = undefined;
    216     }
    217 }