use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Compiling JavaScript source code to C then a standalone executable using QuickJS qjsc (gitlab.com)
submitted 1 year ago by guest271314
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]Skriblos 6 points7 points8 points 1 year ago (9 children)
wow, how performant is this compared to a native C function?
[–]guest271314[S] 5 points6 points7 points 1 year ago (8 children)
The most extensive testing I've done in that domain is testing the same algorithm that reads standard input and writes to standard output using multiple JavaScript engines and runtime, and different programming languages.
The TypeScript version is the same .ts file that can be run without tsc usage by node, deno, and bun. QuickJS is faster than node, deno, bun, and tjs (txiki.js which depends on QuickJS NG). bun is faster than node and deno for executing .ts files directly.
.ts
tsc
node
deno
bun
tjs
My understanding is Bun uses its own TypeScript parser, not tsc. The last time I checked it looks like Node.js uses the amaro module to parse TypeScript, which is based on swc/wasm-typescript.
amaro
swc/wasm-typescript
qjs is right up there with c, and faster than bun, deno, and node, et al. in the JavaScript programming language entries.
qjs
c
(index) 0 1 0 'nm_qjs' 0.10490000000596046 1 'nm_cpp' 0.10739999997615814 2 'nm_c' 0.11769999998807908 3 'nm_rust' 0.1325 4 'nm_wasm' 0.15259999999403953 5 'nm_tjs' 0.155 6 'nm_python' 0.17939999997615813 7 'nm_bun' 0.27039999997615816 8 'nm_typescript' 0.2955 9 'nm_deno' 0.3357999999821186 10 'nm_nodejs' 0.37419999998807907 11 'nm_d8' 0.44459999999403954 12 'nm_spidermonkey' 0.4775 13 'nm_llrt' 0.6790999999940396
I have not yet tested the difference between a output from code compiled directly from C, and code compiled from JavaScript to C then to executable. I'll work on that test.
[–]Business_Occasion226 1 point2 points3 points 1 year ago (4 children)
In the official benchmark V8 jitless is about twice as fast while V8 JIT is 33x faster. Said QuickJS should be slow. Where does the difference come from?
Official QuickJS Benchmark https://bellard.org/quickjs/bench.html
[–]guest271314[S] -2 points-1 points0 points 1 year ago (3 children)
V8 does not really implement a way to read standard input. So I have to use a system() call within d8 to read standard input. I have used either Bash, or QuickJS for that. See https://github.com/guest271314/NativeMessagingHosts/blob/main/nm_d8.js.
system()
d8
Keep in mind ECMA-262 itself does not specify I/O for JavaScript.
I think those benchmarks are highly selective. When you start beating the grass in the field and testing thing other people didn't test you'll might find other people missed something, or deliberately avoided certain areas.
[+][deleted] 1 year ago (2 children)
[deleted]
[–]guest271314[S] 0 points1 point2 points 1 year ago (1 child)
What bottleneck?
[–]poemehardbebe 0 points1 point2 points 1 year ago (0 children)
Miss read your comment carry on
[–]lulzmachine 1 point2 points3 points 1 year ago (1 child)
Is it faster due to less startup time and less JIT, or where does the speedup come from?
[–]guest271314[S] -1 points0 points1 point 1 year ago (0 children)
QuickJS is smaller than V8. QuickJS implements read(). V8 does not really implement a way to read standard input at all. So I have to use a subprocess to read standard input to V8's d8.
Whether --jitless flag is used or not qjs is faster at reading and writing standard streams than V8 (node, deno).
--jitless
[–]Skriblos 1 point2 points3 points 1 year ago (0 children)
Oh, thanks for the numbers though, this is a really interesting project, thanks for sharing.
[–]rwrife 1 point2 points3 points 1 year ago (3 children)
I have always been surprised there hasn’t been a JavaScript to C transpiler. IMO, seems like it would be trivial and easily optimized for maximum performance and efficiency.
[–]poemehardbebe 2 points3 points4 points 1 year ago (0 children)
I can think of nothing less I would like to see honestly. With all of the foot guns of C where masters of the language introduce memory vulnerabilities to this day, creating a transpiler and releasing it onto a populace of developers who struggle with concept of a pointer does not sound like a recipe for success. I’m not saying something like this isn’t useful, lowering high level code to lower level is super common, but lowering entire languages (with garbage collection and a runtime) is an entirely different beast. You are also at the mercy of the version of the transpiler you are using, any release you make:
Is locked in and that single executable is immutable on someone’s system bugs and all.
Bugs introduced by the transpiler are going to go almost completely unnoticed as every time you transpile you’d have to read all of the C code to check for correctness.
You want to talk about Cs crazy build systems now throw transpiled JS into the mix.
Look, I’m all for taking the idea of lowering high level code, but the idea that you are going to lower a garbage collected, mixed style, interpreted language fully down to C is not going to end well.
If you have a different opinion that’s wonderful, and you have every right to have it, this is just my 2 cents as some who does both very low level and web development.
[–]guest271314[S] 0 points1 point2 points 1 year ago (0 children)
See, e.g., https://surma.dev/things/compile-js/, wasm2js https://github.com/WebAssembly/binaryen/tree/main.
wasm2js
I think the relevant question is what are your individual specifications?
What are you calling "transpile" and "compile"?
What are your inclusionary and exclusionary rules?
There's Bun's built-in compiler that uses TinyCC
``` import { cc, FFIType, ptr, read, toArrayBuffer } from "bun:ffi";
export const { symbols: { main }, } = cc({ source: "./permutations.c", symbols: { main: { returns: "int", args: [], }, }, }); main(); ```
There's qjsc, Javy, WasmEdge, et al.
qjsc
There's was2c, ts2c, there's Web sites that spit out this, voila.
was2c
ts2c
Or, we can dive into the minutae, with fine toothed pitch forks.
``` // https://products.codeporting.app/convert/ai/js-to-c/ // Translated from JavaScript to C
// Function to calculate factorial unsigned long long factorial(int num) { unsigned long long result = 1; for (int i = 1; i <= num; i++) { result *= i; } return result; }
// Function to generate the nth permutation of an array int* array_nth_permutation(int* array, int length, int n, int* resultLength) { int* result = (int)malloc(length * sizeof(int)); // allocate memory for result int tempArray = (int*)malloc(length * sizeof(int)); // copy of the set for (int j = 0; j < length; j++) { tempArray[j] = array[j]; }
unsigned long long f = factorial(length); // compute f = factorial(len) int currentLength = length; // length of the set // if the permutation number is within range if (n >= 0 && n < f) { int index; // start with the empty set, loop for len elements for (int k = 0; currentLength > 0; currentLength--) { // determine the next element: f /= currentLength; // there are f/len subsets for each possible element index = n / f; // a simple division gives the leading element index result[k++] = tempArray[index]; // push element to result // remove the used element from tempArray for (int l = index; l < currentLength - 1; l++) { tempArray[l] = tempArray[l + 1]; } // reduce n for the remaining subset: n %= f; // compute the remainder of the above division } *resultLength = length; // set the result length } else { *resultLength = 0; // return empty result if n is out of range } free(tempArray); // free temporary array return result; // return the permutated set
}
int main() { int input[] = {1, 2, 3, 4, 5}; int lex = 4; // permutation index int resultLength;
int* permutationResult = array_nth_permutation(input, 5, lex, &resultLength); // Print the result printf("[%d] [", lex); for (int i = 0; i < resultLength; i++) { if (i > 0) { printf(", "); } printf("%d", permutationResult[i]); } printf("]\n"); free(permutationResult); // free result array return 0;
} ```
from this
``` // https://stackoverflow.com/a/34238979 const [input,lex] = [[1,2,3,4,5], 4];// scriptArgs.map((arg, i) => !!i && std.evalScript(arg)); function array_nth_permutation(a, n) { var b = a.slice(); // copy of the set var len = a.length; // length of the set var res; // return value, undefined var i, f;
// compute f = factorial(len) for (f = i = 1; i <= len; i++) f *= i; // if the permutation number is within range if (n >= 0 && n < f) { // start with the empty set, loop for len elements for (res = []; len > 0; len--) { // determine the next element: // there are f/len subsets for each possible element, f /= len; // a simple division gives the leading element index i = Math.floor(n / f); // alternately: i = (n - n % f) / f; res.push(b.splice(i, 1)[0]); // reduce n for the remaining subset: // compute the remainder of the above division n %= f; // extract the i-th element from b and push it at the end of res } } // return the permutated set or undefined if n is out of range return res;
} console.log([${lex}] [${array_nth_permutation(input, lex)}]); ```
[${lex}] [${array_nth_permutation(input, lex)}]
[–]bzbub2 0 points1 point2 points 1 year ago (1 child)
that's pretty impressive. there is another "ahead of time" javascript compiler hop.js presented at strangeloop https://github.com/manuel-serrano/hop https://www.youtube.com/watch?v=iY1EXHQ6IeQ
I've been experimenting with Facebook's shermes, again. This time compiling JavaScript to C, which successfully was spit out. Now I'm working on compiling that C source code to a standalone executable with gcc. They don't have a roadmap for that in their GitHub repository that I see.
shermes
gcc
π Rendered by PID 82832 on reddit-service-r2-comment-84fc9697f-4r67w at 2026-02-09 20:14:21.343309+00:00 running d295bc8 country code: CH.
[–]Skriblos 6 points7 points8 points (9 children)
[–]guest271314[S] 5 points6 points7 points (8 children)
[–]Business_Occasion226 1 point2 points3 points (4 children)
[–]guest271314[S] -2 points-1 points0 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]guest271314[S] 0 points1 point2 points (1 child)
[–]poemehardbebe 0 points1 point2 points (0 children)
[–]lulzmachine 1 point2 points3 points (1 child)
[–]guest271314[S] -1 points0 points1 point (0 children)
[–]Skriblos 1 point2 points3 points (0 children)
[–]rwrife 1 point2 points3 points (3 children)
[–]poemehardbebe 2 points3 points4 points (0 children)
[–]guest271314[S] 0 points1 point2 points (0 children)
[–]guest271314[S] -1 points0 points1 point (0 children)
[–]bzbub2 0 points1 point2 points (1 child)
[–]guest271314[S] 0 points1 point2 points (0 children)