Bug 848464

Summary: gobject javascript bindings cannot use 64 bit integers
Product: [Community] Virtualization Tools Reporter: Richard W.M. Jones <rjones>
Component: libguestfsAssignee: Richard W.M. Jones <rjones>
Status: NEW --- QA Contact:
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: unspecifiedCC: berrange
Target Milestone: ---   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Richard W.M. Jones 2012-08-15 16:38:36 UTC
Description of problem:

64 bit integers cannot be used reliably via the Javascript
GObject bindings.  This applies to gjs, I didn't test anything
else.  It applies to integer literals, but my belief is this
bug would affect any 64 bit number, not just source code literals
but ones eg. read in from external sources or passed through
to the API from return values from other functions.

Version-Release number of selected component (if applicable):

libguestfs 1.19.30

How reproducible:

100%

Steps to Reproduce:
1. ./run gjs gobject/bindtests.js

Actual results:

Fails on the following line:
o = new Guestfs.InternalTest({obool: true, oint: 1, oint64: 9223372036854775807});
with the error:

    JS ERROR: !!!   Exception was: Error: can't convert 9223372036854776000 to an integer
    JS ERROR: !!!     message = '"can't convert 9223372036854776000 to an integer"'
    JS ERROR: !!!     fileName = '"gobject/bindtests.js"'
    JS ERROR: !!!     lineNumber = '27'
    JS ERROR: !!!     stack = '"@gobject/bindtests.js:27
"'
Error: can't convert 9223372036854776000 to an integer

Additional info:

There seem to be two interacting problems.

(1) Javascript cannot represent 64 bit integers accurately.  We should
be using another type, eg. string.

(2) GObject Introspection converts the number to a 32 bit integer and
fails on overflow, so any time we try to use a number which is larger
than can be held in a 32 bit integer, this is going to fail.

Comment 1 Richard W.M. Jones 2012-11-30 14:36:44 UTC
I had a look into this, and here are my findings:

(1) GObject is a world of pain.  It's a wonder it works at all.

(2) gjs is a thin wrapper around SpiderMonkey, which is the same
Javascript engine used by Firefox (ie. written by Mozilla).
https://developer.mozilla.org/en/docs/SpiderMonkey
http://pkgs.fedoraproject.org/cgit/js.git/

(3) SpiderMonkey has a well-defined embedding API, mainly
designed so you can use it from other applications.  See:
https://developer.mozilla.org/en-US/docs/SpiderMonkey/JSAPI_User_Guide

(4) gjs supports "native modules".  These are .so objects which
are dlopened and load into gjs, they are present on the search
path etc.  All the examples use GObject, but I'm not sure if that's
required -- apart from GObject stupid, most of them just make
direct JSAPI calls.
http://git.gnome.org/browse/gjs/tree/modules/

$ ls -l /usr/lib64/gjs-1.0/
total 240
-rwxr-xr-x. 1 root root 90280 Sep 25 16:52 cairoNative.so
-rwxr-xr-x. 1 root root 11288 Sep 25 16:52 console.so
-rwxr-xr-x. 1 root root 71096 Sep 25 16:52 dbusNative.so
-rwxr-xr-x. 1 root root  6960 Sep 25 16:52 debugger.so
-rwxr-xr-x. 1 root root  7000 Sep 25 16:52 formatNative.so
-rwxr-xr-x. 1 root root 11200 Sep 25 16:52 gettextNative.so
-rwxr-xr-x. 1 root root  6984 Sep 25 16:52 langNative.so
-rwxr-xr-x. 1 root root 15600 Sep 25 16:52 mainloop.so
-rwxr-xr-x. 1 root root 11184 Sep 25 16:52 system.so

So could we not write the Javascript bindings either directly
using the JSAPI, or that plus a thin gjs "native module"
wrapper?  That would eliminate use of GObject Introspection,
and possibly even GObject entirely.