From b5912ae2ccf16d0ec845e642f86c87f314ecfce1 Mon Sep 17 00:00:00 2001 From: theMackabu Date: Tue, 12 May 2026 00:56:17 -0700 Subject: [PATCH] migrate to skim for type stripping (saves 900kb) --- .github/versions.json | 7 --- .github/workflows/build-platform.yml | 12 ---- AGENTS.md | 3 +- ARCHITECTURE.md | 2 +- BUILDING.md | 14 ++--- CONTRIBUTING.md | 1 - README.md | 4 +- include/oxc.h | 22 -------- include/utils.h | 1 - libant/meson.build | 4 +- libant/scripts/bundle.sh | 1 - meson.build | 2 +- meson/deps/meson.build | 37 ++----------- src/esm/loader.c | 5 +- src/utils.c | 82 ++++++++++++++++++---------- vendor/skim.wrap | 4 ++ 16 files changed, 77 insertions(+), 124 deletions(-) delete mode 100644 include/oxc.h create mode 100644 vendor/skim.wrap diff --git a/.github/versions.json b/.github/versions.json index 9ddd093..2fac627 100644 --- a/.github/versions.json +++ b/.github/versions.json @@ -12,7 +12,6 @@ "os_type": "linux-glibc", "arch": "x86_64", "zig_target": "x86_64-linux-gnu", - "rust_target": "x86_64-unknown-linux-gnu", "artifact_name": "ant-linux-x64", "binary_name": "ant", "deps": [], @@ -24,7 +23,6 @@ "os_type": "linux-glibc", "arch": "aarch64", "zig_target": "aarch64-linux-gnu", - "rust_target": "aarch64-unknown-linux-gnu", "artifact_name": "ant-linux-aarch64", "binary_name": "ant", "deps": [], @@ -36,7 +34,6 @@ "os_type": "linux-musl", "arch": "x86_64", "zig_target": "x86_64-linux-musl", - "rust_target": "x86_64-unknown-linux-musl", "artifact_name": "ant-linux-x64-musl", "binary_name": "ant", "deps": ["zlib"], @@ -48,7 +45,6 @@ "os_type": "linux-musl", "arch": "aarch64", "zig_target": "aarch64-linux-musl", - "rust_target": "aarch64-unknown-linux-musl", "artifact_name": "ant-linux-aarch64-musl", "binary_name": "ant", "deps": ["zlib"], @@ -60,7 +56,6 @@ "os_type": "macos", "arch": "x86_64", "zig_target": "x86_64-macos", - "rust_target": "x86_64-apple-darwin", "artifact_name": "ant-darwin-x64", "binary_name": "ant", "deps": [], @@ -72,7 +67,6 @@ "os_type": "macos", "arch": "aarch64", "zig_target": "aarch64-macos", - "rust_target": "aarch64-apple-darwin", "artifact_name": "ant-darwin-aarch64", "binary_name": "ant", "deps": [], @@ -84,7 +78,6 @@ "os_type": "windows", "arch": "x86_64", "zig_target": "x86_64-windows-gnu", - "rust_target": "x86_64-pc-windows-gnu", "artifact_name": "ant-windows-x64", "binary_name": "ant.exe", "deps": [], diff --git a/.github/workflows/build-platform.yml b/.github/workflows/build-platform.yml index b6c02e8..0db3519 100644 --- a/.github/workflows/build-platform.yml +++ b/.github/workflows/build-platform.yml @@ -139,7 +139,6 @@ jobs: echo "os_type=$(echo $CONFIG | jq -r '.os_type')" >> $GITHUB_OUTPUT echo "arch=$(echo $CONFIG | jq -r '.arch')" >> $GITHUB_OUTPUT echo "zig_target=$(echo $CONFIG | jq -r '.zig_target')" >> $GITHUB_OUTPUT - echo "rust_target=$(echo $CONFIG | jq -r '.rust_target')" >> $GITHUB_OUTPUT echo "binary_name=$(echo $CONFIG | jq -r '.binary_name')" >> $GITHUB_OUTPUT echo "static_link=$(echo $CONFIG | jq -r '.static_link')" >> $GITHUB_OUTPUT echo "cmake_generator=$(echo $CONFIG | jq -r '.cmake_generator // empty')" >> $GITHUB_OUTPUT @@ -168,17 +167,6 @@ jobs: version: ${{ steps.config.outputs.llvm_version }} os_type: ${{ steps.config.outputs.os_type }} - # === SETUP RUST === - - name: Setup Rust - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ steps.config.outputs.rust_target }} - - - name: Cache Rust - uses: Swatinem/rust-cache@v2 - with: - workspaces: src/strip -> ../../build/oxc-target - # === BUILD NATIVE DEPS === - name: Build native dependencies uses: ./.github/actions/build-native-deps diff --git a/AGENTS.md b/AGENTS.md index 7ea1d96..5589a50 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,7 +35,8 @@ entire repository into context. - `src/gc/` contains heap layout, roots, strings, ropes, and collection logic. - `src/modules/` and `src/builtins/` implement built-in modules and host APIs. - `src/http/`, `src/net/`, and `src/streams/` are the transport and I/O stack. -- `src/pkg/` is the Zig package manager; `src/strip/` is the Rust type-stripper. +- `src/pkg/` is the Zig package manager; TypeScript stripping is provided by + the Skim Meson subproject. - `meson/` and `meson.build` define the build graph and generated headers. - `.github/agents/` contains the lightweight repo-harness checks and validation router used by local tasks and CI. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6be4dc7..3eae1d5 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -47,7 +47,7 @@ meant to answer "where should this change live?" before anyone starts editing. - `src/core/` stores TypeScript sources and runtime metadata that feed generation steps. - `src/pkg/` is the Zig package manager. -- `src/strip/` is the Rust type-stripper used during builds. +- TypeScript stripping is provided by the Skim Meson subproject. - `meson/` and the root [meson.build](meson.build) describe the build graph, dependency setup, and custom code generation targets. diff --git a/BUILDING.md b/BUILDING.md index ed20ae4..615a93d 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -83,7 +83,6 @@ The following tools are required to build Ant regardless of platform: - **[CMake](https://cmake.org/)** (for the tlsuv subproject) - **pkg-config** - **Node.js** >= 22 (used to generate the JS snapshot at build time) -- **[Rust](https://rustup.rs/)** toolchain (stable) with `cargo` (builds the OXC type-strip library) - **[Zig](https://ziglang.org/)** >= 0.15 (builds the package manager component) - **Git** @@ -141,12 +140,9 @@ Installation via package manager: util-linux-dev util-linux-static linux-headers libunwind-dev libunwind-static ``` -You will also need Rust and Zig installed. The recommended approach: +You will also need Zig installed. The recommended approach: ```bash -# Rust (via rustup) -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - # Zig (download from https://ziglang.org/download/) # Or via package manager if available ``` @@ -165,10 +161,10 @@ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh brew install meson ninja llvm node ``` -- Rust and Zig: +- Zig: ```bash - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh + # install 0.15.2 brew install zig ``` @@ -375,9 +371,7 @@ Ant on Windows is built using the MSYS2 MINGW64 toolchain. mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake \ mingw-w64-x86_64-lld mingw-w64-x86_64-nodejs git ``` -3. Install Rust via [rustup](https://rustup.rs/) (select the - `x86_64-pc-windows-gnu` target) -4. Install [Zig](https://ziglang.org/download/) +3. Install [Zig](https://ziglang.org/download/) #### Building Ant diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2790911..bfbafc6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,7 +75,6 @@ src/ ├── pkg/ # Zig-based package manager ├── silver/ # Silver bytecode compiler and VM │ └── ops/ # Bytecode operation definitions -├── strip/ # Rust-based type stripping (oxc) ├── tools/ # Code generation scripts (snapshot gen) ├── types/ # TypeScript type declarations include/ # C header files diff --git a/README.md b/README.md index fefdd6f..a6ee649 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@ Built to carry more than it weighs while delivering near-V8 speeds. ```bash $ ls -lh ant --rwxr-xr-x⠀9.0M⠀ant* +-rwxr-xr-x⠀8.7M⠀ant* # built with -Os --rwxr-xr-x⠀6.5M⠀ant* +-rwxr-xr-x⠀5.9M⠀ant* ``` ## Table of contents diff --git a/include/oxc.h b/include/oxc.h deleted file mode 100644 index 48acd98..0000000 --- a/include/oxc.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef OXC_STRIP_H -#define OXC_STRIP_H - -#include - -#define OXC_ERR_NULL_INPUT -1 -#define OXC_ERR_INVALID_UTF8 -2 -#define OXC_ERR_PARSE_FAILED -3 -#define OXC_ERR_TRANSFORM_FAILED -4 -#define OXC_ERR_OUTPUT_TOO_LARGE -5 - -char *OXC_strip_types_owned( - const char *input, - const char *filename, - int is_module, - size_t *out_len, - int *out_error, - char *error_output, - size_t error_output_len -); - -#endif diff --git a/include/utils.h b/include/utils.h index 89ca10b..70fa8f8 100644 --- a/include/utils.h +++ b/include/utils.h @@ -38,7 +38,6 @@ int strip_typescript_inplace( char **buffer, size_t len, const char *filename, - int is_module, size_t *out_len, const char **error_detail ); diff --git a/libant/meson.build b/libant/meson.build index d4ed328..c20f8d3 100644 --- a/libant/meson.build +++ b/libant/meson.build @@ -33,7 +33,7 @@ libant_core = static_library( 'ant_core', lib_sources + [snapshot_h, messages_h], include_directories: include, - dependencies: ant_deps + [oxc_dep], + dependencies: ant_deps, ) if use_lto @@ -41,7 +41,7 @@ if use_lto 'ant_core_lto', lib_sources + [snapshot_h, messages_h], include_directories: include, - dependencies: ant_deps + [oxc_dep], + dependencies: ant_deps, c_args: ['-flto'], ) endif diff --git a/libant/scripts/bundle.sh b/libant/scripts/bundle.sh index d3f09ba..cbcfffa 100755 --- a/libant/scripts/bundle.sh +++ b/libant/scripts/bundle.sh @@ -19,7 +19,6 @@ bundle_lib() { ! -name 'libant.a' \ ! -name 'libant-lto.a' \ ! -name 'libpkg.a' \ - ! -path '*/oxc-target/release/deps/*' \ ! -path '*/.external/*' \ 2>/dev/null | grep -E -v "$EXCLUDE" | sort -u) diff --git a/meson.build b/meson.build index 3dc0f9d..a8e259a 100644 --- a/meson.build +++ b/meson.build @@ -81,7 +81,7 @@ pkg_dep = declare_dependency( libant_dep = declare_dependency( link_with: libant, include_directories: include, - dependencies: ant_deps + [oxc_dep, pkg_dep] + dependencies: ant_deps + [pkg_dep] ) link_args = [] diff --git a/meson/deps/meson.build b/meson/deps/meson.build index 536f754..bcf6f72 100644 --- a/meson/deps/meson.build +++ b/meson/deps/meson.build @@ -155,42 +155,17 @@ libffi_dep = subproject('libffi', default_options: [ ]).get_variable('ffi_dep') pcre2_dep = subproject('pcre2', default_options: [ - 'optimization=s', + 'optimization=3', 'warning_level=0', 'grep=false', 'test=false' ]).get_variable('libpcre2_8') -cargo = find_program('cargo', required: true) -cp = find_program('cp', required: true) - -oxc_lib_name = 'liboxc.a' -oxc_output_name = 'liboxc.a' - -if host_machine.system() == 'windows' - rust_target = 'x86_64-pc-windows-gnu' - oxc_release_dir = meson.project_build_root() / 'oxc-target' / rust_target / 'release' - rust_target_arg = ' --target ' + rust_target -else - oxc_release_dir = meson.project_build_root() / 'oxc-target' / 'release' - rust_target_arg = '' -endif - -oxc_lib = custom_target( - 'oxc_strip', - output: oxc_output_name, - command: [ - 'sh', '-c', - '"' + cargo.full_path() + '"' + ' build --release' + rust_target_arg + ' ' + - '--manifest-path "' + src_root / 'src' / 'strip' / 'Cargo.toml' + '" ' + - '--target-dir "' + meson.project_build_root() / 'oxc-target' + '"' + - ' && "' + cp.full_path() + '" "' + oxc_release_dir / oxc_lib_name + '" @OUTPUT@' - ], - build_by_default: true, - build_always_stale: true -) +skim_dep = subproject('skim', default_options: [ + 'optimization=3', + 'default_library=static', +]).get_variable('skim_dep') -oxc_dep = declare_dependency(link_with: oxc_lib) zig = find_program('zig', required: true) deps_info = { @@ -241,7 +216,7 @@ ant_deps = [ uriparser_dep, utf8proc_dep, ssl_dep, crypto_dep, zlib_dep, brotli_common_dep, brotli_dec_dep, brotli_enc_dep, uthash_dep, lmdb_dep, wamr_dep, - double_conversion_dep, wirecall, + double_conversion_dep, wirecall, skim_dep, ] + win_deps if get_option('jit') diff --git a/src/esm/loader.c b/src/esm/loader.c index cd2d3d0..5f86e66 100644 --- a/src/esm/loader.c +++ b/src/esm/loader.c @@ -1213,8 +1213,7 @@ static ant_value_t esm_load_module(ant_t *js, esm_module_t *mod) { if (!mod->embedded_code) { int strip_result = strip_typescript_inplace( - &content, size, mod->resolved_path, - mod->format != MODULE_EVAL_FORMAT_CJS, + &content, size, mod->resolved_path, &js_len, &strip_detail ); @@ -1223,8 +1222,10 @@ static ant_value_t esm_load_module(ant_t *js, esm_module_t *mod) { js, "TypeScript error: strip failed (%d): %s", strip_result, strip_detail ); + free(content); mod->is_loading = false; + return err; }} diff --git a/src/utils.c b/src/utils.c index 93c7f08..4122987 100644 --- a/src/utils.c +++ b/src/utils.c @@ -1,12 +1,12 @@ #include "utils.h" #include "messages.h" -#include +#include #include -#include +#include #include +#include #include -#include #ifdef _WIN32 #include @@ -21,6 +21,21 @@ const char *const module_resolve_extensions[] = { ".json", ".node", NULL }; +static _Thread_local skim_context_t ts_strip_context; +static _Thread_local bool ts_strip_context_ready; + +static int ensure_ts_strip_context(const char **error_detail) { + if (ts_strip_context_ready) return 0; + + if (skim_context_init(&ts_strip_context) != 0) { + if (error_detail) *error_detail = "out of memory while initializing TypeScript stripper"; + return SKIM_ERR_TRANSFORM_FAILED; + } + + ts_strip_context_ready = true; + return 0; +} + static const char *ant_home_dir(void) { #ifdef _WIN32 const char *home = getenv("USERPROFILE"); @@ -278,11 +293,8 @@ int is_typescript_file(const char *filename) { } int strip_typescript_inplace( - char **buffer, - size_t len, - const char *filename, - int is_module, - size_t *out_len, + char **buffer, size_t len, + const char *filename, size_t *out_len, const char **error_detail ) { if (out_len) *out_len = len; @@ -291,18 +303,23 @@ int strip_typescript_inplace( if (!buffer || !*buffer) { if (error_detail) *error_detail = "null input/output passed"; - return OXC_ERR_NULL_INPUT; + return SKIM_ERR_NULL_INPUT; } char *input = *buffer; char error_buf[256] = {0}; size_t stripped_len = 0; - - int strip_error = OXC_ERR_TRANSFORM_FAILED; - char *stripped = OXC_strip_types_owned( - input, filename, is_module, - &stripped_len, &strip_error, - error_buf, sizeof(error_buf) + + int init_result = ensure_ts_strip_context(error_detail); + if (init_result < 0) return init_result; + + skim_context_reset(&ts_strip_context); + skim_error_t strip_error = SKIM_ERR_TRANSFORM_FAILED; + + const char *stripped = skim_strip_typescript_borrowed( + &ts_strip_context, input, len, filename, + SKIM_SOURCE_AUTO, NULL, + &stripped_len, &strip_error, error_buf, sizeof(error_buf) ); if (!stripped) { @@ -312,27 +329,24 @@ int strip_typescript_inplace( memcpy(input, error_buf, copy_len); input[copy_len] = '\0'; } else input[0] = '\0'; - - if (error_detail) { - *error_detail = input[0] != '\0' ? input : "unknown strip error"; - } - return strip_error; + if (error_detail) + *error_detail = input[0] != '\0' + ? input : "unknown strip error"; + + return (int)strip_error; } char *next = realloc(input, stripped_len + 1); if (!next) { - free(stripped); if (error_detail) *error_detail = "out of memory while resizing strip output buffer"; - return OXC_ERR_OUTPUT_TOO_LARGE; + return SKIM_ERR_OUTPUT_TOO_LARGE; } memcpy(next, stripped, stripped_len + 1); - free(stripped); - *buffer = next; if (out_len) *out_len = stripped_len; - + return 0; } @@ -432,11 +446,19 @@ char *resolve_typescript_source_fallback(const char *filename) { } typedef struct { - const char *repl; size_t repl_len; size_t *ri; - const char *matched; size_t matched_len; - const char *str; size_t str_len; size_t position; - const repl_capture_t *caps; int ncaptures; - char **buf; size_t *buf_len; size_t *buf_cap; + const char *repl; + size_t repl_len; + size_t *ri; + const char *matched; + size_t matched_len; + const char *str; + size_t str_len; + size_t position; + const repl_capture_t *caps; + int ncaptures; + char **buf; + size_t *buf_len; + size_t *buf_cap; } rt_ctx_t; static bool rt_append(rt_ctx_t *c, const char *data, size_t dlen) { diff --git a/vendor/skim.wrap b/vendor/skim.wrap new file mode 100644 index 0000000..a3b0851 --- /dev/null +++ b/vendor/skim.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/themackabu/skim.git +revision = head +depth = 1 \ No newline at end of file -- 2.51.2