string_decoder: fix regressions
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. StringDecoder#lastNeed was not defined, redefine it using the new interface and fix StringDecoder#lastTotal. PR-URL: https://github.com/nodejs/node/pull/18723 Refs: https://github.com/nodejs/node/pull/18537 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Evan Lucas <evanlucas@me.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
This commit is contained in:
parent
b6000d8285
commit
e782715d0a
@ -56,47 +56,61 @@ for (var i = 0; i < encodings.length; ++i)
|
|||||||
// StringDecoder provides an interface for efficiently splitting a series of
|
// StringDecoder provides an interface for efficiently splitting a series of
|
||||||
// buffers into a series of JS strings without breaking apart multi-byte
|
// buffers into a series of JS strings without breaking apart multi-byte
|
||||||
// characters.
|
// characters.
|
||||||
class StringDecoder {
|
function StringDecoder(encoding) {
|
||||||
constructor(encoding) {
|
this.encoding = normalizeEncoding(encoding);
|
||||||
this.encoding = normalizeEncoding(encoding);
|
this[kNativeDecoder] = Buffer.alloc(kSize);
|
||||||
this[kNativeDecoder] = Buffer.alloc(kSize);
|
this[kNativeDecoder][kEncodingField] = encodingsMap[this.encoding];
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Everything below this line is undocumented legacy stuff. */
|
|
||||||
|
|
||||||
text(buf, offset) {
|
|
||||||
this[kNativeDecoder][kMissingBytes] = 0;
|
|
||||||
this[kNativeDecoder][kBufferedBytes] = 0;
|
|
||||||
return this.write(buf.slice(offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
get lastTotal() {
|
|
||||||
return this[kNativeDecoder][kBufferedBytes] + this.lastNeed;
|
|
||||||
}
|
|
||||||
|
|
||||||
get lastChar() {
|
|
||||||
return this[kNativeDecoder].subarray(kIncompleteCharactersStart,
|
|
||||||
kIncompleteCharactersEnd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 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));
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.defineProperties(StringDecoder.prototype, {
|
||||||
|
lastChar: {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return this[kNativeDecoder].subarray(kIncompleteCharactersStart,
|
||||||
|
kIncompleteCharactersEnd);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lastNeed: {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return this[kNativeDecoder][kMissingBytes];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lastTotal: {
|
||||||
|
configurable: true,
|
||||||
|
enumerable: true,
|
||||||
|
get() {
|
||||||
|
return this[kNativeDecoder][kBufferedBytes] +
|
||||||
|
this[kNativeDecoder][kMissingBytes];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
exports.StringDecoder = StringDecoder;
|
exports.StringDecoder = StringDecoder;
|
||||||
|
@ -29,6 +29,11 @@ const StringDecoder = require('string_decoder').StringDecoder;
|
|||||||
let decoder = new StringDecoder();
|
let decoder = new StringDecoder();
|
||||||
assert.strictEqual(decoder.encoding, 'utf8');
|
assert.strictEqual(decoder.encoding, 'utf8');
|
||||||
|
|
||||||
|
// Should work without 'new' keyword
|
||||||
|
const decoder2 = {};
|
||||||
|
StringDecoder.call(decoder2);
|
||||||
|
assert.strictEqual(decoder2.encoding, 'utf8');
|
||||||
|
|
||||||
// UTF-8
|
// UTF-8
|
||||||
test('utf-8', Buffer.from('$', 'utf-8'), '$');
|
test('utf-8', Buffer.from('$', 'utf-8'), '$');
|
||||||
test('utf-8', Buffer.from('¢', 'utf-8'), '¢');
|
test('utf-8', Buffer.from('¢', 'utf-8'), '¢');
|
||||||
@ -84,6 +89,11 @@ test('utf16le', Buffer.from('3DD84DDC', 'hex'), '\ud83d\udc4d'); // thumbs up
|
|||||||
// Additional UTF-8 tests
|
// Additional UTF-8 tests
|
||||||
decoder = new StringDecoder('utf8');
|
decoder = new StringDecoder('utf8');
|
||||||
assert.strictEqual(decoder.write(Buffer.from('E1', 'hex')), '');
|
assert.strictEqual(decoder.write(Buffer.from('E1', 'hex')), '');
|
||||||
|
|
||||||
|
// A quick test for lastNeed & lastTotal which are undocumented.
|
||||||
|
assert.strictEqual(decoder.lastNeed, 2);
|
||||||
|
assert.strictEqual(decoder.lastTotal, 3);
|
||||||
|
|
||||||
assert.strictEqual(decoder.end(), '\ufffd');
|
assert.strictEqual(decoder.end(), '\ufffd');
|
||||||
|
|
||||||
decoder = new StringDecoder('utf8');
|
decoder = new StringDecoder('utf8');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user