Skip to content

Commit

Permalink
use c-smile/quickjspp to address theduke#72
Browse files Browse the repository at this point in the history
compiles on msvc but crashes on all tests
  • Loading branch information
l0calh05t committed Nov 19, 2020
1 parent dad76a5 commit cfe9dc6
Show file tree
Hide file tree
Showing 12 changed files with 760 additions and 329 deletions.
59 changes: 53 additions & 6 deletions libquickjs-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ fn main() {
println!("cargo:rustc-link-lib=static={}", LIB_NAME);
}

#[cfg(not(target_env = "msvc"))]
#[cfg(feature = "bundled")]
fn main() {
// compile statics
Expand All @@ -81,8 +82,6 @@ fn main() {
apply_patches(&code_dir);

eprintln!("Compiling quickjs...");
let quickjs_version =
std::fs::read_to_string(code_dir.join("VERSION")).expect("failed to read quickjs version");
cc::Build::new()
.files(
[
Expand All @@ -96,10 +95,6 @@ fn main() {
.map(|f| code_dir.join(f)),
)
.define("_GNU_SOURCE", None)
.define(
"CONFIG_VERSION",
format!("\"{}\"", quickjs_version.trim()).as_str(),
)
.define("CONFIG_BIGNUM", None)
// The below flags are used by the official Makefile.
.flag_if_supported("-Wchar-subscripts")
Expand Down Expand Up @@ -128,6 +123,58 @@ fn main() {
.expect("Could not copy bindings.rs");
}

#[cfg(target_env = "msvc")]
#[cfg(feature = "bundled")]
fn main() {
// compile statics
cc::Build::new()
.file("static-functions.c")
// JS_STRICT_NAN_BOXING required for MSVC build
.define("JS_STRICT_NAN_BOXING", None)
.define("_CRT_SECURE_NO_WARNINGS", None)
.flag_if_supported("/std:c++latest")
.compile("quickjs-static-functions.lib");

let embed_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("embed");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());

let code_dir = out_path.join("quickjs");
if exists(&code_dir) {
std::fs::remove_dir_all(&code_dir).unwrap();
}
copy_dir::copy_dir(embed_path.join("quickjs"), &code_dir)
.expect("Could not copy quickjs directory");

// Patch command generally unavailable on Windows
// #[cfg(feature = "patched")]
// apply_patches(&code_dir);

eprintln!("Compiling quickjs...");
cc::Build::new()
.files(
[
"cutils.c",
"libbf.c",
"libregexp.c",
"libunicode.c",
"quickjs.c",
]
.iter()
.map(|f| code_dir.join(f)),
)
// JS_STRICT_NAN_BOXING required for MSVC build
.define("JS_STRICT_NAN_BOXING", None)
.define("_CRT_SECURE_NO_WARNINGS", None)
.define("CONFIG_BIGNUM", None)
.flag_if_supported("/std:c++latest")
// c-smile/quickjspp does not build with opt_level(2)!
.opt_level(1)
.compile(LIB_NAME);

std::fs::copy(embed_path.join("bindings.rs"), out_path.join("bindings.rs"))
.expect("Could not copy bindings.rs");
}

#[cfg(feature = "patched")]
fn apply_patches(code_dir: &PathBuf) {
use std::fs;
Expand Down
31 changes: 31 additions & 0 deletions libquickjs-sys/embed/quickjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@


# QuickJS Javascript Engine

Authors: Fabrice Bellard and Charlie Gordon

Ported from https://bellard.org/quickjs/ and its official GitHub mirror https://github.com/bellard/quickjs

By Andrew Fedoniouk (a.k.a. c-smile)

This version is

* Microsoft Visual C++ compatible/compileable
* Is used in Sciter.JS
* It contains extras, check [wiki](https://github.com/c-smile/quickjspp/wiki)

The main documentation is in doc/quickjs.pdf or doc/quickjs.html.

# Build using Microsoft Visual Studio (2017 or 2019)

Prerequisite: **premake5** - [download](https://premake.github.io/download.html) and install it.

Then go to /win folder and run premake-vs2017.bat or premake-vs2019.bat .

It will generate .build/vs2017/quickjs-msvc.sln and open it in Microsoft Visual Studio.

Press F5 to compile it and run qjs - interactive JS command line application.




26 changes: 25 additions & 1 deletion libquickjs-sys/embed/quickjs/cutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,30 @@

#include "cutils.h"

#ifdef _MSC_VER

// From: https://stackoverflow.com/a/26085827
int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL);

SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;

GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
time = ((uint64_t)file_time.dwLowDateTime);
time += ((uint64_t)file_time.dwHighDateTime) << 32;

tp->tv_sec = (long)((time - EPOCH) / 10000000L);
tp->tv_usec = (long)(system_time.wMilliseconds * 1000);

return 0;
}
#endif


void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
Expand Down Expand Up @@ -297,7 +321,7 @@ int unicode_from_utf8(const uint8_t *p, int max_len, const uint8_t **pp)
return -1;
c = (c << 6) | (b & 0x3f);
}
if (c < utf8_min_code[l - 1])
if (c < (int)utf8_min_code[l - 1])
return -1;
*pp = p;
return c;
Expand Down
97 changes: 90 additions & 7 deletions libquickjs-sys/embed/quickjs/cutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,32 @@
#include <stdlib.h>
#include <inttypes.h>

#ifdef _MSC_VER
#include <windows.h>
#include <intrin.h>
#else
#include <sys/time.h>
#endif

/* set if CPU is big endian */
#undef WORDS_BIGENDIAN

#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))
#define __maybe_unused __attribute__((unused))
#ifndef __has_attribute
#define likely(x) (x)
#define unlikely(x) (x)
#define force_inline __forceinline
#define no_inline __declspec(noinline)
#define __maybe_unused
#define __attribute__(x)
#define __attribute(x)
typedef intptr_t ssize_t;
#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))
#define __maybe_unused __attribute__((unused))
#endif

#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
Expand Down Expand Up @@ -114,27 +132,91 @@ static inline int64_t min_int64(int64_t a, int64_t b)
/* WARNING: undefined if a = 0 */
static inline int clz32(unsigned int a)
{
#ifdef _MSC_VER
unsigned long idx;
_BitScanReverse(&idx, a);
return 31 ^ idx;
#else
return __builtin_clz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int clz64(uint64_t a)
{
return __builtin_clzll(a);
#ifdef _MSC_VER
unsigned long where;
// BitScanReverse scans from MSB to LSB for first set bit.
// Returns 0 if no set bit is found.
#if INTPTR_MAX >= INT64_MAX // 64-bit
if (_BitScanReverse64(&where, a))
return (int)(63 - where);
#else
// Scan the high 32 bits.
if (_BitScanReverse(&where, (uint32_t)(a >> 32)))
return (int)(63 - (where + 32)); // Create a bit offset from the MSB.
// Scan the low 32 bits.
if (_BitScanReverse(&where, (uint32_t)(a)))
return (int)(63 - where);
#endif
return 64; // Undefined Behavior.
#else
return __builtin_clzll(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz32(unsigned int a)
{
#ifdef _MSC_VER
unsigned long idx;
_BitScanForward(&idx, a);
return 31 ^ idx;
#else
return __builtin_ctz(a);
#endif
}

/* WARNING: undefined if a = 0 */
static inline int ctz64(uint64_t a)
{
return __builtin_ctzll(a);
#ifdef _MSC_VER
unsigned long where;
// Search from LSB to MSB for first set bit.
// Returns zero if no set bit is found.
#if INTPTR_MAX >= INT64_MAX // 64-bit
if (_BitScanForward64(&where, a))
return (int)(where);
#else
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
// Scan the Low Word.
if (_BitScanForward(&where, (uint32_t)(a)))
return (int)(where);
// Scan the High Word.
if (_BitScanForward(&where, (uint32_t)(a >> 32)))
return (int)(where + 32); // Create a bit offset from the LSB.
#endif
return 64;
#else
return __builtin_ctzll(a);
#endif
}

#ifdef _MSC_VER
#pragma pack(push, 1)
struct packed_u64 {
uint64_t v;
};

struct packed_u32 {
uint32_t v;
};

struct packed_u16 {
uint16_t v;
};
#pragma pack(pop)
#else
struct __attribute__((packed)) packed_u64 {
uint64_t v;
};
Expand All @@ -146,6 +228,7 @@ struct __attribute__((packed)) packed_u32 {
struct __attribute__((packed)) packed_u16 {
uint16_t v;
};
#endif

static inline uint64_t get_u64(const uint8_t *tab)
{
Expand Down
2 changes: 1 addition & 1 deletion libquickjs-sys/embed/quickjs/libregexp.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ static int parse_digits(const uint8_t **pp, BOOL allow_overflow)
p++;
}
*pp = p;
return v;
return (int)v;
}

static int re_parse_expect(REParseState *s, const uint8_t **pp, int c)
Expand Down
8 changes: 6 additions & 2 deletions libquickjs-sys/embed/quickjs/qjs.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,20 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#if defined(__APPLE__)
#include <malloc/malloc.h>
#include <unistd.h>
#elif defined(__linux__)
#include <malloc.h>
#include <unistd.h>
#endif

#include "cutils.h"
#include "quickjs-libc.h"
#include "quickjs-version.h"

extern const uint8_t qjsc_repl[];
extern const uint32_t qjsc_repl_size;
Expand Down Expand Up @@ -276,7 +278,7 @@ static const JSMallocFunctions trace_mf = {

void help(void)
{
printf("QuickJS version " CONFIG_VERSION "\n"
printf("QuickJS version " QUICKJS_VERSION "\n"
"usage: " PROG_NAME " [options] [file [args]]\n"
"-h --help list options\n"
"-e --eval EXPR evaluate EXPR\n"
Expand Down Expand Up @@ -448,8 +450,10 @@ int main(int argc, char **argv)
}
}

#ifdef CONFIG_BIGNUM
if (load_jscalc)
bignum_ext = 1;
#endif

if (trace_memory) {
js_trace_malloc_init(&trace_data);
Expand Down
7 changes: 5 additions & 2 deletions libquickjs-sys/embed/quickjs/qjsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,17 @@
#include <inttypes.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#if !defined(_WIN32)
#include <sys/wait.h>
#include <unistd.h>
#else
#include "win/getopt.h"
#endif

#include "cutils.h"
#include "quickjs-libc.h"
#include "quickjs-version.h"

typedef struct {
char *name;
Expand Down Expand Up @@ -341,7 +344,7 @@ static const char main_c_template2[] =

void help(void)
{
printf("QuickJS Compiler version " CONFIG_VERSION "\n"
printf("QuickJS Compiler version " QUICKJS_VERSION "\n"
"usage: " PROG_NAME " [options] [files]\n"
"\n"
"options are:\n"
Expand Down
3 changes: 3 additions & 0 deletions libquickjs-sys/embed/quickjs/quickjs-atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,9 @@ DEF(BigDecimal, "BigDecimal")
DEF(OperatorSet, "OperatorSet")
DEF(Operators, "Operators")
#endif
#ifdef CONFIG_JSX
DEF(JSX, "JSX")
#endif
DEF(Map, "Map")
DEF(Set, "Set") /* Map + 1 */
DEF(WeakMap, "WeakMap") /* Map + 2 */
Expand Down
Loading

0 comments on commit cfe9dc6

Please sign in to comment.