{"id":35140294,"url":"https://github.com/bellard/mquickjs","last_synced_at":"2026-01-21T05:08:44.567Z","repository":{"id":329967058,"uuid":"1121153522","full_name":"bellard/mquickjs","owner":"bellard","description":"Public repository of the Micro QuickJS Javascript Engine","archived":false,"fork":false,"pushed_at":"2026-01-15T09:28:33.000Z","size":98,"stargazers_count":5298,"open_issues_count":13,"forks_count":186,"subscribers_count":31,"default_branch":"main","last_synced_at":"2026-01-15T15:33:27.449Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bellard.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-12-22T14:20:32.000Z","updated_at":"2026-01-15T14:03:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bellard/mquickjs","commit_stats":null,"previous_names":["bellard/mquickjs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bellard/mquickjs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellard%2Fmquickjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellard%2Fmquickjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellard%2Fmquickjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellard%2Fmquickjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bellard","download_url":"https://codeload.github.com/bellard/mquickjs/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bellard%2Fmquickjs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28627388,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-28T11:00:48.327Z","updated_at":"2026-01-21T05:08:44.562Z","avatar_url":"https://github.com/bellard.png","language":"C","readme":"MicroQuickJS\n============\n\n## Introduction\n\nMicroQuickJS (aka. MQuickJS) is a JavaScript engine targeted at\nembedded systems. It compiles and runs JavaScript programs using as little\nas 10 kB of RAM. The whole engine requires about 100 kB of ROM (ARM\nThumb-2 code) including the C library. The speed is comparable to\nQuickJS.\n\nMQuickJS only supports a [subset](#javascript-subset-reference) of JavaScript close to ES5. It\nimplements a **stricter mode** where some error prone or inefficient\nJavaScript constructs are forbidden.\n\nAlthough MQuickJS shares much code with QuickJS, it internals are\ndifferent in order to consume less memory. In particular, it relies on\na tracing garbage collector, the VM does not use the CPU stack and\nstrings are stored in UTF-8.\n\n## REPL\n\nThe REPL is `mqjs`. Usage:\n\n```\nusage: mqjs [options] [file [args]]\n-h  --help            list options\n-e  --eval EXPR       evaluate EXPR\n-i  --interactive     go to interactive mode\n-I  --include file    include an additional file\n-d  --dump            dump the memory usage stats\n    --memory-limit n  limit the memory usage to 'n' bytes\n--no-column           no column number in debug information\n-o FILE               save the bytecode to FILE\n-m32                  force 32 bit bytecode output (use with -o)\n-b  --allow-bytecode  allow bytecode in input file\n```\n\nCompile and run a program using 10 kB of RAM:\n\n```sh\n./mqjs --memory-limit 10k tests/mandelbrot.js\n```\n\n\nIn addition to normal script execution, `mqjs` can output the compiled\nbytecode to a persistent storage (file or ROM):\n\n```sh\n./mqjs -o mandelbrot.bin tests/mandelbrot.js\n```\n\nThen you can run the compiled bytecode as a normal script:\n\n```sh\n./mqjs -b mandelbrot.bin\n```\n\nThe bytecode format depends on the endianness and word length (32 or\n64 bit) of the CPU. On a 64 bit CPU, it is possible to use the option\n`-m32` to generate 32 bit bytecode that can run on an embedded 32 bit\nsystem.\n\nUse the option `--no-column` to remove the column number debug info\n(only line numbers are remaining) if you want to save some storage.\n\n## Stricter mode\n\nMQuickJS only supports a subset of JavaScript (mostly ES5). It is\nalways in **stricter** mode where some error prone JavaScript features\nare disabled. The general idea is that the stricter mode is a subset\nof JavaScript, so it still works as usual in other JavaScript\nengines. Here are the main points:\n\n- Only **strict mode** constructs are allowed, hence no `with` keyword\n  and global variables must be declared with the `var` keyword.\n\n- Arrays cannot have holes. Writing an element after the end is not\n  allowed:\n```js\n    a = []\n    a[0] = 1; // OK to extend the array length\n    a[10] = 2; // TypeError\n```\n  If you need an array like object with holes, use a normal object\n  instead:\n```js\n    a = {}\n    a[0] = 1;\n    a[10] = 2;\n```\n  `new Array(len)` still works as expected, but the array elements are\n  initialized to `undefined`.\n  Array literals with holes are a syntax error:\n```js\n    [ 1, , 3 ] // SyntaxError\n```\n- Only global `eval` is supported so it cannot access to nor modify\n  local variables:\n```js\n    eval('1 + 2'); // forbidden\n    (1, eval)('1 + 2'); // OK\n```\n- No value boxing: `new Number(1)` is not supported and never\n  necessary.\n\n## JavaScript Subset Reference\n \n- Only strict mode is supported with emphasis on ES5 compatibility.\n\n- `Array` objects:\n\n    - They have no holes.\n    \n    - Numeric properties are always handled by the array object and not\n      forwarded to its prototype.\n  \n    - Out-of-bound sets are an error except when they are at the end of\n      the array.\n      \n    - The `length` property is a getter/setter in the array prototype.\n\n- all properties are writable, enumerable and configurable.\n\n- `for in` only iterates over the object own properties. It should be\n  used with this common pattern to have a consistent behavior with\n  standard JavaScript:\n  \n```js\n    for(var prop in obj) {\n        if (obj.hasOwnProperty(prop)) {\n            ...\n        }\n    }\n```    \nAlways prefer using `for of` instead which is supported with arrays:\n\n```js\n    for(var prop of Object.keys(obj)) {\n        ...\n    }\n```\n\n- `prototype`, `length` and `name` are getter/setter in function objects.\n\n- C functions cannot have their own properties (but C constructors\n  behave as expected).\n\n- The global object is supported, but its use is discouraged. It\n  cannot contain getter/setters and properties directly created in it\n  are not visible as global variables in the executing script.\n\n- The variable associated with the `catch` keyword is a normal\n  variable.\n\n- Direct `eval` is not supported. Only indirect (=global) `eval` is\n  supported.\n\n- No value boxing (e.g. `new Number(1)` is not supported)\n\n- Regexp:\n\n    - case folding only works with ASCII characters.\n\n    - the matching is unicode only i.e. `/./` matches a unicode code\n      point instead of an UTF-16 character as with the `u` flag.\n\n- String: `toLowerCase` / `toUpperCase` only handle ASCII characters.\n\n- Date: only `Date.now()` is supported.\n\nES5 extensions:\n  \n- `for of` is supported but iterates only over arrays. No custom\n   iterator is supported (yet).\n\n- Typed arrays.\n\n- `\\u{hex}` is accepted in string literals\n\n- Math functions: `imul`, `clz32`, `fround`, `trunc`, `log2`, `log10`.\n\n- The exponentiation operator\n\n- Regexp: the dotall (`s`), sticky (`y`) and unicode (`u`) flags are\n  accepted. In unicode mode, the unicode properties are not supported.\n\n- String functions: `codePointAt`, `replaceAll`, `trimStart`, `trimEnd`.\n\n- The `globalThis` global property.\n\n## C API\n\n### Engine initialization\n\nMQuickJS has almost no dependency on the C library. In particular it\ndoes not use `malloc()`, `free()` nor `printf()`. When creating a\nMQuickJS context, a memory buffer must be provided. The engine only\nallocates memory in this buffer:\n```c\n    JSContext *ctx;\n    uint8_t mem_buf[8192];\n    ctx = JS_NewContext(mem_buf, sizeof(mem_buf), \u0026js_stdlib);\n    ...\n    JS_FreeContext(ctx);\n```\n`JS_FreeContext(ctx)` is only necessary to call the finalizers of user\nobjects as no system memory is allocated by the engine.\n\n### Memory handling\n\nThe C API is very similar to QuickJS (see `mquickjs.h`). However,\nsince there is a compacting garbage collector, there are important\ndifferences:\n\n1. Explicitly freeing values is not necessary (no `JS_FreeValue()`).\n\n2. The address of objects can move each time a JS allocation is\ncalled. The general rule is to avoid having variables of type\n`JSValue` in C. They may be present only for temporary use between\nMQuickJS API calls. In the other cases, always use a pointer to a\n`JSValue`. `JS_PushGCRef()` returns a pointer to a temporary opaque\n`JSValue` stored in a `JSGCRef` variable. `JS_PopGCRef()` must be used\nto release the temporary reference. The opaque value in `JSGCRef` is\nautomatically updated when objects move. Example:\n\n```c\nJSValue my_js_func(JSContext *ctx, JSValue *this_val, int argc, JSValue *argv)\n{\n        JSGCRef obj1_ref, obj2_ref;\n        JSValue *obj1, *obj2, ret;\n\n        ret = JS_EXCEPTION;\n        obj1 = JS_PushGCRef(ctx, \u0026obj1_ref);\n        obj2 = JS_PushGCRef(ctx, \u0026obj2_ref);\n        *obj1 = JS_NewObject(ctx);\n        if (JS_IsException(*obj1))\n            goto fail;\n        *obj2 = JS_NewObject(ctx); // obj1 may move\n        if (JS_IsException(*obj2))\n            goto fail;\n        JS_SetPropertyStr(ctx, *obj1, \"x\", *obj2);  // obj1 and obj2 may move\n        ret = *obj1;\n     fail:\n        PopGCRef(ctx, \u0026obj2_ref);\n        PopGCRef(ctx, \u0026obj1_ref);\n        return ret;\n}\n```\n\nWhen running on a PC, the `DEBUG_GC` define can be used to force the\nJS allocator to always move objects at each allocation. It is a good\nway to check no invalid JSValue is used.\n\n### Standard library\n\nThe standard library is compiled by a custom tool (`mquickjs_build.c`)\nto C structures that may reside in ROM. Hence the standard library\ninstantiation is very fast and requires almost no RAM. An example of\nstandard library for `mqjs` is provided in `mqjs_stdlib.c`. The result\nof its compilation is `mqjs_stdlib.h`.\n\n`example.c` is a complete example using the MQuickJS C API.\n\n### Persistent bytecode\n\nThe bytecode generated by `mqjs` may be executed from ROM. In this\ncase, it must be relocated before being flashed into ROM (see\n`JS_RelocateBytecode()`). It is then instantiated with\n`JS_LoadBytecode()` and run as normal script with `JS_Run()` (see\n`mqjs.c`).\n\nAs with QuickJS, no backward compatibility is guaranteed at the\nbytecode level. Moreover, the bytecode is not verified before being\nexecuted. Only run JavaScript bytecode from trusted sources.\n\n### Mathematical library and floating point emulation\n\nMQuickJS contains its own tiny mathematical library (in\n`libm.c`). Moreover, in case the CPU has no floating point support, it\ncontains its own floating point emulator which may be smaller than the\none provided with the GCC toolchain.\n\n## Internals and comparison with QuickJS\n\n### Garbage collection\n\nA tracing and compacting garbage collector is used instead of\nreference counting. It allows smaller objects. The GC adds an overhead\nof a few bits per allocated memory block. Moreover, memory\nfragmentation is avoided.\n\nThe engine has its own memory allocator and does not depend on the C\nlibrary malloc.\n\n### Value and object representation\n\nThe value has the same size as a CPU word (hence 32 bits on a 32 bit\nCPU). A value may contain:\n\n  - a 31 bit integer (1 bit tag)\n\n  - a single unicode codepoint (hence a string of one or two 16 bit code units)\n\n  - a 64 bit floating point number with a small exponent with 64 bit CPU words\n\n  - a pointer to a memory block. Memory blocks have a tag stored in\n    memory.\n\nJavaScript objects require at least 3 CPU words (hence 12 bytes on a\n32 bit CPU). Additional data may be allocated depending on the object\nclass. The properties are stored in a hash table. Each property\nrequires at least 3 CPU words. Properties may reside in ROM for\nstandard library objects.\n\nProperty keys are JSValues unlike QuickJS where they have a specific\ntype. They are either a string or a positive 31 bit integer. String\nproperty keys are internalized (unique).\n\nStrings are internally stored in WTF-8 (UTF-8 + unpaired surrogates)\ninstead of 8 or 16 bit arrays in QuickJS. Surrogate pairs are not\nstored explicitly but are still visible when iterating thru 16 bit\ncode units in JavaScript. Hence full compatibility with JavaScript and\nUTF-8 is maintained.\n\nC Functions can be stored as a single value to reduce the overhead. In\nthis case, no additional properties can be added. Most standard\nlibrary functions are stored this way.\n\n### Standard library\n\nThe whole standard library resides in ROM. It is generated at compile\ntime. Only a few objects are created in RAM. Hence the engine\ninstantiation time is very low.\n\n### Bytecode\n\nIt is a stack based bytecode (similar to QuickJS). However, the\nbytecode references atoms thru an indirect table.\n\nLine and column number information is compressed with \n[exponential-Golomb codes](https://en.wikipedia.org/wiki/Exponential-Golomb_coding).\n\n### Compilation\n\nThe parser is very close to the QuickJS one but it avoids recursion so\nthe C stack usage is bounded. There is no abstract syntax tree. The\nbytecode is generated in one pass with several tricks to optimize it\n(QuickJS has several optimization passes).\n\n## Tests and benchmarks\n\nRunning the basic tests:\n```sh\nmake test\n```\n\nRunning the QuickJS micro benchmark:\n```sh\nmake microbench\n```\n\nAdditional tests and a patched version of the Octane benchmark running\nin stricter mode can be downloaded\n[here](https://bellard.org/mquickjs/mquickjs-extras.tar.xz):\n\nRunning the V8 octane benchmark:\n```sh\nmake octane\n```\n\n## License\n\nMQuickJS is released under the MIT license.\n\nUnless otherwise specified, the MQuickJS sources are copyright Fabrice\nBellard and Charlie Gordon.\n\n","funding_links":[],"categories":["C","Scripting","前端开发框架及项目"],"sub_categories":["多工具库支持或纯JS"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbellard%2Fmquickjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbellard%2Fmquickjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbellard%2Fmquickjs/lists"}