feat(pkg): compat.quickjs-ng 0.17.0 (QuickJS-ng JavaScript engine) - #466
Merged
Merged
Conversation
The four engine TUs upstream builds as its library, with the flags upstream's CMake and meson builds set, and libm and the thread library on the linux link line because upstream makes them PUBLIC; quickjs-libc is not built. quickjs.h reaches consumers through a forwarder, so the engine's private headers stay off the include path. Linux only, plain-string url (no CN mirror). The member evaluates JavaScript and checks each compiled source file by value. The catalog row it joins loses a stray `|` that hid its last entry on GitHub. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
compat.quickjs-ng0.17.0, the QuickJS-ng JavaScript engine as an embeddable C library. The engine is MIT; one generated table it compiles in carries the Unicode License V3, solicenseslists both. Line numbers below are for the v0.17.0 tag.Shape
C-source compat, like
compat.xxhashandcompat.libaio. Upstream'sqjs_sources(dtoa.c, libregexp.c, libunicode.c, quickjs.c; CMakeLists.txt:273-278) are built into one lib. The descriptor has alinuxsection only and a plain-string url. A consumer writes#include <quickjs.h>.What is left out
quickjs-libc.c is not compiled. It is upstream's optional standard library: the std, os and bjson modules, which give scripts files, environment variables, timers, child processes and signal handlers. Upstream leaves it out of the library by default too. CMake adds it to libqjs only under QJS_BUILD_LIBC (meson: -Dlibc=true), and otherwise builds it as a separate static library for the qjs and qjsc programs, which it does not install. I use the engine embedded in a C++ host that runs scripts with no access to the host, and I think that is the right default for the base package. An embedder can add capabilities to a bare engine, but it cannot take quickjs-libc back out of a lib that already contains it. I have not tried carrying quickjs-libc as a feature.
Only quickjs.h reaches the consumer. The tarball keeps it at the root next to the engine's private headers, among them list.h, cutils.h and dtoa.h, and a consumer could easily have its own files with those names. Without quickjs-libc, upstream installs quickjs.h alone (CMakeLists.txt:557, meson.build:144-146 and 263). The descriptor does the same with a one-line forwarder in
generated_files, as compat.libaio does. The engine's own TUs include their headers in quote form next to the .c files and need no -I. The test member refuses to compile if cutils.h or libregexp.h becomes reachable, and I checked that this guard fires (see below).Flags
All four come from upstream's CMake and meson builds. They go through
cflags, so they reach this package's C TUs and not the consumer's. I confirmed this in the compile database: the test's C++ TU gets none of them.-std=gnu11. Upstream is C11 with GNU extensions (CMakeLists.txt:9-11, meson.build:6). The descriptor'sc_standarddoes not decide the -std on the package's compile line. Withc_standard = "gnu11"the line still has-std=c11, the same observation compat.libaio records, so the dialect is appended incflags, where the later -std wins, as compat.wamr does. The engine also builds with plain-std=c11, but I followed upstream rather than rely on that.-funsigned-char. CMakeLists.txt:109, meson.build:42, and /J for MSVC (meson.build:70). x86_64 and aarch64 Linux disagree on the sign of plain char, and upstream pins it so the engine behaves the same on both. quickjs.h passes char only through pointers, so consumers do not need the flag.-D_GNU_SOURCE. CMakeLists.txt:285 and meson.build:162, on every platform.-DQUICKJS_NG_BUILD. CMakeLists.txt:46, meson.build:19. quickjs.h reads it only for quickjs-libc's Windows export macro (quickjs.h:82), so it changes nothing on Linux today. I kept it so the engine's TUs see the same macros as in upstream's own build. Happy to drop it.There is no CONFIG_VERSION. That macro belongs to the original QuickJS. QuickJS-ng takes its version from quickjs.h (QJS_VERSION_*, quickjs.h:1458-1461), and the test checks JS_GetVersion() against those macros.
NDEBUG is not set, as in most descriptors here, in either the dev or the release profile. The engine therefore keeps its assertions and its debug-dump code (quickjs.c:84-86). Upstream's default build type is Release in both CMake and meson, which would define NDEBUG. quickjs.h does not read NDEBUG, so either choice only affects the library's internals. Tell me if you would rather have it on.
Link libraries
Upstream links libm and the thread library PUBLIC on Unix (CMakeLists.txt:291, 299-311; meson.build:133-136), and the v0.17.0 release notes include "Link against libm unconditionally on Unices" (quickjs-ng/quickjs#1699). quickjs.c calls into libm for Math, and cutils.h uses pthread_once, mutexes and condition variables. A C++ consumer never notices, because the C++ driver links libm for its own runtime. A consumer with no C++ in it is linked by the C driver, and there the link fails with undefined references to floor, round, lrint and the rest. So the linux section carries
ldflags = { "-lm", "-lpthread" }, as compat.libwebp and compat.wamr do. libdl is left out, because only quickjs-libc.c calls dlopen.Linux only
Built and run with llvm 22.1.8 on x86_64-linux-gnu, and in an openkal graph for x86_64-linux-gnu; details are below. I also compiled the four TUs and the test outside mcpp with gcc 16.2.1 and the same flags, at -O0 and -O2. There were no warnings and the test passed. That is not the index's gcc leg, which uses its own sysroot, so the linux default leg will still be this package's first real gcc build. Upstream supports macOS and Windows and its CI builds both. I have not built this package there, so those sections are not declared. The member gates the dependency with
cfg(linux), as libaio and wamr do.Licenses
The engine is MIT (LICENSE). libunicode.c compiles in libunicode-table.h, which is generated from the Unicode data files, and that file's header is the Unicode License V3 (SPDX
Unicode-3.0). A binary built from this package needs both notices, so both are listed.No CN mirror
I do not have
mcpp-reswrite access, sourlis the plain-string upstream form described in docs/cn-mirror.md. The tarball can be mirrored as it is, and the sha256 stays the same.Test member
tests/examples/quickjs-ngevaluates JavaScript and compares the resulting strings with values written out by hand from the specification. Each group needs a different compiled source file:.thenreaction must not run until the host drains the queue with JS_ExecutePendingJob.0.1 + 0.2,5e-324,1e21), plustoFixedand radix conversion.lastIndex.'straße'.toUpperCase(), NFC normalization, and\p{Script=Greek}.The test frees the runtime at the end. Because NDEBUG is unset, JS_FreeRuntime asserts that no object is still alive (quickjs.c:2699), so an object the test forgot to free aborts it.
I did not add the member to tests/openkal/members.toml. It runs there on x86_64 (below), so say the word if you want it measured.
Catalog entry
The entry goes after compat.xxhash in the "C-source compat" row of docs/descriptor-examples.md and its Chinese counterpart. That row has a stray
|before· compat.xxhash, which makes it three cells under a two-column header, and GitHub drops the third cell. compat.xxhash does not appear on the rendered page today, and the new entry would not either. I removed that|in both files and closed the row with|. The compat.sqlitecpp and compat.reflectcpp entries sit behind the same stray|in their rows. I left those alone to keep this PR to one package, and I can fix them here if you prefer.Verification
Run locally with mcpp 2026.9.21.3. validate.yml has since moved to 2026.9.25.1, which #465 says changes no descriptor grammar.
Lint: the per-file checks from validate.yml all pass for the new descriptor: Lua syntax, required fields, no leading
v, check_mirror_urls.lua, check_package_name.lua and the c++fly check. check_cross_package_refs.lua, check_platform_version_parity.lua, check_duplicate_versions.lua andcompat.py selftestpass for the whole tree.On a cold run the member fetched the tarball from the url in the descriptor. The fetched file matched the declared sha256 and was byte-identical to a separate download of the same url. With the build cache off:
It also passes with
--profile release, where the package's TUs build at -O2.The package's compile line for quickjs.c (include path shortened):
A C consumer, a project whose only source is
src/main.cand which therefore links through the C driver, evaluatesString(Math.pow(2, 10) + Math.round(Math.sin(0))). Without the ldflags its link stops atundefined symbol: round(then lrint, floor and more). With them it links and prints 1024.openkal: I made the member copy with tests/openkal/compat.py's own
prepare(), which adds openkal-llvm-runtime 0.15.1 and the[indices]redirect, and ran the commandcommand_for()produces,mcpp test --toolchain llvm@22.1.8:Before the ldflags were added, the same graph's aarch64-linux-musl target also passed under qemu-aarch64. With
-lmit no longer links, and the cause is not in this package. The graph passes no sysroot, so clang's driver appends the build host's library directories (-L/lib/../lib64 -L/usr/lib64 -L/lib -L/usr/lib) to the cross link. On my machine /usr/lib/libm.a is glibc's linker script,OUTPUT_FORMAT(elf64-x86-64) GROUP(/usr/lib/libm-2.44.a /usr/lib/libmvec.a), and lld stops withis incompatible with elf64-x86-64. The same clang 22.1.8 fails the same way when it links an empty aarch64 object with--target=aarch64-unknown-linux-musl -nostdlib -static -lm, so I expect any descriptor that passes -lm to fail there too. On x86_64 the link finds that same file, but lld extracts nothing from it (checked with --why-extract), because the graph's own libc objects already define every math function. tests/openkal/pins.toml measures x86_64 targets only, so CI does not see the aarch64 case. I reported the link-side cause as mcpp-community/mcpp#696.Negative check: I pointed
include_dirsback at the tarball root and moved the dialect toc_standard = "gnu11". The member then stops at its guard, and the compile line shows-std=c11:After I restored the descriptor, the member passed again.
How to reproduce
The C consumer:
Tarball: https://github.com/quickjs-ng/quickjs/archive/refs/tags/v0.17.0.tar.gz, sha256
559bc4c420475e55c7ab4510adbc562f55d7524d75e8e89d79ce4bb02f5687d9. Tag v0.17.0 is commit 6d46d07d04041b40f4f49eaa7fdebe44c314c699, released 2026-09-18.