Hello,
I needed QuickJS for a personal project and patched a few files so that they
compile with Visual Studio (2017 or later). There is little chance for most of
the changes to ever land upstream, but it could be a starting point for anyone
interested in porting more of it, so I'm leaving it here.
Attached is a patch; it can also be read on GitHub:
https://github.com/horhof/quickjs/compare/master...samhocevar:task/msvc-support
The files that now build (in C mode) are:
cutils.c cutils.h
libbf.c
libregexp.c
libunicode.c
quickjs.c quickjs.h
Note that quickjs.h also builds properly when included from C++ code using
extern "C", which is slightly more restrictive.
I did not want to port all the atomic / pthread stuff so I just disabled
CONFIG_ATOMICS.
This was enough for me to have QuickJS embedded in a C++ application that
builds and runs from Visual Studio using MSVC.
Cheers,
--
Sam.
diff --git a/cutils.c b/cutils.c
index 64a32d3..2c2e5bc 100644
--- a/cutils.c
+++ b/cutils.c
@@ -166,8 +166,12 @@ int dbuf_putstr(DynBuf *s, const char *str)
return dbuf_put(s, (const uint8_t *)str, strlen(str));
}
+#if defined(_MSC_VER)
+int dbuf_printf(DynBuf *s, const char *fmt, ...)
+#else
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...)
+#endif
{
va_list ap;
char buf[128];
@@ -257,6 +261,22 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const
uint8_t **pp)
*pp = p;
return c;
}
+#if defined(_MSC_VER)
+ else if (c < 0xc0)
+ return -1;
+ else if (c < 0xe0)
+ l = 1;
+ else if (c < 0xf0)
+ l = 2;
+ else if (c < 0xf8)
+ l = 3;
+ else if (c < 0xfc)
+ l = 4;
+ else if (c < 0xfe)
+ l = 5;
+ else
+ return -1;
+#else
switch(c) {
case 0xc0 ... 0xdf:
l = 1;
@@ -276,6 +296,7 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const
uint8_t **pp)
default:
return -1;
}
+#endif
/* check that we have enough characters */
if (l > (max_len - 1))
return -1;
diff --git a/cutils.h b/cutils.h
index fdbf44a..b09e61a 100644
--- a/cutils.h
+++ b/cutils.h
@@ -27,14 +27,24 @@
#include <stdlib.h>
#include <inttypes.h>
+#if defined(_MSC_VER)
+#include <intrin.h>
+#endif
/* set if CPU is big endian */
#undef WORDS_BIGENDIAN
+#if defined(_MSC_VER)
+#define likely(x) (x)
+#define unlikely(x) (x)
+#define force_inline inline
+#define no_inline
+#else
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define force_inline inline __attribute__((always_inline))
#define no_inline __attribute__((noinline))
+#endif
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
@@ -113,27 +123,57 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
+#if defined(_MSC_VER)
+ unsigned long ret = 0;
+ _BitScanReverse(&ret, a);
+ return (int)ret;
+#else
return __builtin_clz(a);
+#endif
}
/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
+#if defined(_MSC_VER)
+ unsigned long ret = 0;
+ _BitScanReverse64(&ret, a);
+ return (int)ret;
+#else
return __builtin_clzll(a);
+#endif
}
/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
+#if defined(_MSC_VER)
+ unsigned long ret = 0;
+ _BitScanForward(&ret, a);
+ return (int)ret;
+#else
return __builtin_ctz(a);
+#endif
}
/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
+#if defined(_MSC_VER)
+ unsigned long ret = 0;
+ _BitScanForward64(&ret, a);
+ return (int)ret;
+#else
return __builtin_ctzll(a);
+#endif
}
+#if defined(_MSC_VER)
+#pragma pack(push)
+#pragma pack(1)
+#define __attribute__(x) /* */
+#endif
+
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
@@ -146,6 +186,11 @@ struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
+#if defined(_MSC_VER)
+#pragma pack(pop)
+#undef __attribute__
+#endif
+
static inline uint64_t get_u64(const uint8_t *tab)
{
return ((const struct packed_u64 *)tab)->v;
@@ -261,8 +306,12 @@ static inline int dbuf_put_u64(DynBuf *s, uint64_t val)
{
return dbuf_put(s, (uint8_t *)&val, 8);
}
+#if defined(_MSC_VER)
+int dbuf_printf(DynBuf *s, const char *fmt, ...);
+#else
int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s,
const char *fmt, ...);
+#endif
void dbuf_free(DynBuf *s);
static inline BOOL dbuf_error(DynBuf *s) {
return s->error;
diff --git a/libbf.c b/libbf.c
index cbabf95..70598e8 100644
--- a/libbf.c
+++ b/libbf.c
@@ -41,7 +41,11 @@
#define USE_FFT_MUL
//#define inline __attribute__((always_inline))
+#if defined(_MSC_VER)
+#define unused /* */
+#else
#define unused __attribute__((unused))
+#endif
#ifdef __AVX2__
#define FFT_MUL_THRESHOLD 100 /* in limbs of the smallest factor */
diff --git a/libregexp.c b/libregexp.c
index ad1e6bf..c691aad 100644
--- a/libregexp.c
+++ b/libregexp.c
@@ -425,7 +425,11 @@ static void re_emit_op_u16(REParseState *s, int op,
uint32_t val)
dbuf_put_u16(&s->byte_code, val);
}
+#if defined(_MSC_VER)
+static int re_parse_error(REParseState *s, const char *fmt, ...)
+#else
static int __attribute__((format(printf, 2, 3))) re_parse_error(REParseState
*s, const char *fmt, ...)
+#endif
{
va_list ap;
va_start(ap, fmt);
@@ -557,7 +561,11 @@ int lre_parse_escape(const uint8_t **pp, int allow_utf16)
}
}
break;
+#if defined(_MSC_VER)
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case
'7':
+#else
case '0' ... '7':
+#endif
c -= '0';
if (allow_utf16 == 2) {
/* only accept \0 not followed by digit */
@@ -1383,7 +1391,11 @@ static int re_parse_term(REParseState *s, BOOL
is_backward_dir)
}
}
goto normal_char;
+#if defined(_MSC_VER)
+ case '1': case '2': case '3': case '4': case '5': case '6': case '7':
case '8': case '9':
+#else
case '1' ... '9':
+#endif
{
const uint8_t *q = ++p;
diff --git a/libunicode.c b/libunicode.c
index 6fe6945..29e4c10 100644
--- a/libunicode.c
+++ b/libunicode.c
@@ -271,7 +271,11 @@ BOOL lre_is_case_ignorable(uint32_t c)
/* character range */
+#if defined(_MSC_VER)
+static void cr_dump(CharRange *cr)
+#else
static __attribute__((unused)) void cr_dump(CharRange *cr)
+#endif
{
int i;
for(i = 0; i < cr->len; i++)
@@ -527,7 +531,17 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c,
} else {
d = unicode_decomp_data + unicode_decomp_table2[idx];
switch(type) {
+#if defined(_MSC_VER)
+ case DECOMP_TYPE_L1:
+ case DECOMP_TYPE_L2:
+ case DECOMP_TYPE_L3:
+ case DECOMP_TYPE_L4:
+ case DECOMP_TYPE_L5:
+ case DECOMP_TYPE_L6:
+ case DECOMP_TYPE_L7:
+#else
case DECOMP_TYPE_L1 ... DECOMP_TYPE_L7:
+#endif
l = type - DECOMP_TYPE_L1 + 1;
d += (c - code) * l * 2;
for(i = 0; i < l; i++) {
@@ -535,7 +549,12 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c,
return 0;
}
return l;
+#if defined(_MSC_VER)
+ case DECOMP_TYPE_LL1:
+ case DECOMP_TYPE_LL2:
+#else
case DECOMP_TYPE_LL1 ... DECOMP_TYPE_LL2:
+#endif
{
uint32_t k, p;
l = type - DECOMP_TYPE_LL1 + 1;
@@ -551,7 +570,15 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c,
}
}
return l;
+#if defined(_MSC_VER)
+ case DECOMP_TYPE_S1:
+ case DECOMP_TYPE_S2:
+ case DECOMP_TYPE_S3:
+ case DECOMP_TYPE_S4:
+ case DECOMP_TYPE_S5:
+#else
case DECOMP_TYPE_S1 ... DECOMP_TYPE_S5:
+#endif
l = type - DECOMP_TYPE_S1 + 1;
d += (c - code) * l;
for(i = 0; i < l; i++) {
@@ -582,7 +609,18 @@ static int unicode_decomp_entry(uint32_t *res, uint32_t c,
case DECOMP_TYPE_B18:
l = 18;
goto decomp_type_b;
+#if defined(_MSC_VER)
+ case DECOMP_TYPE_B1:
+ case DECOMP_TYPE_B2:
+ case DECOMP_TYPE_B3:
+ case DECOMP_TYPE_B4:
+ case DECOMP_TYPE_B5:
+ case DECOMP_TYPE_B6:
+ case DECOMP_TYPE_B7:
+ case DECOMP_TYPE_B8:
+#else
case DECOMP_TYPE_B1 ... DECOMP_TYPE_B8:
+#endif
l = type - DECOMP_TYPE_B1 + 1;
decomp_type_b:
{
diff --git a/quickjs-libc.c b/quickjs-libc.c
index 37da67b..4b2fe47 100644
--- a/quickjs-libc.c
+++ b/quickjs-libc.c
@@ -28,18 +28,26 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
+#if !defined(_WIN32)
#include <unistd.h>
+#endif
#include <errno.h>
#include <fcntl.h>
+#if !defined(_WIN32)
#include <sys/time.h>
+#endif
#include <time.h>
#include <signal.h>
#include <limits.h>
#include <sys/stat.h>
+#if !defined(_WIN32)
#include <dirent.h>
+#endif
#if defined(_WIN32)
#include <windows.h>
#include <conio.h>
+typedef int64_t ssize_t;
+#define PATH_MAX MAX_PATH
#else
#include <dlfcn.h>
#include <termios.h>
@@ -2067,9 +2075,15 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst
this_val,
JS_DefinePropertyValueStr(ctx, obj, "size",
JS_NewInt64(ctx, st.st_size),
JS_PROP_C_W_E);
+#if defined(_WIN32)
+ JS_DefinePropertyValueStr(ctx, obj, "blocks",
+ JS_NewInt64(ctx, 0),
+ JS_PROP_C_W_E);
+#else
JS_DefinePropertyValueStr(ctx, obj, "blocks",
JS_NewInt64(ctx, st.st_blocks),
JS_PROP_C_W_E);
+#endif
#if defined(__APPLE__)
JS_DefinePropertyValueStr(ctx, obj, "atime",
JS_NewInt64(ctx,
timespec_to_ms(&st.st_atimespec)),
@@ -2080,6 +2094,16 @@ static JSValue js_os_stat(JSContext *ctx, JSValueConst
this_val,
JS_DefinePropertyValueStr(ctx, obj, "ctime",
JS_NewInt64(ctx,
timespec_to_ms(&st.st_ctimespec)),
JS_PROP_C_W_E);
+#elif defined(_WIN32)
+ JS_DefinePropertyValueStr(ctx, obj, "atime",
+ JS_NewInt64(ctx,
timespec_to_ms(&st.st_atime)),
+ JS_PROP_C_W_E);
+ JS_DefinePropertyValueStr(ctx, obj, "mtime",
+ JS_NewInt64(ctx,
timespec_to_ms(&st.st_mtime)),
+ JS_PROP_C_W_E);
+ JS_DefinePropertyValueStr(ctx, obj, "ctime",
+ JS_NewInt64(ctx,
timespec_to_ms(&st.st_ctime)),
+ JS_PROP_C_W_E);
#else
JS_DefinePropertyValueStr(ctx, obj, "atime",
JS_NewInt64(ctx,
timespec_to_ms(&st.st_atim)),
@@ -2143,6 +2167,9 @@ static JSValue js_os_readlink(JSContext *ctx,
JSValueConst this_val,
static JSValue js_os_readdir(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv)
{
+#if defined(_WIN32)
+ return JS_EXCEPTION; /* FIXME: use FindFirstFile() etc. */
+#else
const char *path;
DIR *f;
struct dirent *d;
@@ -2180,6 +2207,7 @@ static JSValue js_os_readdir(JSContext *ctx, JSValueConst
this_val,
closedir(f);
done:
return make_obj_error(ctx, obj, err);
+#endif
}
static void ms_to_timeval(struct timeval *tv, uint64_t v)
@@ -2263,15 +2291,21 @@ static const JSCFunctionListEntry js_os_funcs[] = {
JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ),
/* st_mode constants */
OS_FLAG(S_IFMT),
+#if !defined(_WIN32)
OS_FLAG(S_IFIFO),
+#endif
OS_FLAG(S_IFCHR),
OS_FLAG(S_IFDIR),
+#if !defined(_WIN32)
OS_FLAG(S_IFBLK),
+#endif
OS_FLAG(S_IFREG),
+#if !defined(_WIN32)
OS_FLAG(S_IFSOCK),
OS_FLAG(S_IFLNK),
OS_FLAG(S_ISGID),
OS_FLAG(S_ISUID),
+#endif
JS_CFUNC_DEF("symlink", 2, js_os_symlink ),
JS_CFUNC_DEF("readlink", 1, js_os_readlink ),
JS_CFUNC_DEF("readdir", 1, js_os_readdir ),
diff --git a/quickjs.c b/quickjs.c
index d5c1c83..6156453 100644
--- a/quickjs.c
+++ b/quickjs.c
@@ -28,7 +28,9 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
+#if !defined(_WIN32)
#include <sys/time.h>
+#endif
#include <time.h>
#include <fenv.h>
#include <math.h>
@@ -50,6 +52,8 @@
#define SHORT_OPCODES 1
#if defined(EMSCRIPTEN)
#define DIRECT_DISPATCH 0
+#elif defined(_MSC_VER)
+#define DIRECT_DISPATCH 0
#else
#define DIRECT_DISPATCH 1
#endif
@@ -67,7 +71,7 @@
/* define to include Atomics.* operations which depend on the OS
threads */
-#if !defined(EMSCRIPTEN)
+#if !defined(EMSCRIPTEN) && !defined(_MSC_VER)
#define CONFIG_ATOMICS
#endif
@@ -102,8 +106,10 @@
//#define FORCE_GC_AT_MALLOC
#ifdef CONFIG_ATOMICS
+#if !defined(_WIN32)
#include <pthread.h>
#include <stdatomic.h>
+#endif
#include <errno.h>
#endif
@@ -193,7 +199,14 @@ typedef enum JSErrorEnum {
#define JS_STACK_SIZE_MAX 65536
#define JS_STRING_LEN_MAX ((1 << 30) - 1)
+#if defined(_WIN32)
+#define __exception /* */
+#define unused /* */
+typedef int64_t ssize_t;
+#else
#define __exception __attribute__((warn_unused_result))
+#define unused __attribute__((unused))
+#endif
typedef struct JSShape JSShape;
typedef struct JSString JSString;
@@ -688,9 +701,10 @@ typedef struct JSShapeProperty {
} JSShapeProperty;
struct JSShape {
- uint32_t prop_hash_end[0]; /* hash table of size hash_mask + 1
- before the start of the structure. */
- JSRefCountHeader header; /* must come first, 32-bit */
+ union {
+ JSRefCountHeader header; /* must come first, 32-bit */
+ uint32_t prop_hash_end[1];
+ };
JSGCHeader gc_header; /* must come after JSRefCountHeader, 8-bit */
/* true if the shape is inserted in the shape hash table. If not,
JSShape.hash is not valid */
@@ -853,19 +867,23 @@ static __exception int JS_ToArrayLengthFree(JSContext
*ctx, uint32_t *plen,
JSValue val);
static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
JSValueConst val, int flags, int scope_idx);
+#if defined(_WIN32)
+JSValue JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext
*ctx, const char *fmt, ...);
-static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt);
-static __attribute__((unused)) void JS_DumpString(JSRuntime *rt,
- const JSString *p);
-static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt);
-static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p);
-static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val);
-static __attribute__((unused)) void JS_DumpValue(JSContext *ctx, JSValueConst
val);
-static __attribute__((unused)) void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val);
-static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt);
+#endif
+static unused void JS_DumpAtoms(JSRuntime *rt);
+static unused void JS_DumpString(JSRuntime *rt,
+ const JSString *p);
+static unused void JS_DumpObjectHeader(JSRuntime *rt);
+static unused void JS_DumpObject(JSRuntime *rt, JSObject *p);
+static unused void JS_DumpValueShort(JSRuntime *rt,
+ JSValueConst val);
+static unused void JS_DumpValue(JSContext *ctx, JSValueConst val);
+static unused void JS_PrintValue(JSContext *ctx,
+ const char *str,
+ JSValueConst val);
+static unused void JS_DumpShapes(JSRuntime *rt);
static JSValue js_function_apply(JSContext *ctx, JSValueConst this_val,
int argc, JSValueConst *argv, int magic);
static void js_array_finalizer(JSRuntime *rt, JSValue val);
@@ -1784,7 +1802,11 @@ static inline BOOL js_check_stack_overflow(JSContext
*ctx, size_t alloca_size)
/* Note: OS and CPU dependent */
static inline uint8_t *js_get_stack_pointer(void)
{
+#if defined(_MSC_VER)
+ return _AddressOfReturnAddress();
+#else
return __builtin_frame_address(0);
+#endif
}
static inline BOOL js_check_stack_overflow(JSContext *ctx, size_t alloca_size)
@@ -2133,8 +2155,7 @@ static uint32_t hash_string(const JSString *str, uint32_t
h)
return h;
}
-static __attribute__((unused)) void JS_DumpString(JSRuntime *rt,
- const JSString *p)
+static unused void JS_DumpString(JSRuntime *rt, const JSString *p)
{
int i, c, sep;
@@ -2165,7 +2186,7 @@ static __attribute__((unused)) void
JS_DumpString(JSRuntime *rt,
putchar(sep);
}
-static __attribute__((unused)) void JS_DumpAtoms(JSRuntime *rt)
+static unused void JS_DumpAtoms(JSRuntime *rt)
{
JSAtomStruct *p;
int h, i;
@@ -2918,7 +2939,7 @@ static BOOL JS_AtomSymbolHasDescription(JSContext *ctx,
JSAtom v)
!(p->len == 0 && p->is_wide_char != 0));
}
-static __attribute__((unused)) void print_atom(JSContext *ctx, JSAtom atom)
+static unused void print_atom(JSContext *ctx, JSAtom atom)
{
char buf[ATOM_GET_STR_BUF_SIZE];
const char *p;
@@ -4234,7 +4255,7 @@ static JSShape *find_hashed_shape_prop(JSRuntime *rt,
JSShape *sh,
return NULL;
}
-static __attribute__((unused)) void JS_DumpShape(JSRuntime *rt, int i, JSShape
*sh)
+static unused void JS_DumpShape(JSRuntime *rt, int i, JSShape *sh)
{
char atom_buf[ATOM_GET_STR_BUF_SIZE];
int j;
@@ -4250,7 +4271,7 @@ static __attribute__((unused)) void
JS_DumpShape(JSRuntime *rt, int i, JSShape *
printf("\n");
}
-static __attribute__((unused)) void JS_DumpShapes(JSRuntime *rt)
+static unused void JS_DumpShapes(JSRuntime *rt)
{
int i;
JSShape *sh;
@@ -4332,7 +4353,23 @@ static JSValue JS_NewObjectFromShape(JSContext *ctx,
JSShape *sh, JSClassID clas
p->prop[0].u.value = JS_UNDEFINED;
break;
case JS_CLASS_ARGUMENTS:
+#if defined(_MSC_VER)
+ case JS_CLASS_UINT8C_ARRAY:
+ case JS_CLASS_INT8_ARRAY:
+ case JS_CLASS_UINT8_ARRAY:
+ case JS_CLASS_INT16_ARRAY:
+ case JS_CLASS_UINT16_ARRAY:
+ case JS_CLASS_INT32_ARRAY:
+ case JS_CLASS_UINT32_ARRAY:
+#ifdef CONFIG_BIGNUM
+ case JS_CLASS_BIG_INT64_ARRAY:
+ case JS_CLASS_BIG_UINT64_ARRAY:
+#endif
+ case JS_CLASS_FLOAT32_ARRAY:
+ case JS_CLASS_FLOAT64_ARRAY:
+#else
case JS_CLASS_UINT8C_ARRAY ... JS_CLASS_FLOAT64_ARRAY:
+#endif
p->is_exotic = 1;
p->fast_array = 1;
p->u.array.u.ptr = NULL;
@@ -6118,7 +6155,11 @@ static JSValue JS_ThrowError(JSContext *ctx, JSErrorEnum
error_num,
return ret;
}
+#if defined(_MSC_VER)
+JSValue JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...)
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowSyntaxError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
JSValue val;
va_list ap;
@@ -6129,7 +6170,11 @@ JSValue __attribute__((format(printf, 2, 3)))
JS_ThrowSyntaxError(JSContext *ctx
return val;
}
+#if defined(_MSC_VER)
+JSValue JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...)
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowTypeError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
JSValue val;
va_list ap;
@@ -6140,7 +6185,11 @@ JSValue __attribute__((format(printf, 2, 3)))
JS_ThrowTypeError(JSContext *ctx,
return val;
}
+#if defined(_MSC_VER)
+static int JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char
*fmt, ...)
+#else
static int __attribute__((format(printf, 3, 4)))
JS_ThrowTypeErrorOrFalse(JSContext *ctx, int flags, const char *fmt, ...)
+#endif
{
va_list ap;
@@ -6168,7 +6217,11 @@ static int JS_ThrowTypeErrorReadOnly(JSContext *ctx, int
flags, JSAtom atom)
}
}
+#if defined(_MSC_VER)
+JSValue JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...)
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowReferenceError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
JSValue val;
va_list ap;
@@ -6179,7 +6232,11 @@ JSValue __attribute__((format(printf, 2, 3)))
JS_ThrowReferenceError(JSContext *
return val;
}
+#if defined(_MSC_VER)
+JSValue JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...)
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowRangeError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
JSValue val;
va_list ap;
@@ -6190,7 +6247,11 @@ JSValue __attribute__((format(printf, 2, 3)))
JS_ThrowRangeError(JSContext *ctx,
return val;
}
+#if defined(_MSC_VER)
+JSValue JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...)
+#else
JSValue __attribute__((format(printf, 2, 3))) JS_ThrowInternalError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
JSValue val;
va_list ap;
@@ -6639,7 +6700,11 @@ static int JS_DefinePrivateField(JSContext *ctx,
JSValueConst obj,
JS_ThrowTypeErrorNotASymbol(ctx);
goto fail;
}
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ prop = js_symbol_to_atom(ctx, name);
+#else
prop = js_symbol_to_atom(ctx, (JSValue)name);
+#endif
p = JS_VALUE_GET_OBJ(obj);
prs = find_own_property(&pr, p, prop);
if (prs) {
@@ -6671,7 +6736,11 @@ static JSValue JS_GetPrivateField(JSContext *ctx,
JSValueConst obj,
/* safety check */
if (unlikely(JS_VALUE_GET_TAG(name) != JS_TAG_SYMBOL))
return JS_ThrowTypeErrorNotASymbol(ctx);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ prop = js_symbol_to_atom(ctx, name);
+#else
prop = js_symbol_to_atom(ctx, (JSValue)name);
+#endif
p = JS_VALUE_GET_OBJ(obj);
prs = find_own_property(&pr, p, prop);
if (!prs) {
@@ -6698,7 +6767,11 @@ static int JS_SetPrivateField(JSContext *ctx,
JSValueConst obj,
JS_ThrowTypeErrorNotASymbol(ctx);
goto fail;
}
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ prop = js_symbol_to_atom(ctx, name);
+#else
prop = js_symbol_to_atom(ctx, (JSValue)name);
+#endif
p = JS_VALUE_GET_OBJ(obj);
prs = find_own_property(&pr, p, prop);
if (!prs) {
@@ -6788,7 +6861,11 @@ static int JS_CheckBrand(JSContext *ctx, JSValueConst
obj, JSValueConst func)
if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT))
goto not_obj;
p = JS_VALUE_GET_OBJ(obj);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, brand));
+#else
prs = find_own_property(&pr, p, js_symbol_to_atom(ctx, (JSValue)brand));
+#endif
if (!prs) {
JS_ThrowTypeError(ctx, "invalid brand on object");
return -1;
@@ -9474,7 +9551,12 @@ static JSValue js_atod(JSContext *ctx, const char *str,
const char **pp,
} else {
no_radix_prefix:
if (!(flags & ATOD_INT_ONLY) && strstart(p, "Infinity", &p)) {
+#if defined(_MSC_VER)
+ double const zero = 0.0;
+ d = 1.0 / zero;
+#else
d = 1.0 / 0.0;
+#endif
goto done;
}
}
@@ -9752,7 +9834,7 @@ static JSValue JS_ToNumber(JSContext *ctx, JSValueConst
val)
return JS_ToNumberFree(ctx, JS_DupValue(ctx, val));
}
-static __attribute__((unused)) JSValue JS_ToIntegerFree(JSContext *ctx,
JSValue val)
+static unused JSValue JS_ToIntegerFree(JSContext *ctx, JSValue val)
{
uint32_t tag;
JSValue ret;
@@ -10821,14 +10903,14 @@ static JSValue JS_ToQuotedString(JSContext *ctx,
JSValueConst val1)
return JS_EXCEPTION;
}
-static __attribute__((unused)) void JS_DumpObjectHeader(JSRuntime *rt)
+static unused void JS_DumpObjectHeader(JSRuntime *rt)
{
printf("%14s %4s %4s %14s %10s %s\n",
"ADDRESS", "REFS", "SHRF", "PROTO", "CLASS", "PROPS");
}
/* for debug only: dump an object without side effect */
-static __attribute__((unused)) void JS_DumpObject(JSRuntime *rt, JSObject *p)
+static unused void JS_DumpObject(JSRuntime *rt, JSObject *p)
{
uint32_t i;
char atom_buf[ATOM_GET_STR_BUF_SIZE];
@@ -10862,7 +10944,13 @@ static __attribute__((unused)) void
JS_DumpObject(JSRuntime *rt, JSObject *p)
case JS_CLASS_ARGUMENTS:
JS_DumpValueShort(rt, p->u.array.u.values[i]);
break;
+#if defined(_MSC_VER)
+ default:
+ if (p->class_id >= JS_CLASS_UINT8C_ARRAY &&
+ p->class_id <= JS_CLASS_FLOAT64_ARRAY)
+#else
case JS_CLASS_UINT8C_ARRAY ... JS_CLASS_FLOAT64_ARRAY:
+#endif
{
int size = 1 << typed_array_size_log2(p->class_id);
const uint8_t *b = p->u.array.u.uint8_ptr + i * size;
@@ -10920,8 +11008,7 @@ static __attribute__((unused)) void
JS_DumpObject(JSRuntime *rt, JSObject *p)
printf("\n");
}
-static __attribute__((unused)) void JS_DumpValueShort(JSRuntime *rt,
- JSValueConst val)
+static unused void JS_DumpValueShort(JSRuntime *rt, JSValueConst val)
{
uint32_t tag = JS_VALUE_GET_NORM_TAG(val);
const char *str;
@@ -11018,15 +11105,13 @@ static __attribute__((unused)) void
JS_DumpValueShort(JSRuntime *rt,
}
}
-static __attribute__((unused)) void JS_DumpValue(JSContext *ctx,
- JSValueConst val)
+static unused void JS_DumpValue(JSContext *ctx, JSValueConst val)
{
JS_DumpValueShort(ctx->rt, val);
}
-static __attribute__((unused)) void JS_PrintValue(JSContext *ctx,
- const char *str,
- JSValueConst val)
+static unused void JS_PrintValue(JSContext *ctx, const char *str,
+ JSValueConst val)
{
printf("%s=", str);
JS_DumpValueShort(ctx->rt, val);
@@ -11245,7 +11330,7 @@ static bf_t *JS_ToBigInt(JSContext *ctx, bf_t *buf,
JSValueConst val)
return JS_ToBigIntFree(ctx, buf, JS_DupValue(ctx, val));
}
-static __attribute__((unused)) JSValue JS_ToBigIntValueFree(JSContext *ctx,
JSValue val)
+static unused JSValue JS_ToBigIntValueFree(JSContext *ctx, JSValue val)
{
if (JS_VALUE_GET_TAG(val) == JS_TAG_BIG_INT) {
return val;
@@ -14606,7 +14691,11 @@ static JSValue js_call_c_function(JSContext *ctx,
JSValueConst func_obj,
#else
sf->js_mode = 0;
#endif
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ sf->cur_func = func_obj;
+#else
sf->cur_func = (JSValue)func_obj;
+#endif
sf->arg_count = argc;
arg_buf = argv;
@@ -14882,7 +14971,11 @@ static JSValue JS_CallInternal(JSContext *ctx,
JSValueConst func_obj,
sf->js_mode = b->js_mode;
arg_buf = argv;
sf->arg_count = argc;
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ sf->cur_func = func_obj;
+#else
sf->cur_func = (JSValue)func_obj;
+#endif
init_list_head(&sf->var_ref_list);
var_refs = p->u.func.var_refs;
@@ -18750,17 +18843,23 @@ static void free_token(JSParseState *s, JSToken
*token)
JS_FreeValue(s->ctx, token->u.regexp.flags);
break;
case TOK_IDENT:
+#if !defined(_MSC_VER)
case TOK_FIRST_KEYWORD ... TOK_LAST_KEYWORD:
+#endif
case TOK_PRIVATE_NAME:
JS_FreeAtom(s->ctx, token->u.ident.atom);
break;
default:
+#if defined(_MSC_VER)
+ if (token->val >= TOK_FIRST_KEYWORD &&
+ token->val <= TOK_LAST_KEYWORD)
+ JS_FreeAtom(s->ctx, token->u.ident.atom);
+#endif
break;
}
}
-static void __attribute((unused)) dump_token(JSParseState *s,
- const JSToken *token)
+static void unused dump_token(JSParseState *s, const JSToken *token)
{
switch(token->val) {
case TOK_NUMBER:
@@ -18820,7 +18919,11 @@ static void __attribute((unused))
dump_token(JSParseState *s,
}
}
+#if defined(_WIN32)
+int js_parse_error(JSParseState *s, const char *fmt, ...)
+#else
int __attribute__((format(printf, 2, 3))) js_parse_error(JSParseState *s,
const char *fmt, ...)
+#endif
{
JSContext *ctx = s->ctx;
va_list ap;
@@ -19290,8 +19393,15 @@ static __exception int next_token(JSParseState *s)
}
}
goto def_token;
+#if defined(_MSC_VER)
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case
'h': case 'i': case 'j': case 'k': case 'l': case 'm':
+ case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case
'u': case 'v': case 'w': case 'x': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case
'H': case 'I': case 'J': case 'K': case 'L': case 'M':
+ case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case
'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
+#else
case 'a' ... 'z':
case 'A' ... 'Z':
+#endif
case '_':
case '$':
/* identifier */
@@ -19420,7 +19530,11 @@ static __exception int next_token(JSParseState *s)
goto fail;
}
goto parse_number;
+#if defined(_MSC_VER)
+ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case
'8': case '9':
+#else
case '1' ... '9':
+#endif
/* number */
parse_number:
#ifdef CONFIG_BIGNUM
@@ -27158,8 +27272,8 @@ static void dump_byte_code(JSContext *ctx, int pass,
js_free(ctx, bits);
}
-static __attribute__((unused)) void dump_pc2line(JSContext *ctx, const uint8_t
*buf, int len,
- int line_num)
+static unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,
+ int line_num)
{
const uint8_t *p_end, *p_next, *p;
int pc, v;
@@ -27203,7 +27317,7 @@ static __attribute__((unused)) void
dump_pc2line(JSContext *ctx, const uint8_t *
}
}
-static __attribute__((unused)) void js_dump_function_bytecode(JSContext *ctx,
JSFunctionBytecode *b)
+static unused void js_dump_function_bytecode(JSContext *ctx,
JSFunctionBytecode *b)
{
int i;
char atom_buf[ATOM_GET_STR_BUF_SIZE];
@@ -31666,7 +31780,7 @@ static void bc_put_u16(BCWriterState *s, uint16_t v)
dbuf_put_u16(&s->dbuf, v);
}
-static __attribute__((unused)) void bc_put_u32(BCWriterState *s, uint32_t v)
+static unused void bc_put_u32(BCWriterState *s, uint32_t v)
{
if (s->byte_swap)
v = bswap32(v);
@@ -32363,7 +32477,7 @@ static int bc_get_u16(BCReaderState *s, uint16_t *pval)
return 0;
}
-static __attribute__((unused)) int bc_get_u32(BCReaderState *s, uint32_t *pval)
+static unused int bc_get_u32(BCReaderState *s, uint32_t *pval)
{
if (unlikely(s->buf_end - s->ptr < 4)) {
*pval = 0; /* avoid warning */
@@ -36326,8 +36440,13 @@ static int64_t JS_FlattenIntoArray(JSContext *ctx,
JSValueConst target,
if (!JS_IsUndefined(mapperFunction)) {
JSValueConst args[3] = { element, JS_NewInt64(ctx, sourceIndex),
source };
element = JS_Call(ctx, mapperFunction, thisArg, 3, args);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ JS_FreeValue(ctx, args[0]);
+ JS_FreeValue(ctx, args[1]);
+#else
JS_FreeValue(ctx, (JSValue)args[0]);
JS_FreeValue(ctx, (JSValue)args[1]);
+#endif
if (JS_IsException(element))
return -1;
}
@@ -37916,7 +38035,11 @@ static JSValue js_string_match(JSContext *ctx,
JSValueConst this_val,
str = JS_NewString(ctx, "g");
if (JS_IsException(str))
goto fail;
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ args[args_len++] = str;
+#else
args[args_len++] = (JSValueConst)str;
+#endif
}
rx = JS_CallConstructor(ctx, ctx->regexp_ctor, args_len, args);
JS_FreeValue(ctx, str);
@@ -39290,7 +39413,12 @@ static JSValue js_math_min_max(JSContext *ctx,
JSValueConst this_val,
uint32_t tag;
if (unlikely(argc == 0)) {
+#if defined(_MSC_VER)
+ double const zero = 0.0;
+ return __JS_NewFloat64(ctx, is_max ? -1.0 / zero : 1.0 / zero);
+#else
return __JS_NewFloat64(ctx, is_max ? -1.0 / 0.0 : 1.0 / 0.0);
+#endif
}
tag = JS_VALUE_GET_TAG(argv[0]);
@@ -39445,9 +39573,13 @@ static uint64_t xorshift64star(uint64_t *pstate)
static void js_random_init(JSContext *ctx)
{
+#if defined(_MSC_VER) // FIXME: implement this
+ ctx->random_state = 42;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
ctx->random_state = ((int64_t)tv.tv_sec * 1000000) + tv.tv_usec;
+#endif
/* the state must be non zero */
if (ctx->random_state == 0)
ctx->random_state = 1;
@@ -39465,6 +39597,11 @@ static JSValue js_math_random(JSContext *ctx,
JSValueConst this_val,
return __JS_NewFloat64(ctx, u.d - 1.0);
}
+#if defined(_MSC_VER)
+static double const_floor(double x) { return floor(x); }
+static double const_ceil(double x) { return ceil(x); }
+#endif
+
static const JSCFunctionListEntry js_math_funcs[] = {
JS_CFUNC_MAGIC_DEF("min", 2, js_math_min_max, 0 ),
JS_CFUNC_MAGIC_DEF("max", 2, js_math_min_max, 1 ),
@@ -39473,8 +39610,13 @@ static const JSCFunctionListEntry js_math_funcs[] = {
#else
JS_CFUNC_SPECIAL_DEF("abs", 1, f_f, fabs ),
#endif
+#if defined(_MSC_VER)
+ JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, const_floor ),
+ JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, const_ceil ),
+#else
JS_CFUNC_SPECIAL_DEF("floor", 1, f_f, floor ),
JS_CFUNC_SPECIAL_DEF("ceil", 1, f_f, ceil ),
+#endif
JS_CFUNC_SPECIAL_DEF("round", 1, f_f, js_math_round ),
JS_CFUNC_SPECIAL_DEF("sqrt", 1, f_f, sqrt ),
@@ -39542,9 +39684,13 @@ static JSValue js___date_clock(JSContext *ctx,
JSValueConst this_val,
int argc, JSValueConst *argv)
{
int64_t d;
+#if defined(_MSC_VER) // FIXME: implement this
+ d = 42;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
d = (int64_t)tv.tv_sec * 1000000 + tv.tv_usec;
+#endif
return JS_NewInt64(ctx, d);
}
@@ -42048,7 +42194,11 @@ static JSValueConst js_proxy_getPrototypeOf(JSContext
*ctx, JSValueConst obj)
}
/* store the prototype in the proxy so that its refcount is at least 1 */
set_value(ctx, &s->proto, ret);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ return ret;
+#else
return (JSValueConst)ret;
+#endif
}
static int js_proxy_setPrototypeOf(JSContext *ctx, JSValueConst obj,
@@ -43280,7 +43430,11 @@ static JSMapRecord *map_add_record(JSContext *ctx,
JSMapState *s,
} else {
JS_DupValue(ctx, key);
}
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ mr->key = key;
+#else
mr->key = (JSValue)key;
+#endif
h = map_hash_key(ctx, key) & (s->hash_size - 1);
list_add_tail(&mr->hash_link, &s->hash_table[h]);
list_add_tail(&mr->link, &s->records);
@@ -43502,7 +43656,11 @@ static JSValue js_map_forEach(JSContext *ctx,
JSValueConst this_val,
args[0] = args[1];
else
args[0] = JS_DupValue(ctx, mr->value);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ args[2] = this_val;
+#else
args[2] = (JSValue)this_val;
+#endif
ret = JS_Call(ctx, func, this_arg, 3, (JSValueConst *)args);
JS_FreeValue(ctx, args[0]);
if (!magic)
@@ -44452,7 +44610,11 @@ static JSValue js_promise_all(JSContext *ctx,
JSValueConst this_val,
goto fail_reject;
}
resolve_element_data[0] = JS_NewBool(ctx, FALSE);
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ resolve_element_data[1] = JS_NewInt32(ctx, index);
+#else
resolve_element_data[1] = (JSValueConst)JS_NewInt32(ctx, index);
+#endif
resolve_element_data[2] = values;
resolve_element_data[3] = resolving_funcs[0];
resolve_element_data[4] = resolve_element_env;
@@ -44801,7 +44963,11 @@ static JSValue
js_async_from_sync_iterator_unwrap_func_create(JSContext *ctx,
{
JSValueConst func_data[1];
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ func_data[0] = JS_NewBool(ctx, done);
+#else
func_data[0] = (JSValueConst)JS_NewBool(ctx, done);
+#endif
return JS_NewCFunctionData(ctx, js_async_from_sync_iterator_unwrap,
1, 0, 1, func_data);
}
@@ -45105,7 +45271,11 @@ static int isURIReserved(int c) {
return c < 0x100 && memchr(";/?:@&=+$,#", c, sizeof(";/?:@&=+$,#") - 1) !=
NULL;
}
+#if defined(_MSC_VER)
+static int js_throw_URIError(JSContext *ctx, const char *fmt, ...)
+#else
static int __attribute__((format(printf, 2, 3))) js_throw_URIError(JSContext
*ctx, const char *fmt, ...)
+#endif
{
va_list ap;
@@ -45718,9 +45888,13 @@ static JSValue get_date_string(JSContext *ctx,
JSValueConst this_val,
/* OS dependent: return the UTC time in ms since 1970. */
static int64_t date_now(void) {
+#if defined(_MSC_VER) // FIXME: implement this
+ return 42;
+#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (int64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
+#endif
}
static JSValue js_date_constructor(JSContext *ctx, JSValueConst new_target,
@@ -48791,7 +48965,11 @@ struct TA_sort_context {
JSValueConst arr;
JSValueConst cmp;
JSValue (*getfun)(JSContext *ctx, const void *a);
+#if defined(_MSC_VER)
+ char *array_ptr;
+#else
void *array_ptr; /* cannot change unless the array is detached */
+#endif
int elt_size;
};
@@ -48836,8 +49014,13 @@ static int js_TA_cmp_generic(const void *a, const void
*b, void *opaque) {
psc->exception = 1;
}
done:
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ JS_FreeValue(ctx, argv[0]);
+ JS_FreeValue(ctx, argv[1]);
+#else
JS_FreeValue(ctx, (JSValue)argv[0]);
JS_FreeValue(ctx, (JSValue)argv[1]);
+#endif
}
return cmp;
}
diff --git a/quickjs.h b/quickjs.h
index 206516b..a116a7c 100644
--- a/quickjs.h
+++ b/quickjs.h
@@ -53,7 +53,7 @@ typedef struct JSClass JSClass;
typedef uint32_t JSClassID;
typedef uint32_t JSAtom;
-#if defined(__x86_64__) || defined(__aarch64__)
+#if defined(__x86_64__) || defined(__aarch64__) || defined(_WIN64)
#define JS_PTR64
#define JS_PTR64_DEF(a) a
#else
@@ -185,9 +185,9 @@ static inline int JS_VALUE_GET_NORM_TAG(JSValue v)
#else /* !JS_NAN_BOXING */
typedef union JSValueUnion {
+ void *ptr;
int32_t int32;
double float64;
- void *ptr;
} JSValueUnion;
typedef struct JSValue {
@@ -205,8 +205,17 @@ typedef struct JSValue {
#define JS_VALUE_GET_FLOAT64(v) ((v).u.float64)
#define JS_VALUE_GET_PTR(v) ((v).u.ptr)
+#if defined(_MSC_VER) && defined(__cplusplus)
+#define JS_MKVAL(tag, val) [&](){ JSValue tmp { { (void *)((intptr_t)val <<
32) }, tag }; return tmp; }()
+#define JS_MKPTR(tag, p) [&](){ JSValue tmp { { p }, tag }; return tmp; }()
+#elif defined(_MSC_VER)
+#define JS_VALUE_CANNOT_BE_CAST 1
+#define JS_MKVAL(tag, val) (JSValue){ { (void *)(intptr_t)(val) }, tag }
+#define JS_MKPTR(tag, p) (JSValue){ { p }, tag }
+#else
#define JS_MKVAL(tag, val) (JSValue){ (JSValueUnion){ .int32 = val }, tag }
#define JS_MKPTR(tag, p) (JSValue){ (JSValueUnion){ .ptr = p }, tag }
+#endif
#define JS_TAG_IS_FLOAT64(tag) ((unsigned)(tag) == JS_TAG_FLOAT64)
@@ -586,7 +595,11 @@ static inline JSValue JS_DupValue(JSContext *ctx,
JSValueConst v)
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
p->ref_count++;
}
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ return v;
+#else
return (JSValue)v;
+#endif
}
static inline JSValue JS_DupValueRT(JSRuntime *rt, JSValueConst v)
@@ -595,7 +608,11 @@ static inline JSValue JS_DupValueRT(JSRuntime *rt,
JSValueConst v)
JSRefCountHeader *p = (JSRefCountHeader *)JS_VALUE_GET_PTR(v);
p->ref_count++;
}
+#if defined(JS_VALUE_CANNOT_BE_CAST)
+ return v;
+#else
return (JSValue)v;
+#endif
}
int JS_ToBool(JSContext *ctx, JSValueConst val); /* return -1 for JS_EXCEPTION
*/