| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Fixes: nodejs#16564 When StringDecoder's `end` is called, it is no longer supposed to wait for the data. If a `write` call is made after `end`, then the decoder has to be flushed and treated as a brand new write request. This patch also introduces a new StringDecoder#reset method, which simply resets all the internal data.
| internal buffer for the next call to `stringDecoder.write()` or | ||
| `stringDecoder.end()`. | ||
|
|
||
| ### stringDecoder.reset([encoding]) |
There was a problem hiding this comment.
A nit: it seems this should go before the stringDecoder.write(), ABC-wise.
Sorry, something went wrong.
There was a problem hiding this comment.
Done!
Sorry, something went wrong.
| StringDecoder.prototype.reset = StringDecoder; | ||
|
|
||
| StringDecoder.prototype.write = function(buf) { | ||
| if (this._closed === true) |
There was a problem hiding this comment.
=== true is unnecessary
Sorry, something went wrong.
There was a problem hiding this comment.
If we explicitly compare strictly against the value, the performance would be better right?
Sorry, something went wrong.
There was a problem hiding this comment.
Not with TurboFan, no. I asked about this in another PR.
Sorry, something went wrong.
There was a problem hiding this comment.
For reference, I think this is the previous discussion in question: #16397 (comment)
Sorry, something went wrong.
|
What if we do something simpler, like overwrite at least .write() (and possibly .end()) in .end(). Perhaps that would have less overhead? .write() is going to be called more times than .end() in general. |
Sorry, something went wrong.
|
@mscdex In that case, users would have to create a new StringDecoder object every time end is called, right? They cannot reuse it. Also, that would break a lot of buggy code which is already out there I think. |
Sorry, something went wrong.
|
@thefourtheye The basic concern still stands though, .write() is hotter than .end(), so if we can come up with some way to avoid adding stuff to .write() that would be ideal (unless benchmarks show that the current solution does not cause a performance regression). |
Sorry, something went wrong.
| If the `buffer` argument is provided, one final call to `stringDecoder.write()` | ||
| is performed before returning the remaining input. | ||
|
|
||
| ### stringDecoder.reset([encoding]) |
There was a problem hiding this comment.
I believe this is an implementation detail users don't have to know about.
Sorry, something went wrong.
There was a problem hiding this comment.
As it is, there is no way for the users to reset the string decoder, right? They have to create a new instance if needed. This will enable reusability.
Sorry, something went wrong.
There was a problem hiding this comment.
A new way to reset the state each time was not requested as far as I read the issue. So I also prefer not to expose the reset function. If I am correct the following should work.
const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');
decoder.write(Buffer.from([0xE2, 0x82])); // => ''
decoder.end(); // => '�'
decoder.write(Buffer.of(0x61)); // => 'a'
Sorry, something went wrong.
|
|
||
| StringDecoder.prototype.write = function(buf) { | ||
| if (this._closed === true) | ||
| this.reset(); |
There was a problem hiding this comment.
Can this logic be in StringDecoder.prototype.end instead? Make the per-encoding this.end switching in the constructor actually set to an internal symbol-named property, and use a shared StringDecoder.prototype.end that calls that internal encoding-specific function and clean up after itself. Would probably help with write performance too if StringDecoders of different encodings (e.g. UTF-8 which does not have an own property end and UTF-16LE that does) are used simultaneously.
Sorry, something went wrong.
There was a problem hiding this comment.
This seems all very complicated. Why isn't StringDecoder#end just doing:
this.lastNeed = 0;
this.lastTotal = 0;The buffer is already "unsafe" and access to it is guarded, so we don't need to sanitize it. And reusing a constructor as a call seems fraught.
Sorry, something went wrong.
One reason is backwards compatibility. |
Sorry, something went wrong.
|
I have updated the PR to make sure that write doesn't have much any changes. PTAL. |
Sorry, something went wrong.
| function end(buf) { | ||
| let result = ''; | ||
|
|
||
| if (this.encoding === 'utf16le') |
There was a problem hiding this comment.
Might consider using a switch here.
Sorry, something went wrong.
There was a problem hiding this comment.
Ack.
Sorry, something went wrong.
| let result = ''; | ||
|
|
||
| if (this.encoding === 'utf16le') | ||
| result = utf16End.call(this, buf); |
There was a problem hiding this comment.
If we're the only ones calling these methods directly, then we should be able to avoid the overhead of .call() and just pass an instance as another argument.
Sorry, something went wrong.
There was a problem hiding this comment.
Ack.
Sorry, something went wrong.
| else | ||
| result = simpleEnd.call(this, buf); | ||
|
|
||
| this.reset(); |
There was a problem hiding this comment.
Would it be better to use this.reset(this.encoding) to avoid the switch in the constructor?
Sorry, something went wrong.
There was a problem hiding this comment.
We still cannot get rid of the switch in the constructor, right?
Sorry, something went wrong.
There was a problem hiding this comment.
Correct, but this.reset(this.encoding) would only hit that first if in the constructor, which might be better.
Sorry, something went wrong.
| ]); | ||
|
|
||
| function end(buf) { | ||
| const result = (endMappings.get(this.encoding) || simpleEnd)(this, buf); |
There was a problem hiding this comment.
This looks "elegant" but using a switch case for the encoding and calling the function directly is probably faster.
Sorry, something went wrong.
| If the `buffer` argument is provided, one final call to `stringDecoder.write()` | ||
| is performed before returning the remaining input. | ||
|
|
||
| ### stringDecoder.reset([encoding]) |
There was a problem hiding this comment.
A new way to reset the state each time was not requested as far as I read the issue. So I also prefer not to expose the reset function. If I am correct the following should work.
const { StringDecoder } = require('string_decoder');
const decoder = new StringDecoder('utf8');
decoder.write(Buffer.from([0xE2, 0x82])); // => ''
decoder.end(); // => '�'
decoder.write(Buffer.of(0x61)); // => 'a'
Sorry, something went wrong.
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. Refs: nodejs#16594 Fixes: nodejs#16564
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: #18494 Fixes: #16564 Refs: #16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This resets the StringDecoder's state after calling `#end`. Further writes to the decoder will act as if it were a brand new instance, allowing simple reuse. PR-URL: nodejs#18494 Fixes: nodejs#16564 Refs: nodejs#16594 Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
| Back | FazBrowse Home | New Git URL |
Fixes: #16564
When StringDecoder's end is called, it is no longer supposed to wait
for the data. If a write call is made after end, then the decoder
has to be flushed and treated as a brand new write request.
This patch also introduces a new StringDecoder#reset method, which
simply resets all the internal data.
Checklist
Affected core subsystem(s)