diff --git a/context.go b/context.go index bb13adb..3bca08f 100644 --- a/context.go +++ b/context.go @@ -338,6 +338,24 @@ func (ctx *Context) Uint32(v uint32) *Value { return ctx.NewUint32(v) } +// NewUint64 returns a JavaScript Number from a uint64. +// Note: Precision loss occurs for values exceeding 2^53 - 1. Use NewBigUint64 +// for full 64-bit precision. +func (ctx *Context) NewUint64(v uint64) *Value { + if !ctx.hasValidRef() { + return nil + } + return &Value{ctx: ctx, ref: C.JS_NewUint64(ctx.ref, C.uint64_t(v))} +} + +// Uint64 returns a JavaScript Number from a uint64. +// Note: Precision loss occurs for values exceeding 2^53 - 1. Use NewBigUint64 +// for full 64-bit precision. +// Deprecated: Use NewUint64() instead. +func (ctx *Context) Uint64(v uint64) *Value { + return ctx.NewUint64(v) +} + // NewBigInt64 returns a int64 value with given uint64. func (ctx *Context) NewBigInt64(v int64) *Value { return &Value{ctx: ctx, ref: C.JS_NewBigInt64(ctx.ref, C.int64_t(v))} diff --git a/context_deprecated_test.go b/context_deprecated_test.go index dae2c16..be971bc 100644 --- a/context_deprecated_test.go +++ b/context_deprecated_test.go @@ -52,33 +52,38 @@ func TestDeprecatedContextAPIs(t *testing.T) { defer val7.Free() require.True(t, val7.IsNumber()) - val8 := ctx.BigInt64(9223372036854775807) + val8 := ctx.Uint64(uint64(1) << 32) defer val8.Free() - require.True(t, val8.IsBigInt()) + require.True(t, val8.IsNumber()) + require.Equal(t, float64(uint64(1)<<32), val8.ToFloat64()) - val9 := ctx.BigUint64(18446744073709551615) + val9 := ctx.BigInt64(9223372036854775807) defer val9.Free() require.True(t, val9.IsBigInt()) - val10 := ctx.Float64(3.14159) + val10 := ctx.BigUint64(18446744073709551615) defer val10.Free() - require.True(t, val10.IsNumber()) + require.True(t, val10.IsBigInt()) - val11 := ctx.String("test") + val11 := ctx.Float64(3.14159) defer val11.Free() - require.True(t, val11.IsString()) + require.True(t, val11.IsNumber()) - val12 := ctx.Object() + val12 := ctx.String("test") defer val12.Free() - require.True(t, val12.IsObject()) + require.True(t, val12.IsString()) - val13 := ctx.ArrayBuffer([]byte{1, 2, 3}) + val13 := ctx.Object() defer val13.Free() - require.True(t, val13.IsByteArray()) + require.True(t, val13.IsObject()) - val14 := ctx.Error(errors.New("test error")) + val14 := ctx.ArrayBuffer([]byte{1, 2, 3}) defer val14.Free() - require.True(t, val14.IsError()) + require.True(t, val14.IsByteArray()) + + val15 := ctx.Error(errors.New("test error")) + defer val15.Free() + require.True(t, val15.IsError()) }) t.Run("DeprecatedTypedArrays", func(t *testing.T) { diff --git a/context_test.go b/context_test.go index 7e529d2..d357ad9 100644 --- a/context_test.go +++ b/context_test.go @@ -52,6 +52,7 @@ func TestContextBasics(t *testing.T) { {"Int32", func() *Value { return ctx.NewInt32(-42) }, func(v *Value) bool { return v.IsNumber() }}, {"Int64", func() *Value { return ctx.NewInt64(1234567890) }, func(v *Value) bool { return v.IsNumber() }}, {"Uint32", func() *Value { return ctx.NewUint32(42) }, func(v *Value) bool { return v.IsNumber() }}, + {"Uint64", func() *Value { return ctx.NewUint64(uint64(1) << 32) }, func(v *Value) bool { return v.IsNumber() && v.ToFloat64() == float64(uint64(1)<<32) }}, {"BigInt64", func() *Value { return ctx.NewBigInt64(9223372036854775807) }, func(v *Value) bool { return v.IsBigInt() }}, {"BigUint64", func() *Value { return ctx.NewBigUint64(18446744073709551615) }, func(v *Value) bool { return v.IsBigInt() }}, {"Float64", func() *Value { return ctx.NewFloat64(3.14159) }, func(v *Value) bool { return v.IsNumber() }}, @@ -410,6 +411,7 @@ func TestContextLibcStage4HelpersNilAndClosedGuards(t *testing.T) { var nilCtx *Context require.Nil(t, nilCtx.NewDate(0)) + require.Nil(t, nilCtx.NewUint64(1)) require.Nil(t, nilCtx.NewSymbol("x")) require.Nil(t, nilCtx.NewGlobalSymbol("x")) require.False(t, nilCtx.SetImportMeta(nil, false, false)) @@ -429,6 +431,7 @@ func TestContextLibcStage4HelpersNilAndClosedGuards(t *testing.T) { ctx.Close() require.Nil(t, ctx.NewDate(0)) + require.Nil(t, ctx.NewUint64(1)) require.Nil(t, ctx.NewSymbol("x")) require.Nil(t, ctx.NewGlobalSymbol("x")) require.False(t, ctx.SetImportMeta(moduleFunc, false, false)) @@ -2084,33 +2087,38 @@ func TestDeprecatedAPIs(t *testing.T) { defer val7.Free() require.True(t, val7.IsNumber()) - val8 := ctx.BigInt64(9223372036854775807) + val8 := ctx.Uint64(uint64(1) << 32) defer val8.Free() - require.True(t, val8.IsBigInt()) + require.True(t, val8.IsNumber()) + require.Equal(t, float64(uint64(1)<<32), val8.ToFloat64()) - val9 := ctx.BigUint64(18446744073709551615) + val9 := ctx.BigInt64(9223372036854775807) defer val9.Free() require.True(t, val9.IsBigInt()) - val10 := ctx.Float64(3.14159) + val10 := ctx.BigUint64(18446744073709551615) defer val10.Free() - require.True(t, val10.IsNumber()) + require.True(t, val10.IsBigInt()) - val11 := ctx.String("test") + val11 := ctx.Float64(3.14159) defer val11.Free() - require.True(t, val11.IsString()) + require.True(t, val11.IsNumber()) - val12 := ctx.Object() + val12 := ctx.String("test") defer val12.Free() - require.True(t, val12.IsObject()) + require.True(t, val12.IsString()) - val13 := ctx.ArrayBuffer([]byte{1, 2, 3}) + val13 := ctx.Object() defer val13.Free() - require.True(t, val13.IsByteArray()) + require.True(t, val13.IsObject()) - val14 := ctx.Error(errors.New("test error")) + val14 := ctx.ArrayBuffer([]byte{1, 2, 3}) defer val14.Free() - require.True(t, val14.IsError()) + require.True(t, val14.IsByteArray()) + + val15 := ctx.Error(errors.New("test error")) + defer val15.Free() + require.True(t, val15.IsError()) }) t.Run("DeprecatedTypedArrays", func(t *testing.T) { diff --git a/runtime.go b/runtime.go index 422bde9..fa8cdfb 100644 --- a/runtime.go +++ b/runtime.go @@ -137,6 +137,32 @@ type MemoryUsage struct { BinaryObjectSize int64 } +// DumpFlag* constants mirror the quickjs-ng runtime dump flags and can be +// combined with bitwise OR for Runtime.SetDumpFlags. +const ( + DumpFlagBytecodeFinal uint64 = C.JS_DUMP_BYTECODE_FINAL + DumpFlagBytecodePass2 uint64 = C.JS_DUMP_BYTECODE_PASS2 + DumpFlagBytecodePass1 uint64 = C.JS_DUMP_BYTECODE_PASS1 + DumpFlagBytecodeHex uint64 = C.JS_DUMP_BYTECODE_HEX + DumpFlagBytecodePC2Line uint64 = C.JS_DUMP_BYTECODE_PC2LINE + DumpFlagBytecodeStack uint64 = C.JS_DUMP_BYTECODE_STACK + DumpFlagBytecodeStep uint64 = C.JS_DUMP_BYTECODE_STEP + DumpFlagReadObject uint64 = C.JS_DUMP_READ_OBJECT + DumpFlagFree uint64 = C.JS_DUMP_FREE + DumpFlagGC uint64 = C.JS_DUMP_GC + DumpFlagGCFree uint64 = C.JS_DUMP_GC_FREE + DumpFlagModuleResolve uint64 = C.JS_DUMP_MODULE_RESOLVE + DumpFlagPromise uint64 = C.JS_DUMP_PROMISE + DumpFlagLeaks uint64 = C.JS_DUMP_LEAKS + DumpFlagAtomLeaks uint64 = C.JS_DUMP_ATOM_LEAKS + DumpFlagMem uint64 = C.JS_DUMP_MEM + DumpFlagObjects uint64 = C.JS_DUMP_OBJECTS + DumpFlagAtoms uint64 = C.JS_DUMP_ATOMS + DumpFlagShapes uint64 = C.JS_DUMP_SHAPES + // DumpFlagAbortOnLeaks aborts on atom/object/string leaks and is intended for testing. + DumpFlagAbortOnLeaks uint64 = C.JS_ABORT_ON_LEAKS +) + // IntrinsicSet controls which QuickJS intrinsics are injected into a raw context. type IntrinsicSet struct { BaseObjects bool diff --git a/runtime_test.go b/runtime_test.go index ec5086d..b14cff6 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -185,6 +185,19 @@ func TestRuntimeDiagnosticsAndRawContext(t *testing.T) { require.True(t, selected.Eval) } +func TestRuntimeDumpFlagConstants(t *testing.T) { + rt := NewRuntime() + defer rt.Close() + + flags := DumpFlagBytecodeFinal | DumpFlagModuleResolve | DumpFlagPromise + rt.SetDumpFlags(flags) + require.EqualValues(t, flags, rt.DumpFlags()) + + require.NotZero(t, DumpFlagAbortOnLeaks) + require.EqualValues(t, DumpFlagLeaks, DumpFlagAbortOnLeaks&DumpFlagLeaks) + require.EqualValues(t, DumpFlagAtomLeaks, DumpFlagAbortOnLeaks&DumpFlagAtomLeaks) +} + func TestRuntimeStage3CoveragePaths(t *testing.T) { useStableOwnerHooksForLegacySubtests(t)