Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
string_decoder: do not declare as a class
There are libraries which invoke StringDecoder using .call
and .inherits, which directly conflicts with making
StringDecoder be a class which can only be invoked with
the new keyword. Revert to declaring it as a function.
  • Loading branch information
apapirovski committed Feb 12, 2018
commit b7d63155316b4a278659f94734ee7a26cc21a712
80 changes: 43 additions & 37 deletions lib/string_decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,47 +56,53 @@ for (var i = 0; i < encodings.length; ++i)
// StringDecoder provides an interface for efficiently splitting a series of
// buffers into a series of JS strings without breaking apart multi-byte
// characters.
class StringDecoder {
constructor(encoding) {
this.encoding = normalizeEncoding(encoding);
this[kNativeDecoder] = Buffer.alloc(kSize);
this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding];
}

write(buf) {
if (typeof buf === 'string')
return buf;
if (!ArrayBuffer.isView(buf))
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buf',
['Buffer', 'Uint8Array', 'ArrayBufferView']);
return decode(this[kNativeDecoder], buf);
}

end(buf) {
let ret = '';
if (buf !== undefined)
ret = this.write(buf);
if (this[kNativeDecoder][kBufferedBytes] > 0)
ret += flush(this[kNativeDecoder]);
return ret;
}
function StringDecoder(encoding) {
this.encoding = normalizeEncoding(encoding);
this[kNativeDecoder] = Buffer.alloc(kSize);
this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding];
}

/* Everything below this line is undocumented legacy stuff. */
StringDecoder.prototype.write = function write(buf) {
if (typeof buf === 'string')
return buf;
if (!ArrayBuffer.isView(buf))
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'buf',
['Buffer', 'Uint8Array', 'ArrayBufferView']);
return decode(this[kNativeDecoder], buf);
};

text(buf, offset) {
this[kNativeDecoder][kMissingBytes] = 0;
this[kNativeDecoder][kBufferedBytes] = 0;
return this.write(buf.slice(offset));
}
StringDecoder.prototype.end = function end(buf) {
let ret = '';
if (buf !== undefined)
ret = this.write(buf);
if (this[kNativeDecoder][kBufferedBytes] > 0)
ret += flush(this[kNativeDecoder]);
return ret;
};

get lastTotal() {
return this[kNativeDecoder][kBufferedBytes] + this.lastNeed;
}
/* Everything below this line is undocumented legacy stuff. */
StringDecoder.prototype.text = function text(buf, offset) {
this[kNativeDecoder][kMissingBytes] = 0;
this[kNativeDecoder][kBufferedBytes] = 0;
return this.write(buf.slice(offset));
};

get lastChar() {
return this[kNativeDecoder].subarray(kIncompleteCharactersStart,
kIncompleteCharactersEnd);
Object.defineProperties(StringDecoder.prototype, {
lastChar: {
configurable: true,
enumerable: true,
get() {
return this[kNativeDecoder].subarray(kIncompleteCharactersStart,
kIncompleteCharactersEnd);
}
},
lastTotal: {
configurable: true,
enumerable: true,
get() {
return this[kNativeDecoder][kBufferedBytes] + this.lastNeed;
}
}
}
});

exports.StringDecoder = StringDecoder;
5 changes: 5 additions & 0 deletions test/parallel/test-string-decoder.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ const StringDecoder = require('string_decoder').StringDecoder;
let decoder = new StringDecoder();
assert.strictEqual(decoder.encoding, 'utf8');

// Should work without 'new' keyword
const decoder2 = {};
StringDecoder.call(decoder2);
assert.strictEqual(decoder2.encoding, 'utf8');

// UTF-8
test('utf-8', Buffer.from('$', 'utf-8'), '$');
test('utf-8', Buffer.from('¢', 'utf-8'), '¢');
Expand Down