mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 06:12:08 +00:00
Compare commits
1 Commits
claude/fix
...
claude/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b4a595ab2 |
@@ -89,7 +89,7 @@ BUN_FFI_IMPORT extern struct NapiEnv Bun__thisFFIModuleNapiEnv;
|
||||
#define TagValueNull (OtherTag)
|
||||
#define NotCellMask (int64_t)(NumberTag | OtherTag)
|
||||
|
||||
#define MAX_INT32 2147483648
|
||||
#define MAX_INT32 2147483647
|
||||
#define MAX_INT52 9007199254740991
|
||||
|
||||
// If all bits in the mask are set, this indicates an integer number,
|
||||
@@ -174,6 +174,7 @@ static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
@@ -260,6 +261,16 @@ static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
|
||||
return val.asInt64;
|
||||
}
|
||||
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) {
|
||||
if (JSVALUE_IS_INT32(val)) {
|
||||
return (uint32_t)JSVALUE_TO_INT32(val);
|
||||
}
|
||||
if (JSVALUE_IS_NUMBER(val)) {
|
||||
return (uint32_t)JSVALUE_TO_DOUBLE(val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = NumberTag | (uint32_t)val;
|
||||
@@ -306,7 +317,7 @@ static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (uint64_t)JSVALUE_TO_INT32(value);
|
||||
return (uint64_t)(uint32_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
@@ -332,11 +343,11 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
|
||||
}
|
||||
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) {
|
||||
if (val < MAX_INT32) {
|
||||
if (val <= MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val < MAX_INT52) {
|
||||
if (val <= MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
|
||||
@@ -2032,7 +2032,8 @@ pub const FFI = struct {
|
||||
/// Types that we can directly pass through as an `int64_t`
|
||||
pub fn needsACastInC(this: ABIType) bool {
|
||||
return switch (this) {
|
||||
.char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => false,
|
||||
.char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t => false,
|
||||
.uint32_t => true,
|
||||
else => true,
|
||||
};
|
||||
}
|
||||
@@ -2143,12 +2144,18 @@ pub const FFI = struct {
|
||||
try writer.writeAll("(bool)");
|
||||
try writer.writeAll("JSVALUE_TO_BOOL(");
|
||||
},
|
||||
.char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t, .uint32_t => {
|
||||
.char, .int8_t, .uint8_t, .int16_t, .uint16_t, .int32_t => {
|
||||
if (self.exact)
|
||||
try writer.print("({s})", .{bun.asByteSlice(@tagName(self.tag))});
|
||||
|
||||
try writer.writeAll("JSVALUE_TO_INT32(");
|
||||
},
|
||||
.uint32_t => {
|
||||
if (self.exact)
|
||||
try writer.writeAll("(uint32_t)");
|
||||
|
||||
try writer.writeAll("JSVALUE_TO_UINT32(");
|
||||
},
|
||||
.i64_fast, .int64_t => {
|
||||
if (self.exact)
|
||||
try writer.writeAll("(int64_t)");
|
||||
@@ -2297,10 +2304,8 @@ pub const FFI = struct {
|
||||
.uint8_t => "uint8_t",
|
||||
.int16_t => "int16_t",
|
||||
.uint16_t => "uint16_t",
|
||||
// see the comment in ffi.ts about why `uint32_t` acts as `int32_t`
|
||||
.int32_t,
|
||||
.uint32_t,
|
||||
=> "int32_t",
|
||||
.int32_t => "int32_t",
|
||||
.uint32_t => "uint32_t",
|
||||
.i64_fast, .int64_t => "int64_t",
|
||||
.u64_fast, .uint64_t => "uint64_t",
|
||||
.double => "double",
|
||||
|
||||
107
test/js/bun/ffi/ffi-int-boundary.test.ts
Normal file
107
test/js/bun/ffi/ffi-int-boundary.test.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { cc } from "bun:ffi";
|
||||
import { afterAll, beforeAll, describe, expect, it } from "bun:test";
|
||||
import { isASAN, tempDirWithFiles } from "harness";
|
||||
import path from "path";
|
||||
|
||||
// TinyCC's setjmp/longjmp error handling conflicts with ASan.
|
||||
describe.skipIf(isASAN)("FFI integer boundary values", () => {
|
||||
const source = /* c */ `
|
||||
#include <stdint.h>
|
||||
|
||||
// 2147483648 is INT32_MAX + 1 (0x80000000)
|
||||
uint32_t returns_uint32_boundary(void) {
|
||||
return 2147483648u;
|
||||
}
|
||||
|
||||
// INT32_MAX = 2147483647
|
||||
uint32_t returns_uint32_max_int32(void) {
|
||||
return 2147483647u;
|
||||
}
|
||||
|
||||
// UINT32_MAX
|
||||
uint32_t returns_uint32_max(void) {
|
||||
return 4294967295u;
|
||||
}
|
||||
|
||||
// Return value that's exactly at the boundary for int64 fast path
|
||||
int64_t returns_int64_boundary_pos(void) {
|
||||
return 2147483648ll;
|
||||
}
|
||||
|
||||
int64_t returns_int64_boundary_neg(void) {
|
||||
return -2147483649ll;
|
||||
}
|
||||
|
||||
// Identity functions for round-tripping
|
||||
uint32_t identity_u32(uint32_t val) {
|
||||
return val;
|
||||
}
|
||||
`;
|
||||
|
||||
let dir: string;
|
||||
|
||||
beforeAll(() => {
|
||||
dir = tempDirWithFiles("bun-ffi-int-boundary", {
|
||||
"boundary.c": source,
|
||||
});
|
||||
});
|
||||
|
||||
describe("uint32 boundary at INT32_MAX+1", () => {
|
||||
let lib: any;
|
||||
|
||||
beforeAll(() => {
|
||||
lib = cc({
|
||||
source: path.join(dir, "boundary.c"),
|
||||
symbols: {
|
||||
returns_uint32_boundary: { args: [], returns: "uint32_t" },
|
||||
returns_uint32_max_int32: { args: [], returns: "uint32_t" },
|
||||
returns_uint32_max: { args: [], returns: "uint32_t" },
|
||||
returns_int64_boundary_pos: { args: [], returns: "i64_fast" },
|
||||
returns_int64_boundary_neg: { args: [], returns: "i64_fast" },
|
||||
identity_u32: { args: ["uint32_t"], returns: "uint32_t" },
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
lib?.close();
|
||||
});
|
||||
|
||||
it("uint32 value 2147483648 should not become negative", () => {
|
||||
// This is the core bug: 2147483648 (0x80000000) was being routed through
|
||||
// the int32 encoding path, causing sign corruption to -2147483648
|
||||
const result = lib.symbols.returns_uint32_boundary();
|
||||
expect(result).toBe(2147483648);
|
||||
expect(result).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("uint32 value 2147483647 (INT32_MAX) should work correctly", () => {
|
||||
const result = lib.symbols.returns_uint32_max_int32();
|
||||
expect(result).toBe(2147483647);
|
||||
});
|
||||
|
||||
it("uint32 value 4294967295 (UINT32_MAX) should work correctly", () => {
|
||||
const result = lib.symbols.returns_uint32_max();
|
||||
expect(result).toBe(4294967295);
|
||||
});
|
||||
|
||||
it("int64_fast value 2147483648 should not become negative", () => {
|
||||
// INT64_TO_JSVALUE was casting 2147483648 to int32_t causing UB/sign corruption
|
||||
const result = lib.symbols.returns_int64_boundary_pos();
|
||||
expect(result).toBe(2147483648);
|
||||
expect(result).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("int64_fast value -2147483649 should be correctly negative", () => {
|
||||
const result = lib.symbols.returns_int64_boundary_neg();
|
||||
expect(result).toBe(-2147483649);
|
||||
expect(result).toBeLessThan(-2147483648);
|
||||
});
|
||||
|
||||
it("round-trip uint32 value 2147483648 through identity function", () => {
|
||||
const result = lib.symbols.identity_u32(2147483648);
|
||||
expect(result).toBe(2147483648);
|
||||
expect(result).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
#define ZIG_REPR_TYPE int64_t
|
||||
|
||||
#ifdef _WIN32
|
||||
#define BUN_FFI_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#define BUN_FFI_IMPORT
|
||||
#endif
|
||||
|
||||
// /* 7.18.1.1 Exact-width integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
@@ -36,7 +41,7 @@ typedef _Bool bool;
|
||||
#define false 0
|
||||
|
||||
#ifndef SRC_JS_NATIVE_API_TYPES_H_
|
||||
typedef struct napi_env__ *napi_env;
|
||||
typedef struct NapiEnv *napi_env;
|
||||
typedef int64_t napi_value;
|
||||
typedef enum {
|
||||
napi_ok,
|
||||
@@ -62,9 +67,9 @@ typedef enum {
|
||||
napi_detachable_arraybuffer_expected,
|
||||
napi_would_deadlock // unused
|
||||
} napi_status;
|
||||
void* NapiHandleScope__open(void* napi_env, bool detached);
|
||||
void NapiHandleScope__close(void* napi_env, void* handleScope);
|
||||
extern struct napi_env__ Bun__thisFFIModuleNapiEnv;
|
||||
BUN_FFI_IMPORT void* NapiHandleScope__open(void* napi_env, bool detached);
|
||||
BUN_FFI_IMPORT void NapiHandleScope__close(void* napi_env, void* handleScope);
|
||||
BUN_FFI_IMPORT extern struct NapiEnv Bun__thisFFIModuleNapiEnv;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -86,7 +91,7 @@ extern struct napi_env__ Bun__thisFFIModuleNapiEnv;
|
||||
#define TagValueNull (OtherTag)
|
||||
#define NotCellMask (int64_t)(NumberTag | OtherTag)
|
||||
|
||||
#define MAX_INT32 2147483648
|
||||
#define MAX_INT32 2147483647
|
||||
#define MAX_INT52 9007199254740991
|
||||
|
||||
// If all bits in the mask are set, this indicates an integer number,
|
||||
@@ -138,7 +143,7 @@ typedef void* JSContext;
|
||||
|
||||
#ifdef IS_CALLBACK
|
||||
void* callback_ctx;
|
||||
ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
|
||||
BUN_FFI_IMPORT ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
|
||||
// We wrap
|
||||
static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) __attribute__((__always_inline__));
|
||||
static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) {
|
||||
@@ -171,6 +176,7 @@ static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
@@ -222,23 +228,26 @@ static void* JSVALUE_TO_PTR(EncodedJSValue val) {
|
||||
return 0;
|
||||
|
||||
if (JSCELL_IS_TYPED_ARRAY(val)) {
|
||||
return JSVALUE_TO_TYPED_ARRAY_VECTOR(val);
|
||||
return JSVALUE_TO_TYPED_ARRAY_VECTOR(val);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_INT32(val)) {
|
||||
return (void*)(uintptr_t)JSVALUE_TO_INT32(val);
|
||||
}
|
||||
|
||||
// Assume the JSValue is a double
|
||||
val.asInt64 -= DoubleEncodeOffset;
|
||||
size_t ptr = (size_t)val.asDouble;
|
||||
return (void*)ptr;
|
||||
return (void*)(uintptr_t)val.asDouble;
|
||||
}
|
||||
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
|
||||
EncodedJSValue val;
|
||||
if (ptr == 0)
|
||||
{
|
||||
val.asInt64 = TagValueNull;
|
||||
return val;
|
||||
if (ptr == 0) {
|
||||
val.asInt64 = TagValueNull;
|
||||
return val;
|
||||
}
|
||||
|
||||
val.asDouble = (double)(size_t)ptr;
|
||||
val.asDouble = (double)(uintptr_t)ptr;
|
||||
val.asInt64 += DoubleEncodeOffset;
|
||||
return val;
|
||||
}
|
||||
@@ -254,6 +263,16 @@ static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
|
||||
return val.asInt64;
|
||||
}
|
||||
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) {
|
||||
if (JSVALUE_IS_INT32(val)) {
|
||||
return (uint32_t)JSVALUE_TO_INT32(val);
|
||||
}
|
||||
if (JSVALUE_IS_NUMBER(val)) {
|
||||
return (uint32_t)JSVALUE_TO_DOUBLE(val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = NumberTag | (uint32_t)val;
|
||||
@@ -300,7 +319,7 @@ static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (uint64_t)JSVALUE_TO_INT32(value);
|
||||
return (uint64_t)(uint32_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
@@ -326,11 +345,11 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
|
||||
}
|
||||
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) {
|
||||
if (val < MAX_INT32) {
|
||||
if (val <= MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val < MAX_INT52) {
|
||||
if (val <= MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
@@ -350,7 +369,7 @@ static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) {
|
||||
}
|
||||
|
||||
#ifndef IS_CALLBACK
|
||||
ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
|
||||
BUN_FFI_IMPORT ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -17,6 +17,11 @@
|
||||
|
||||
#define ZIG_REPR_TYPE int64_t
|
||||
|
||||
#ifdef _WIN32
|
||||
#define BUN_FFI_IMPORT __declspec(dllimport)
|
||||
#else
|
||||
#define BUN_FFI_IMPORT
|
||||
#endif
|
||||
|
||||
// /* 7.18.1.1 Exact-width integer types */
|
||||
typedef unsigned char uint8_t;
|
||||
@@ -36,7 +41,7 @@ typedef _Bool bool;
|
||||
#define false 0
|
||||
|
||||
#ifndef SRC_JS_NATIVE_API_TYPES_H_
|
||||
typedef struct napi_env__ *napi_env;
|
||||
typedef struct NapiEnv *napi_env;
|
||||
typedef int64_t napi_value;
|
||||
typedef enum {
|
||||
napi_ok,
|
||||
@@ -62,9 +67,9 @@ typedef enum {
|
||||
napi_detachable_arraybuffer_expected,
|
||||
napi_would_deadlock // unused
|
||||
} napi_status;
|
||||
void* NapiHandleScope__open(void* napi_env, bool detached);
|
||||
void NapiHandleScope__close(void* napi_env, void* handleScope);
|
||||
extern struct napi_env__ Bun__thisFFIModuleNapiEnv;
|
||||
BUN_FFI_IMPORT void* NapiHandleScope__open(void* napi_env, bool detached);
|
||||
BUN_FFI_IMPORT void NapiHandleScope__close(void* napi_env, void* handleScope);
|
||||
BUN_FFI_IMPORT extern struct NapiEnv Bun__thisFFIModuleNapiEnv;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -86,7 +91,7 @@ extern struct napi_env__ Bun__thisFFIModuleNapiEnv;
|
||||
#define TagValueNull (OtherTag)
|
||||
#define NotCellMask (int64_t)(NumberTag | OtherTag)
|
||||
|
||||
#define MAX_INT32 2147483648
|
||||
#define MAX_INT32 2147483647
|
||||
#define MAX_INT52 9007199254740991
|
||||
|
||||
// If all bits in the mask are set, this indicates an integer number,
|
||||
@@ -138,7 +143,7 @@ typedef void* JSContext;
|
||||
|
||||
#ifdef IS_CALLBACK
|
||||
void* callback_ctx;
|
||||
ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
|
||||
BUN_FFI_IMPORT ZIG_REPR_TYPE FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args);
|
||||
// We wrap
|
||||
static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) __attribute__((__always_inline__));
|
||||
static EncodedJSValue _FFI_Callback_call(void* ctx, size_t argCount, ZIG_REPR_TYPE* args) {
|
||||
@@ -171,6 +176,7 @@ static EncodedJSValue PTR_TO_JSVALUE(void* ptr) __attribute__((__always_inline__
|
||||
|
||||
static void* JSVALUE_TO_PTR(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static int32_t JSVALUE_TO_INT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static float JSVALUE_TO_FLOAT(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static double JSVALUE_TO_DOUBLE(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
static bool JSVALUE_TO_BOOL(EncodedJSValue val) __attribute__((__always_inline__));
|
||||
@@ -222,23 +228,26 @@ static void* JSVALUE_TO_PTR(EncodedJSValue val) {
|
||||
return 0;
|
||||
|
||||
if (JSCELL_IS_TYPED_ARRAY(val)) {
|
||||
return JSVALUE_TO_TYPED_ARRAY_VECTOR(val);
|
||||
return JSVALUE_TO_TYPED_ARRAY_VECTOR(val);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_INT32(val)) {
|
||||
return (void*)(uintptr_t)JSVALUE_TO_INT32(val);
|
||||
}
|
||||
|
||||
// Assume the JSValue is a double
|
||||
val.asInt64 -= DoubleEncodeOffset;
|
||||
size_t ptr = (size_t)val.asDouble;
|
||||
return (void*)ptr;
|
||||
return (void*)(uintptr_t)val.asDouble;
|
||||
}
|
||||
|
||||
static EncodedJSValue PTR_TO_JSVALUE(void* ptr) {
|
||||
EncodedJSValue val;
|
||||
if (ptr == 0)
|
||||
{
|
||||
val.asInt64 = TagValueNull;
|
||||
return val;
|
||||
if (ptr == 0) {
|
||||
val.asInt64 = TagValueNull;
|
||||
return val;
|
||||
}
|
||||
|
||||
val.asDouble = (double)(size_t)ptr;
|
||||
val.asDouble = (double)(uintptr_t)ptr;
|
||||
val.asInt64 += DoubleEncodeOffset;
|
||||
return val;
|
||||
}
|
||||
@@ -254,6 +263,16 @@ static int32_t JSVALUE_TO_INT32(EncodedJSValue val) {
|
||||
return val.asInt64;
|
||||
}
|
||||
|
||||
static uint32_t JSVALUE_TO_UINT32(EncodedJSValue val) {
|
||||
if (JSVALUE_IS_INT32(val)) {
|
||||
return (uint32_t)JSVALUE_TO_INT32(val);
|
||||
}
|
||||
if (JSVALUE_IS_NUMBER(val)) {
|
||||
return (uint32_t)JSVALUE_TO_DOUBLE(val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static EncodedJSValue INT32_TO_JSVALUE(int32_t val) {
|
||||
EncodedJSValue res;
|
||||
res.asInt64 = NumberTag | (uint32_t)val;
|
||||
@@ -300,7 +319,7 @@ static bool JSVALUE_TO_BOOL(EncodedJSValue val) {
|
||||
|
||||
static uint64_t JSVALUE_TO_UINT64(EncodedJSValue value) {
|
||||
if (JSVALUE_IS_INT32(value)) {
|
||||
return (uint64_t)JSVALUE_TO_INT32(value);
|
||||
return (uint64_t)(uint32_t)JSVALUE_TO_INT32(value);
|
||||
}
|
||||
|
||||
if (JSVALUE_IS_NUMBER(value)) {
|
||||
@@ -326,11 +345,11 @@ static int64_t JSVALUE_TO_INT64(EncodedJSValue value) {
|
||||
}
|
||||
|
||||
static EncodedJSValue UINT64_TO_JSVALUE(void* jsGlobalObject, uint64_t val) {
|
||||
if (val < MAX_INT32) {
|
||||
if (val <= MAX_INT32) {
|
||||
return INT32_TO_JSVALUE((int32_t)val);
|
||||
}
|
||||
|
||||
if (val < MAX_INT52) {
|
||||
if (val <= MAX_INT52) {
|
||||
return DOUBLE_TO_JSVALUE((double)val);
|
||||
}
|
||||
|
||||
@@ -350,7 +369,7 @@ static EncodedJSValue INT64_TO_JSVALUE(void* jsGlobalObject, int64_t val) {
|
||||
}
|
||||
|
||||
#ifndef IS_CALLBACK
|
||||
ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
|
||||
BUN_FFI_IMPORT ZIG_REPR_TYPE JSFunctionCall(void* jsGlobalObject, void* callFrame);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user