[
https://issues.apache.org/jira/browse/THRIFT-4214?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Teodor Atroshenko updated THRIFT-4214:
--------------------------------------
Description:
The service is defined with the following function:
{code:javascript}
map<i64,double> someFunctionName()
{code}
The --gen js:node code:
{code:javascript}
output.writeFieldBegin('success', Thrift.Type.MAP, 0);
output.writeMapBegin(Thrift.Type.I64, Thrift.Type.DOUBLE,
Thrift.objectLength(this.success));
for (var kiter18 in this.success)
{
if (this.success.hasOwnProperty(kiter18))
{
var viter19 = this.success[kiter18];
output.writeI64(kiter18);
output.writeDouble(viter19);
}
}
output.writeMapEnd();
output.writeFieldEnd();
{code}
String {{kiter18}} is passed to {{output.writeI64}}. Only *TBinaryProtocol* is
affected by this. The function
[defenition|https://github.com/apache/thrift/blob/19baeefd8c38d62085891d7956349601f79448b3/lib/nodejs/lib/thrift/binary_protocol.js#L137]:
{code:javascript}
TBinaryProtocol.prototype.writeI64 = function(i64) {
if (i64.buffer) {
this.trans.write(i64.buffer);
} else {
this.trans.write(new Int64(i64).buffer);
}
};
{code}
*Int64*
[constructor|https://github.com/broofa/node-int64/blob/master/Int64.js#L49]
accepts the following arguments:
* new Int64(buffer\[, offset=0]) - Existing Buffer with byte offset
* new Int64(Uint8Array\[, offset=0]) - Existing Uint8Array with a byte offset
* new Int64(string) - Hex string (throws if n is outside int64
range)
* new Int64(number) - Number (throws if n is outside int64 range)
* new Int64(hi, lo) - Raw bits as two 32-bit values
What happens, is that JavaScript object keys are always Strings, so the
generated function passes the object key as-is (in String representation) and
*Int64* library assumes it's a hex string and converts it to a different 64-bit
integer.
For example {{"4398046511580"}} becomes {{\[Int64 value:1189123005158784
octets:00 04 39 80 46 51 15 80]}}
This also happens when returning {{list<i64>}}, however in lists it can be
bypassed by calling {{Number()}} on all Array elements before passing it to
Thrift's {{result()}} function.
To solve this, the compiler can be adding {{Number()}} around everything that
is a decimal number that is passed to {{writeI64}}; and if {{writeI64}} will
never be called with an actual hex string, then js library can be updated to
include the {{Number()}} call around *Int64* constructor argument.
was:
The struct has a service defined as follows:
{code:javascript}
map<i64,double> someFunctionName()
{code}
The --gen js:node code:
{code:javascript}
output.writeFieldBegin('success', Thrift.Type.MAP, 0);
output.writeMapBegin(Thrift.Type.I64, Thrift.Type.DOUBLE,
Thrift.objectLength(this.success));
for (var kiter18 in this.success)
{
if (this.success.hasOwnProperty(kiter18))
{
var viter19 = this.success[kiter18];
output.writeI64(kiter18);
output.writeDouble(viter19);
}
}
output.writeMapEnd();
output.writeFieldEnd();
{code}
String {{kiter18}} is passed to {{output.writeI64}}. Only *TBinaryProtocol* is
affected by this. The function
[defenition|https://github.com/apache/thrift/blob/19baeefd8c38d62085891d7956349601f79448b3/lib/nodejs/lib/thrift/binary_protocol.js#L137]:
{code:javascript}
TBinaryProtocol.prototype.writeI64 = function(i64) {
if (i64.buffer) {
this.trans.write(i64.buffer);
} else {
this.trans.write(new Int64(i64).buffer);
}
};
{code}
*Int64*
[constructor|https://github.com/broofa/node-int64/blob/master/Int64.js#L49]
accepts the following arguments:
* new Int64(buffer\[, offset=0]) - Existing Buffer with byte offset
* new Int64(Uint8Array\[, offset=0]) - Existing Uint8Array with a byte offset
* new Int64(string) - Hex string (throws if n is outside int64
range)
* new Int64(number) - Number (throws if n is outside int64 range)
* new Int64(hi, lo) - Raw bits as two 32-bit values
What happens, is that JavaScript object keys are always Strings, so the
generated function passes the object key as-is (in String representation) and
*Int64* library assumes it's a hex string and converts it to a different 64-bit
integer.
For example {{"4398046511580"}} becomes {{\[Int64 value:1189123005158784
octets:00 04 39 80 46 51 15 80]}}
This also happens when returning {{list<i64>}}, however in lists it can be
bypassed by calling {{Number()}} on all Array elements before passing it to
Thrift's {{result()}} function.
To solve this, the compiler can be adding {{Number()}} around everything that
is a decimal number that is passed to {{writeI64}}; and if {{writeI64}} will
never be called with an actual hex string, then js library can be updated to
include the {{Number()}} call around *Int64* constructor argument.
> map<i64,value> key treated as hex value in JavaScript
> -----------------------------------------------------
>
> Key: THRIFT-4214
> URL: https://issues.apache.org/jira/browse/THRIFT-4214
> Project: Thrift
> Issue Type: Bug
> Components: JavaScript - Compiler, JavaScript - Library
> Affects Versions: 0.10.0
> Reporter: Teodor Atroshenko
> Priority: Blocker
> Labels: easyfix
>
> The service is defined with the following function:
> {code:javascript}
> map<i64,double> someFunctionName()
> {code}
> The --gen js:node code:
> {code:javascript}
> output.writeFieldBegin('success', Thrift.Type.MAP, 0);
> output.writeMapBegin(Thrift.Type.I64, Thrift.Type.DOUBLE,
> Thrift.objectLength(this.success));
> for (var kiter18 in this.success)
> {
> if (this.success.hasOwnProperty(kiter18))
> {
> var viter19 = this.success[kiter18];
> output.writeI64(kiter18);
> output.writeDouble(viter19);
> }
> }
> output.writeMapEnd();
> output.writeFieldEnd();
> {code}
> String {{kiter18}} is passed to {{output.writeI64}}. Only *TBinaryProtocol*
> is affected by this. The function
> [defenition|https://github.com/apache/thrift/blob/19baeefd8c38d62085891d7956349601f79448b3/lib/nodejs/lib/thrift/binary_protocol.js#L137]:
> {code:javascript}
> TBinaryProtocol.prototype.writeI64 = function(i64) {
> if (i64.buffer) {
> this.trans.write(i64.buffer);
> } else {
> this.trans.write(new Int64(i64).buffer);
> }
> };
> {code}
> *Int64*
> [constructor|https://github.com/broofa/node-int64/blob/master/Int64.js#L49]
> accepts the following arguments:
> * new Int64(buffer\[, offset=0]) - Existing Buffer with byte offset
> * new Int64(Uint8Array\[, offset=0]) - Existing Uint8Array with a byte offset
> * new Int64(string) - Hex string (throws if n is outside int64
> range)
> * new Int64(number) - Number (throws if n is outside int64 range)
> * new Int64(hi, lo) - Raw bits as two 32-bit values
> What happens, is that JavaScript object keys are always Strings, so the
> generated function passes the object key as-is (in String representation) and
> *Int64* library assumes it's a hex string and converts it to a different
> 64-bit integer.
> For example {{"4398046511580"}} becomes {{\[Int64 value:1189123005158784
> octets:00 04 39 80 46 51 15 80]}}
> This also happens when returning {{list<i64>}}, however in lists it can be
> bypassed by calling {{Number()}} on all Array elements before passing it to
> Thrift's {{result()}} function.
> To solve this, the compiler can be adding {{Number()}} around everything that
> is a decimal number that is passed to {{writeI64}}; and if {{writeI64}} will
> never be called with an actual hex string, then js library can be updated to
> include the {{Number()}} call around *Int64* constructor argument.
--
This message was sent by Atlassian JIRA
(v6.3.15#6346)