Skip to content

BigInt-related API fixes and non-breaking changes #285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 1 addition & 1 deletion lib/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ function makeEnum(info) {
for (let i = 0; i < nValues; i++) {
const valueInfo = GI.enum_info_get_value(info, i);
const valueName = getName(valueInfo).toUpperCase()
const value = GI.value_info_get_value(valueInfo)
const value = Number(GI.value_info_get_value(valueInfo))
Object.defineProperty(object, valueName, {
configurable: true,
enumerable: true,
Expand Down
2 changes: 1 addition & 1 deletion lib/inspect.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ function ConstantInfo(info, parent) {

function ValueInfo (info, parent) {
BaseInfo.call(this, info)
this.value = GI.value_info_get_value(info)
this.value = Number(GI.value_info_get_value(info))
}

function PropInfo(info, parent) {
Expand Down
117 changes: 65 additions & 52 deletions src/value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using v8::Array;
using v8::TypedArray;
using v8::Integer;
using v8::BigInt;
using v8::Local;
using v8::Number;
using v8::Object;
Expand All @@ -35,6 +36,22 @@ static void HashPointerToGIArgument (GIArgument *arg, GITypeInfo *type_info);

static bool IsUint8Array (GITypeInfo *type_info);

static int64_t V8ToInt64 (Local<Value> value) {
if (value->IsBigInt())
return value.As<v8::BigInt>()->Int64Value();
return Nan::To<int64_t>(value).ToChecked();
}

static int64_t V8ToUint64Strict (Local<Value> value) {
return Local<BigInt>::Cast(value)->Uint64Value();
}

static int64_t V8ToInt32 (Local<Value> value) {
if (value->IsBigInt())
return value.As<v8::BigInt>()->Int64Value();
return Nan::To<int32_t>(value).ToChecked();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one feels a bit weird, with the name being ToInt32 but it returns an int64_t. Maybe it should return an int32_t?



Local<Value> GIArgumentToV8(GITypeInfo *type_info, GIArgument *arg, long length, bool mustCopy) {
GITypeTag type_tag = g_type_info_get_tag (type_info);
Expand Down Expand Up @@ -64,9 +81,9 @@ Local<Value> GIArgumentToV8(GITypeInfo *type_info, GIArgument *arg, long length,
/* For 64-bit integer types, use a float. When JS and V8 adopt
* bigger sized integer types, start using those instead. */
case GI_TYPE_TAG_INT64:
return New<Number> (arg->v_int64);
return v8::BigInt::New(Isolate::GetCurrent(), arg->v_int64);
case GI_TYPE_TAG_UINT64:
return New<Number> (arg->v_uint64);
return v8::BigInt::NewFromUnsigned(Isolate::GetCurrent(), arg->v_uint64);

case GI_TYPE_TAG_GTYPE: /* c++: gulong */
return v8::BigInt::NewFromUnsigned(Isolate::GetCurrent(), arg->v_ulong);
Expand Down Expand Up @@ -688,28 +705,28 @@ bool V8ToGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> value,
arg->v_boolean = Nan::To<bool> (value).ToChecked();
break;
case GI_TYPE_TAG_INT8:
arg->v_int8 = Nan::To<int32_t> (value).ToChecked();
arg->v_int8 = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT16:
arg->v_int16 = Nan::To<int32_t> (value).ToChecked();
arg->v_int16 = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT32:
arg->v_int = Nan::To<int32_t> (value).ToChecked();
arg->v_int = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT64:
arg->v_int64 = Nan::To<int64_t> (value).ToChecked();
arg->v_int64 = V8ToInt64(value);
break;
case GI_TYPE_TAG_UINT8:
arg->v_uint8 = Nan::To<uint32_t> (value).ToChecked();
arg->v_uint8 = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT16:
arg->v_uint16 = Nan::To<uint32_t> (value).ToChecked();
arg->v_uint16 = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT32:
arg->v_uint = Nan::To<uint32_t> (value).ToChecked();
arg->v_uint = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT64:
arg->v_uint64 = Nan::To<int64_t> (value).ToChecked();
arg->v_uint64 = V8ToInt64(value);
break;
case GI_TYPE_TAG_FLOAT:
arg->v_float = Nan::To<double> (value).ToChecked();
Expand All @@ -718,10 +735,7 @@ bool V8ToGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> value,
arg->v_double = Nan::To<double> (value).ToChecked();
break;
case GI_TYPE_TAG_GTYPE:
if (value->IsBigInt())
arg->v_ulong = value.As<v8::BigInt>()->Uint64Value();
else
arg->v_ulong = Nan::To<int64_t> (value).ToChecked();
arg->v_ulong = V8ToUint64Strict(value);
break;

case GI_TYPE_TAG_UTF8:
Expand Down Expand Up @@ -826,28 +840,28 @@ bool V8ToOutGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> valu
*(gboolean*)arg->v_pointer = Nan::To<bool> (value).ToChecked();
break;
case GI_TYPE_TAG_INT8:
*(gint8*)arg->v_pointer = Nan::To<int32_t> (value).ToChecked();
*(gint8*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT16:
*(gint16*)arg->v_pointer = Nan::To<int32_t> (value).ToChecked();
*(gint16*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT32:
*(gint*)arg->v_pointer = Nan::To<int32_t> (value).ToChecked();
*(gint*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_INT64:
*(gint64*)arg->v_pointer = Nan::To<int64_t> (value).ToChecked();
*(gint64*)arg->v_pointer = V8ToInt64(value);
break;
case GI_TYPE_TAG_UINT8:
*(guint8*)arg->v_pointer = Nan::To<uint32_t> (value).ToChecked();
*(guint8*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT16:
*(guint16*)arg->v_pointer = Nan::To<uint32_t> (value).ToChecked();
*(guint16*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT32:
*(guint*)arg->v_pointer = Nan::To<uint32_t> (value).ToChecked();
*(guint*)arg->v_pointer = V8ToInt32(value);
break;
case GI_TYPE_TAG_UINT64:
*(guint64*)arg->v_pointer = Nan::To<int64_t> (value).ToChecked();
*(guint64*)arg->v_pointer = V8ToInt64(value);
break;
case GI_TYPE_TAG_FLOAT:
*(gfloat*)arg->v_pointer = Nan::To<double> (value).ToChecked();
Expand All @@ -856,10 +870,7 @@ bool V8ToOutGIArgument(GITypeInfo *type_info, GIArgument *arg, Local<Value> valu
*(gdouble*)arg->v_pointer = Nan::To<double> (value).ToChecked();
break;
case GI_TYPE_TAG_GTYPE:
if (value->IsBigInt())
*(gulong*)arg->v_pointer = value.As<v8::BigInt>()->Uint64Value();
else
*(gulong*)arg->v_pointer = Nan::To<int64_t> (value).ToChecked();
*(gulong*)arg->v_pointer = V8ToUint64Strict(value);
break;

case GI_TYPE_TAG_UTF8:
Expand Down Expand Up @@ -918,12 +929,14 @@ bool CanConvertV8ToGIArgument(GITypeInfo *type_info, Local<Value> value, bool ma
case GI_TYPE_TAG_UINT16:
case GI_TYPE_TAG_UINT32:
case GI_TYPE_TAG_UINT64:
return value->IsNumber () || value->IsBigInt ();

case GI_TYPE_TAG_FLOAT:
case GI_TYPE_TAG_DOUBLE:
return value->IsNumber ();

case GI_TYPE_TAG_GTYPE:
return value->IsNumber () || value->IsBigInt ();
return value->IsBigInt ();

case GI_TYPE_TAG_UTF8:
return true;
Expand Down Expand Up @@ -1300,27 +1313,27 @@ bool CanConvertV8ToGValue(GValue *gvalue, Local<Value> value) {
if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
return value->IsBoolean() || value->IsNumber();
} else if (G_VALUE_HOLDS_CHAR (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_UCHAR (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_INT (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_UINT (gvalue)) {
return value->IsNumber();
} else if (G_VALUE_HOLDS_LONG (gvalue)) {
return value->IsNumber();
} else if (G_VALUE_HOLDS_ULONG (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_INT64 (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_UINT64 (gvalue)) {
return value->IsNumber();
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_LONG (gvalue)) {
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_ULONG (gvalue)) {
return value->IsNumber() || value->IsBigInt();
} else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
return value->IsNumber();
} else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
return value->IsNumber();
} else if (G_VALUE_HOLDS_GTYPE (gvalue)) {
return value->IsNumber();
return value->IsBigInt();
} else if (G_VALUE_HOLDS_ENUM (gvalue)) {
return value->IsNumber();
} else if (G_VALUE_HOLDS_FLAGS (gvalue)) {
Expand Down Expand Up @@ -1364,27 +1377,27 @@ bool V8ToGValue(GValue *gvalue, Local<Value> value, bool mustCopy) {
if (G_VALUE_HOLDS_BOOLEAN (gvalue)) {
g_value_set_boolean (gvalue, Nan::To<bool> (value).ToChecked());
} else if (G_VALUE_HOLDS_CHAR (gvalue)) {
g_value_set_schar (gvalue, Nan::To<int32_t> (value).ToChecked());
g_value_set_schar (gvalue, V8ToInt32(value));
} else if (G_VALUE_HOLDS_UCHAR (gvalue)) {
g_value_set_uchar (gvalue, Nan::To<uint32_t> (value).ToChecked());
g_value_set_uchar (gvalue, V8ToInt32(value));
} else if (G_VALUE_HOLDS_INT (gvalue)) {
g_value_set_int (gvalue, Nan::To<int32_t> (value).ToChecked());
g_value_set_int (gvalue, V8ToInt32(value));
} else if (G_VALUE_HOLDS_UINT (gvalue)) {
g_value_set_uint (gvalue, Nan::To<uint32_t> (value).ToChecked());
g_value_set_uint (gvalue, V8ToInt32(value));
} else if (G_VALUE_HOLDS_LONG (gvalue)) {
g_value_set_long (gvalue, Nan::To<int64_t> (value).ToChecked());
g_value_set_long (gvalue, V8ToInt64(value));
} else if (G_VALUE_HOLDS_ULONG (gvalue)) {
g_value_set_ulong (gvalue, Nan::To<uint32_t> (value).ToChecked());
g_value_set_ulong (gvalue, V8ToInt64(value));
} else if (G_VALUE_HOLDS_INT64 (gvalue)) {
g_value_set_int64 (gvalue, Nan::To<int64_t> (value).ToChecked());
g_value_set_int64 (gvalue, V8ToInt64(value));
} else if (G_VALUE_HOLDS_UINT64 (gvalue)) {
g_value_set_uint64 (gvalue, Nan::To<uint32_t> (value).ToChecked());
g_value_set_uint64 (gvalue, V8ToInt64(value));
} else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
g_value_set_float (gvalue, Nan::To<double> (value).ToChecked());
} else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
g_value_set_double (gvalue, Nan::To<double> (value).ToChecked());
} else if (G_VALUE_HOLDS_GTYPE (gvalue)) {
g_value_set_gtype (gvalue, Nan::To<int64_t> (value).ToChecked());
g_value_set_gtype (gvalue, (GType) V8ToUint64Strict(value));
} else if (G_VALUE_HOLDS_ENUM (gvalue)) {
g_value_set_enum (gvalue, Nan::To<int32_t> (value).ToChecked());
} else if (G_VALUE_HOLDS_FLAGS (gvalue)) {
Expand Down Expand Up @@ -1440,19 +1453,19 @@ Local<Value> GValueToV8(const GValue *gvalue, bool mustCopy) {
} else if (G_VALUE_HOLDS_UINT (gvalue)) {
return New<v8::Uint32>(g_value_get_uint (gvalue));
} else if (G_VALUE_HOLDS_LONG (gvalue)) {
return New<Number>(g_value_get_long (gvalue));
return v8::BigInt::New(Isolate::GetCurrent(), g_value_get_long (gvalue));
} else if (G_VALUE_HOLDS_ULONG (gvalue)) {
return New<Number>(g_value_get_ulong (gvalue));
return v8::BigInt::NewFromUnsigned(Isolate::GetCurrent(), g_value_get_ulong (gvalue));
} else if (G_VALUE_HOLDS_INT64 (gvalue)) {
return New<Number>(g_value_get_int64 (gvalue));
return v8::BigInt::New(Isolate::GetCurrent(), g_value_get_int64 (gvalue));
} else if (G_VALUE_HOLDS_UINT64 (gvalue)) {
return New<Number>(g_value_get_uint64 (gvalue));
return v8::BigInt::NewFromUnsigned(Isolate::GetCurrent(), g_value_get_uint64 (gvalue));
} else if (G_VALUE_HOLDS_FLOAT (gvalue)) {
return New<Number>(g_value_get_float (gvalue));
} else if (G_VALUE_HOLDS_DOUBLE (gvalue)) {
return New<Number>(g_value_get_double (gvalue));
} else if (G_VALUE_HOLDS_GTYPE (gvalue)) {
return New<Number>(g_value_get_gtype (gvalue));
return v8::BigInt::NewFromUnsigned(Isolate::GetCurrent(), g_value_get_gtype(gvalue));
} else if (G_VALUE_HOLDS_ENUM (gvalue)) {
return New<Integer>(g_value_get_enum (gvalue));
} else if (G_VALUE_HOLDS_FLAGS (gvalue)) {
Expand Down
2 changes: 1 addition & 1 deletion tests/object__non-introspected.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('create non-introspected objected', () => {

it('has non-introspected properties', () => {
expect(src.pattern, 0)
expect(src.timestampOffset, 0)
expect(src.timestampOffset, BigInt(0))
expect(src.isLive, false)
})

Expand Down
2 changes: 1 addition & 1 deletion tests/union__fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const tk = new GLib.TokenValue()
tk.vInt = Number.MAX_SAFE_INTEGER
const result = tk.vInt
console.log('Result:', result)
common.assert(result === Number.MAX_SAFE_INTEGER)
common.assert(result === BigInt(Number.MAX_SAFE_INTEGER))
}

/*
Expand Down