@mikrojs/native 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CMakeLists.txt +198 -0
- package/LICENSE +21 -0
- package/README.md +49 -0
- package/cmake/mikrojs_bytecode.cmake +146 -0
- package/cmake.js +22 -0
- package/dist/index.d.ts +52 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +132 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/include/byteorder_apple.h +11 -0
- package/include/byteorder_windows.h +12 -0
- package/include/mikrojs/cbor_helpers.h +24 -0
- package/include/mikrojs/cutils_wrap.h +59 -0
- package/include/mikrojs/errors.h +144 -0
- package/include/mikrojs/mem.h +11 -0
- package/include/mikrojs/mik_color.h +32 -0
- package/include/mikrojs/mikrojs.h +331 -0
- package/include/mikrojs/platform.h +82 -0
- package/include/mikrojs/private.h +281 -0
- package/include/mikrojs/utils.h +125 -0
- package/package.json +100 -0
- package/prebuilds/darwin-arm64/mikrojs.napi.node +0 -0
- package/prebuilds/linux-arm64/mikrojs.napi.node +0 -0
- package/prebuilds/linux-x64/mikrojs.napi.node +0 -0
- package/runtime/ble/ble.ts +231 -0
- package/runtime/ble/types.ts +194 -0
- package/runtime/ble/uuid.ts +89 -0
- package/runtime/ble/validators.ts +61 -0
- package/runtime/cbor/cbor.ts +1 -0
- package/runtime/cbor/types.ts +8 -0
- package/runtime/console/types.ts +50 -0
- package/runtime/env/env.ts +17 -0
- package/runtime/env/types.ts +12 -0
- package/runtime/format/types.ts +4 -0
- package/runtime/fs/fs.ts +93 -0
- package/runtime/fs/types.ts +92 -0
- package/runtime/globals.d.ts +87 -0
- package/runtime/http/helpers.ts +222 -0
- package/runtime/http/native.ts +151 -0
- package/runtime/http/request.ts +25 -0
- package/runtime/i2c/i2c.ts +35 -0
- package/runtime/i2c/types.ts +55 -0
- package/runtime/inspect/types.ts +10 -0
- package/runtime/internal.d.ts +456 -0
- package/runtime/kv/nvs.ts +17 -0
- package/runtime/kv/rtc.ts +17 -0
- package/runtime/kv/shared.ts +107 -0
- package/runtime/kv/types.ts +150 -0
- package/runtime/neopixel/neopixel.ts +38 -0
- package/runtime/neopixel/types.ts +27 -0
- package/runtime/pin/pin.ts +51 -0
- package/runtime/pin/types.ts +49 -0
- package/runtime/pwm/pwm.ts +32 -0
- package/runtime/pwm/types.ts +29 -0
- package/runtime/reader/reader.ts +167 -0
- package/runtime/reader/types.ts +34 -0
- package/runtime/result/native-result.node-shim.ts +44 -0
- package/runtime/result/result.ts +26 -0
- package/runtime/result/types.ts +60 -0
- package/runtime/schema/schema.ts +321 -0
- package/runtime/schema/types.ts +152 -0
- package/runtime/sleep/sleep.ts +14 -0
- package/runtime/sleep/types.ts +44 -0
- package/runtime/sntp/sntp.ts +54 -0
- package/runtime/sntp/types.ts +38 -0
- package/runtime/spi/spi.ts +31 -0
- package/runtime/spi/types.ts +42 -0
- package/runtime/stdio/stdio.ts +44 -0
- package/runtime/stdio/types.ts +22 -0
- package/runtime/stream/stream.ts +150 -0
- package/runtime/stream/types.ts +47 -0
- package/runtime/sys/sys.ts +90 -0
- package/runtime/sys/types.ts +131 -0
- package/runtime/test/test.ts +595 -0
- package/runtime/test/types.ts +97 -0
- package/runtime/uart/types.ts +75 -0
- package/runtime/uart/uart.ts +51 -0
- package/runtime/wifi/types.ts +156 -0
- package/runtime/wifi/wifi.ts +208 -0
- package/scripts/bundle-runtime.js +149 -0
- package/scripts/compare-minifiers.js +189 -0
- package/scripts/compile-bytecode.sh +38 -0
- package/scripts/copy-prebuild.js +20 -0
- package/scripts/generate-symbol-map.js +146 -0
- package/src/builtins.cpp +82 -0
- package/src/cutils_compat.c +38 -0
- package/src/eval_bytecode.cpp +42 -0
- package/src/fs.cpp +878 -0
- package/src/mem.cpp +63 -0
- package/src/mik_abort.cpp +160 -0
- package/src/mik_app_config.cpp +358 -0
- package/src/mik_cbor.cpp +334 -0
- package/src/mik_color.cpp +46 -0
- package/src/mik_console.cpp +422 -0
- package/src/mik_inspect.cpp +850 -0
- package/src/mik_repl.cpp +1122 -0
- package/src/mik_result.cpp +344 -0
- package/src/mik_stdio.cpp +147 -0
- package/src/mik_sys.cpp +239 -0
- package/src/mik_text_encoding.cpp +443 -0
- package/src/mikrojs.cpp +942 -0
- package/src/modules.cpp +944 -0
- package/src/platform_posix.cpp +134 -0
- package/src/timers.cpp +208 -0
- package/src/utils.cpp +173 -0
package/CMakeLists.txt
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.20)
|
|
2
|
+
project(mikrojs LANGUAGES C CXX)
|
|
3
|
+
|
|
4
|
+
set(CMAKE_C_STANDARD 11)
|
|
5
|
+
set(CMAKE_CXX_STANDARD 23)
|
|
6
|
+
set(CMAKE_C_STANDARD_REQUIRED ON)
|
|
7
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
8
|
+
|
|
9
|
+
# ── Resolve @mikrojs/quickjs via Node.js ─────────────────────────────
|
|
10
|
+
execute_process(
|
|
11
|
+
COMMAND node -e "import('@mikrojs/quickjs').then(m=>process.stdout.write(m.cmakePath))"
|
|
12
|
+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
|
13
|
+
OUTPUT_VARIABLE QUICKJS_CMAKE_PATH
|
|
14
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
15
|
+
RESULT_VARIABLE _QUICKJS_RESOLVE_RESULT
|
|
16
|
+
)
|
|
17
|
+
if(NOT _QUICKJS_RESOLVE_RESULT EQUAL 0)
|
|
18
|
+
message(FATAL_ERROR "Failed to resolve @mikrojs/quickjs. Run pnpm install first.")
|
|
19
|
+
endif()
|
|
20
|
+
|
|
21
|
+
include("${QUICKJS_CMAKE_PATH}")
|
|
22
|
+
|
|
23
|
+
# qjsc is built by @mikrojs/quickjs postinstall during pnpm install
|
|
24
|
+
if(NOT EXISTS "${QJSC_EXECUTABLE}")
|
|
25
|
+
message(FATAL_ERROR "qjsc not found at ${QJSC_EXECUTABLE}. Run 'pnpm install' first.")
|
|
26
|
+
endif()
|
|
27
|
+
|
|
28
|
+
# ── mikrojs static library ──────────────────────────────────────────
|
|
29
|
+
# Core source files shared between standalone lib and ESP-IDF builds.
|
|
30
|
+
# platform_posix.cpp is only used in the standalone build (ESP-IDF uses platform_esp32.cpp).
|
|
31
|
+
set(MIKROJS_CORE_SOURCES
|
|
32
|
+
src/cutils_compat.c
|
|
33
|
+
src/mikrojs.cpp
|
|
34
|
+
src/modules.cpp
|
|
35
|
+
src/builtins.cpp
|
|
36
|
+
src/timers.cpp
|
|
37
|
+
src/fs.cpp
|
|
38
|
+
src/mem.cpp
|
|
39
|
+
src/utils.cpp
|
|
40
|
+
src/eval_bytecode.cpp
|
|
41
|
+
src/mik_inspect.cpp
|
|
42
|
+
src/mik_stdio.cpp
|
|
43
|
+
src/mik_text_encoding.cpp
|
|
44
|
+
src/mik_color.cpp
|
|
45
|
+
src/mik_abort.cpp
|
|
46
|
+
src/mik_cbor.cpp
|
|
47
|
+
src/mik_result.cpp
|
|
48
|
+
src/mik_console.cpp
|
|
49
|
+
src/mik_sys.cpp
|
|
50
|
+
src/mik_repl.cpp
|
|
51
|
+
src/mik_app_config.cpp
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
add_library(mikrojs STATIC
|
|
55
|
+
${MIKROJS_CORE_SOURCES}
|
|
56
|
+
src/platform_posix.cpp
|
|
57
|
+
deps/nanocbor/src/encoder.c
|
|
58
|
+
deps/nanocbor/src/decoder.c
|
|
59
|
+
)
|
|
60
|
+
set_target_properties(mikrojs PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
61
|
+
|
|
62
|
+
target_include_directories(mikrojs PUBLIC
|
|
63
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/include"
|
|
64
|
+
)
|
|
65
|
+
target_include_directories(mikrojs PRIVATE
|
|
66
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/deps/nanocbor/include"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# nanocbor defaults to <endian.h> (glibc). Apple SDKs and MSVC don't ship
|
|
70
|
+
# it, so route them to per-platform shims that map htobe*/be*toh onto
|
|
71
|
+
# whatever native intrinsics the toolchain provides.
|
|
72
|
+
if(APPLE)
|
|
73
|
+
target_compile_definitions(mikrojs PRIVATE "NANOCBOR_BYTEORDER_HEADER=\"byteorder_apple.h\"")
|
|
74
|
+
elseif(WIN32)
|
|
75
|
+
target_compile_definitions(mikrojs PRIVATE "NANOCBOR_BYTEORDER_HEADER=\"byteorder_windows.h\"")
|
|
76
|
+
endif()
|
|
77
|
+
|
|
78
|
+
# ── Generated bytecode headers ────────────────────────────────────
|
|
79
|
+
include(cmake/mikrojs_bytecode.cmake)
|
|
80
|
+
mikrojs_generate_bytecode(
|
|
81
|
+
RUNTIME_DIR "${CMAKE_CURRENT_SOURCE_DIR}/runtime"
|
|
82
|
+
MODULES cbor env result schema fs http/helpers http/request i2c kv/nvs kv/rtc kv/shared neopixel pin pwm reader sleep spi sntp stdio stream sys test uart wifi
|
|
83
|
+
MODULE_PREFIX "mikrojs"
|
|
84
|
+
SYMBOL_PREFIX "mikrojs"
|
|
85
|
+
TARGET gen_bytecode
|
|
86
|
+
)
|
|
87
|
+
add_dependencies(mikrojs gen_bytecode)
|
|
88
|
+
target_include_directories(mikrojs PRIVATE "${gen_bytecode_INCLUDE_DIR}")
|
|
89
|
+
|
|
90
|
+
target_link_libraries(mikrojs PUBLIC quickjs)
|
|
91
|
+
|
|
92
|
+
# Note: self-registering native modules need force-include linker flags (-u symbol)
|
|
93
|
+
# to prevent stripping from static libraries. These are added by consumers:
|
|
94
|
+
# - ESP-IDF firmware: mikrojs_force_include_modules() in firmware CMakeLists
|
|
95
|
+
# - Host tests: target_link_options on mikrojs_tests below
|
|
96
|
+
|
|
97
|
+
# Suppress warnings from QuickJS headers in our code. MSVC uses /W3 by default
|
|
98
|
+
# and doesn't understand the -W flags. The dead-stripping flags below are
|
|
99
|
+
# similarly GCC/Clang-only; MSVC's linker dead-strips by default with /OPT:REF.
|
|
100
|
+
if(NOT MSVC)
|
|
101
|
+
target_compile_options(mikrojs PRIVATE -Wall -Wextra -Wno-unused-parameter)
|
|
102
|
+
# Emit per-function/data sections so the linker can dead-strip unreferenced
|
|
103
|
+
# symbols at executable link time. This matches ESP-IDF's default toolchain
|
|
104
|
+
# flags and lets us measure flash-size effects of source-level changes
|
|
105
|
+
# (e.g. intrinsic stripping) on the host build.
|
|
106
|
+
target_compile_options(mikrojs PRIVATE -ffunction-sections -fdata-sections)
|
|
107
|
+
endif()
|
|
108
|
+
|
|
109
|
+
# Version metadata for sys.version()
|
|
110
|
+
execute_process(
|
|
111
|
+
COMMAND node -e "import('../../../package.json',{with:{type:'json'}}).then(m=>process.stdout.write(m.default.version))"
|
|
112
|
+
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
|
113
|
+
OUTPUT_VARIABLE _MIK_VERSION
|
|
114
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
115
|
+
RESULT_VARIABLE _MIK_VERSION_RESULT
|
|
116
|
+
)
|
|
117
|
+
if(NOT _MIK_VERSION_RESULT EQUAL 0 OR _MIK_VERSION STREQUAL "")
|
|
118
|
+
message(FATAL_ERROR "Failed to resolve package version for MIK_FW_VERSION. Check that package.json exists at the workspace root.")
|
|
119
|
+
endif()
|
|
120
|
+
target_compile_definitions(mikrojs PRIVATE "MIK_FW_VERSION=\"${_MIK_VERSION}\"")
|
|
121
|
+
|
|
122
|
+
# UTC build timestamp. `string(TIMESTAMP ... UTC)` honors SOURCE_DATE_EPOCH
|
|
123
|
+
# when set (for reproducible builds). Refreshes on re-configure only, not
|
|
124
|
+
# every build — coarse enough for sys.firmware.date, which is a sanity
|
|
125
|
+
# fence for clock-synced checks, not a precise build identifier.
|
|
126
|
+
string(TIMESTAMP _MIK_BUILD_DATE_UTC "%Y-%m-%dT%H:%M:%SZ" UTC)
|
|
127
|
+
target_compile_definitions(mikrojs PRIVATE "MIK_BUILD_DATE_UTC=\"${_MIK_BUILD_DATE_UTC}\"")
|
|
128
|
+
|
|
129
|
+
# ── Exported variables for ESP-IDF consumers ─────────────────────────
|
|
130
|
+
# ESP-IDF components can't use CMake targets, so export source/include paths.
|
|
131
|
+
# Only set PARENT_SCOPE when included as a subdirectory (avoids warnings in standalone builds).
|
|
132
|
+
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|
133
|
+
# Prefix each core source with the full path for PARENT_SCOPE export
|
|
134
|
+
set(MIKROJS_SOURCES "")
|
|
135
|
+
foreach(_src ${MIKROJS_CORE_SOURCES})
|
|
136
|
+
list(APPEND MIKROJS_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/${_src}")
|
|
137
|
+
endforeach()
|
|
138
|
+
set(MIKROJS_SOURCES ${MIKROJS_SOURCES} PARENT_SCOPE)
|
|
139
|
+
set(MIKROJS_NANOCBOR_DIR "${CMAKE_CURRENT_SOURCE_DIR}/deps/nanocbor" PARENT_SCOPE)
|
|
140
|
+
set(MIKROJS_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include" PARENT_SCOPE)
|
|
141
|
+
set(MIKROJS_SCRIPTS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/scripts" PARENT_SCOPE)
|
|
142
|
+
set(MIKROJS_RUNTIME_DIR "${CMAKE_CURRENT_SOURCE_DIR}/runtime" PARENT_SCOPE)
|
|
143
|
+
endif()
|
|
144
|
+
|
|
145
|
+
# ── Tests ────────────────────────────────────────────────────────────
|
|
146
|
+
if(BUILD_TESTING)
|
|
147
|
+
enable_testing()
|
|
148
|
+
|
|
149
|
+
add_executable(mikrojs_tests
|
|
150
|
+
test/main.cpp
|
|
151
|
+
test/runtime_test.cpp
|
|
152
|
+
test/modules_test.cpp
|
|
153
|
+
test/text_encoding_test.cpp
|
|
154
|
+
test/cbor_test.cpp
|
|
155
|
+
test/abort_test.cpp
|
|
156
|
+
test/repl_protocol_test.cpp
|
|
157
|
+
test/app_config_test.cpp
|
|
158
|
+
test/oom_test.cpp
|
|
159
|
+
test/reader_test.cpp
|
|
160
|
+
test/stream_test.cpp
|
|
161
|
+
test/runtime_recycle_test.cpp
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
target_link_libraries(mikrojs_tests PRIVATE mikrojs)
|
|
165
|
+
target_include_directories(mikrojs_tests PRIVATE
|
|
166
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/test"
|
|
167
|
+
"${CMAKE_CURRENT_SOURCE_DIR}/deps/nanocbor/include"
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
include(CTest)
|
|
171
|
+
add_test(NAME mikrojs_tests COMMAND mikrojs_tests)
|
|
172
|
+
|
|
173
|
+
# native_stubs registers no-op `native:*` modules so the bench can load
|
|
174
|
+
# ESP-only builtins (wifi, fetch, kv, …) on the host. Compiled into the
|
|
175
|
+
# executable directly so its self-registering constructors aren't
|
|
176
|
+
# dead-stripped (no -u flags needed).
|
|
177
|
+
add_executable(memory_bench test/memory_bench.cpp test/native_stubs.cpp)
|
|
178
|
+
target_link_libraries(memory_bench PRIVATE mikrojs)
|
|
179
|
+
# Run the bench as a smoke test so module-load regressions (e.g. a
|
|
180
|
+
# builtin that imports an unregistered native module on host) surface
|
|
181
|
+
# in `pnpm test:lib` / `pnpm check` rather than only in the CI
|
|
182
|
+
# memory-bench workflow. Output is discarded; we only assert it exits 0.
|
|
183
|
+
add_test(NAME memory_bench COMMAND memory_bench)
|
|
184
|
+
set_tests_properties(memory_bench PROPERTIES
|
|
185
|
+
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
|
186
|
+
|
|
187
|
+
add_executable(bundle_compare test/bundle_compare.cpp)
|
|
188
|
+
target_link_libraries(bundle_compare PRIVATE mikrojs)
|
|
189
|
+
# Dead-strip unreferenced code at link time. Used for measuring the
|
|
190
|
+
# binary-size impact of source-level changes (intrinsic drops, etc.).
|
|
191
|
+
# Applied only to memory_bench to avoid interfering with doctest's
|
|
192
|
+
# static-initializer registration in mikrojs_tests.
|
|
193
|
+
if(APPLE)
|
|
194
|
+
target_link_options(memory_bench PRIVATE -Wl,-dead_strip)
|
|
195
|
+
else()
|
|
196
|
+
target_link_options(memory_bench PRIVATE -Wl,--gc-sections)
|
|
197
|
+
endif()
|
|
198
|
+
endif()
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Bjørge Næss
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @mikrojs/native
|
|
2
|
+
|
|
3
|
+
Standalone, platform-independent C++ runtime library for mikrojs, powered by QuickJS-NG. Zero ESP-IDF dependencies — runs on any POSIX host for development and testing, and on ESP32 via a thin platform adapter.
|
|
4
|
+
|
|
5
|
+
## Directory structure
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
include/ Public C/C++ headers (mikrojs.h, platform.h, private.h, …)
|
|
9
|
+
src/ C/C++ source files (runtime, modules, timers, REPL, …)
|
|
10
|
+
runtime/ TypeScript runtime modules bundled to bytecode at build time
|
|
11
|
+
addon/ Node-API addon exposing the runtime to Node.js
|
|
12
|
+
scripts/ Build scripts (esbuild bundling, qjsc bytecode compilation)
|
|
13
|
+
test/ Host-side C++ tests (Unity, run via ctest)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Build
|
|
17
|
+
|
|
18
|
+
```sh
|
|
19
|
+
# Standalone library (host)
|
|
20
|
+
cmake -B build && cmake --build build
|
|
21
|
+
|
|
22
|
+
# Run C++ tests
|
|
23
|
+
ctest --test-dir build --output-on-failure
|
|
24
|
+
|
|
25
|
+
# Node addon
|
|
26
|
+
pnpm run build:native
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Architecture
|
|
30
|
+
|
|
31
|
+
The runtime abstracts platform-specific operations via `MIKPlatform` (defined in `include/mikrojs/platform.h`). A default POSIX implementation is provided in `src/platform_posix.cpp`. The ESP32 adapter in `packages/@mikrojs/firmware/components/mikrojs/` supplies an ESP-IDF implementation.
|
|
32
|
+
|
|
33
|
+
### Runtime modules
|
|
34
|
+
|
|
35
|
+
TypeScript modules in `runtime/` are the JS-facing APIs (fetch, pin, wifi, etc.). During each CMake build they are:
|
|
36
|
+
|
|
37
|
+
1. Bundled with esbuild (`scripts/bundle-runtime.js`)
|
|
38
|
+
2. Compiled to bytecode with qjsc (`scripts/compile-bytecode.sh`)
|
|
39
|
+
3. Included as C headers in `src/builtins.cpp`
|
|
40
|
+
|
|
41
|
+
Type-checked separately via `tsconfig.runtime.json`:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
tsc --noEmit -p tsconfig.runtime.json
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Node addon
|
|
48
|
+
|
|
49
|
+
The `addon/` directory contains a Node-API binding that wraps the C++ runtime for use from Node.js/TypeScript. See [`addon/README.md`](addon/README.md).
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# mikrojs_generate_bytecode() — Reusable CMake function for compiling TypeScript
|
|
2
|
+
# runtime modules to QuickJS bytecode headers.
|
|
3
|
+
#
|
|
4
|
+
# Used by the core runtime, ESP-IDF component, and board/driver packages.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# mikrojs_generate_bytecode(
|
|
8
|
+
# RUNTIME_DIR <path> # Directory containing <mod>/<mod>.ts files
|
|
9
|
+
# MODULES <mod1> <mod2> # Module names to compile
|
|
10
|
+
# MODULE_PREFIX <prefix> # Module name prefix (e.g. "mikrojs" -> "mikrojs/pin")
|
|
11
|
+
# SYMBOL_PREFIX <prefix> # C symbol prefix (e.g. "mikrojs" -> "mikrojs_pin_bytecode")
|
|
12
|
+
# TARGET <name> # Custom target name (default: gen_bytecode)
|
|
13
|
+
# WORKING_DIRECTORY <dir> # Working dir for esbuild (default: CMAKE_CURRENT_SOURCE_DIR)
|
|
14
|
+
# )
|
|
15
|
+
#
|
|
16
|
+
# After calling, the following are set in the caller's scope:
|
|
17
|
+
# ${TARGET}_HEADERS — list of generated .h file paths
|
|
18
|
+
# ${TARGET}_GEN_DIR — directory containing the generated headers (include this)
|
|
19
|
+
|
|
20
|
+
include_guard(GLOBAL)
|
|
21
|
+
|
|
22
|
+
# Resolve paths relative to this file (inside @mikrojs/native).
|
|
23
|
+
# Use CACHE so the path is available across all components that include this file.
|
|
24
|
+
get_filename_component(_MIK_BC_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
|
|
25
|
+
set(_MIK_BC_SCRIPTS_DIR "${_MIK_BC_CMAKE_DIR}/../scripts" CACHE INTERNAL "")
|
|
26
|
+
|
|
27
|
+
function(mikrojs_generate_bytecode)
|
|
28
|
+
cmake_parse_arguments(ARG "" "RUNTIME_DIR;MODULE_PREFIX;SYMBOL_PREFIX;TARGET;WORKING_DIRECTORY" "MODULES" ${ARGN})
|
|
29
|
+
|
|
30
|
+
# Defaults
|
|
31
|
+
if(NOT ARG_TARGET)
|
|
32
|
+
set(ARG_TARGET "gen_bytecode")
|
|
33
|
+
endif()
|
|
34
|
+
if(NOT ARG_WORKING_DIRECTORY)
|
|
35
|
+
set(ARG_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
36
|
+
endif()
|
|
37
|
+
|
|
38
|
+
# Validate required args
|
|
39
|
+
if(NOT ARG_RUNTIME_DIR)
|
|
40
|
+
message(FATAL_ERROR "mikrojs_generate_bytecode: RUNTIME_DIR is required")
|
|
41
|
+
endif()
|
|
42
|
+
if(NOT ARG_MODULES)
|
|
43
|
+
message(FATAL_ERROR "mikrojs_generate_bytecode: MODULES is required")
|
|
44
|
+
endif()
|
|
45
|
+
if(NOT ARG_MODULE_PREFIX)
|
|
46
|
+
message(FATAL_ERROR "mikrojs_generate_bytecode: MODULE_PREFIX is required")
|
|
47
|
+
endif()
|
|
48
|
+
if(NOT ARG_SYMBOL_PREFIX)
|
|
49
|
+
message(FATAL_ERROR "mikrojs_generate_bytecode: SYMBOL_PREFIX is required")
|
|
50
|
+
endif()
|
|
51
|
+
|
|
52
|
+
# Verify qjsc exists (set by quickjs.cmake)
|
|
53
|
+
if(NOT EXISTS "${QJSC_EXECUTABLE}")
|
|
54
|
+
message(FATAL_ERROR "qjsc not found at ${QJSC_EXECUTABLE}. Run 'pnpm install' first.")
|
|
55
|
+
endif()
|
|
56
|
+
|
|
57
|
+
set(_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen")
|
|
58
|
+
set(_BUNDLE_DIR "${CMAKE_CURRENT_BINARY_DIR}/bundled")
|
|
59
|
+
|
|
60
|
+
# Collect source files so the bundle step re-runs when they change.
|
|
61
|
+
# Also track the shell scripts that drive the pipeline so changes to
|
|
62
|
+
# the scripts (e.g. qjsc flag fixes) invalidate the generated outputs
|
|
63
|
+
# and trigger a rebuild — otherwise ninja sees `bundle.stamp` unchanged
|
|
64
|
+
# and silently reuses stale bytecode headers.
|
|
65
|
+
file(GLOB_RECURSE _RUNTIME_SOURCES "${ARG_RUNTIME_DIR}/*.ts")
|
|
66
|
+
set(_BUNDLE_SCRIPT "${_MIK_BC_SCRIPTS_DIR}/bundle-runtime.js")
|
|
67
|
+
set(_COMPILE_SCRIPT "${_MIK_BC_SCRIPTS_DIR}/compile-bytecode.sh")
|
|
68
|
+
|
|
69
|
+
# Optional minifier override (e.g. -DMIK_MINIFIER=terser -DMIK_MINIFY_LEVEL=max)
|
|
70
|
+
set(_MINIFIER_ARGS "")
|
|
71
|
+
if(DEFINED MIK_MINIFIER)
|
|
72
|
+
list(APPEND _MINIFIER_ARGS "--minifier=${MIK_MINIFIER}")
|
|
73
|
+
endif()
|
|
74
|
+
if(DEFINED MIK_MINIFY_LEVEL)
|
|
75
|
+
list(APPEND _MINIFIER_ARGS "--minify-level=${MIK_MINIFY_LEVEL}")
|
|
76
|
+
endif()
|
|
77
|
+
|
|
78
|
+
# Step 1: Bundle TypeScript runtime modules to JS with esbuild
|
|
79
|
+
add_custom_command(
|
|
80
|
+
OUTPUT ${_BUNDLE_DIR}/bundle.stamp
|
|
81
|
+
COMMAND node ${_BUNDLE_SCRIPT}
|
|
82
|
+
${_BUNDLE_DIR} ${ARG_RUNTIME_DIR} ${ARG_MODULES} ${_MINIFIER_ARGS}
|
|
83
|
+
COMMAND ${CMAKE_COMMAND} -E touch ${_BUNDLE_DIR}/bundle.stamp
|
|
84
|
+
DEPENDS ${_RUNTIME_SOURCES} ${_BUNDLE_SCRIPT}
|
|
85
|
+
COMMENT "Bundling runtime modules"
|
|
86
|
+
WORKING_DIRECTORY ${ARG_WORKING_DIRECTORY}
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Step 2: Compile each bundled JS file to a bytecode header with qjsc
|
|
90
|
+
set(_HEADERS "")
|
|
91
|
+
foreach(mod ${ARG_MODULES})
|
|
92
|
+
# Sanitize module name for C identifiers (replace non-alphanumeric with _)
|
|
93
|
+
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" _mod_safe "${mod}")
|
|
94
|
+
set(_header "${_GEN_DIR}/${ARG_SYMBOL_PREFIX}_${_mod_safe}.h")
|
|
95
|
+
add_custom_command(
|
|
96
|
+
OUTPUT ${_header}
|
|
97
|
+
COMMAND ${CMAKE_COMMAND} -E make_directory ${_GEN_DIR}
|
|
98
|
+
COMMAND sh ${_COMPILE_SCRIPT}
|
|
99
|
+
${QJSC_EXECUTABLE}
|
|
100
|
+
${_BUNDLE_DIR}/${mod}.js
|
|
101
|
+
${_header}
|
|
102
|
+
"${ARG_MODULE_PREFIX}/${mod}"
|
|
103
|
+
"${ARG_SYMBOL_PREFIX}_${_mod_safe}_bytecode"
|
|
104
|
+
DEPENDS ${_BUNDLE_DIR}/bundle.stamp ${_COMPILE_SCRIPT} ${QJSC_EXECUTABLE}
|
|
105
|
+
COMMENT "Compiling bytecode: ${ARG_MODULE_PREFIX}/${mod}"
|
|
106
|
+
)
|
|
107
|
+
list(APPEND _HEADERS ${_header})
|
|
108
|
+
endforeach()
|
|
109
|
+
|
|
110
|
+
# Step 3: Generate builtins table header (includes + lookup table)
|
|
111
|
+
set(_TABLE_HEADER "${_GEN_DIR}/${ARG_SYMBOL_PREFIX}_builtins_table.h")
|
|
112
|
+
set(_TABLE_CONTENT "/* Auto-generated by mikrojs_generate_bytecode() — do not edit */\n")
|
|
113
|
+
foreach(mod ${ARG_MODULES})
|
|
114
|
+
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" _mod_safe "${mod}")
|
|
115
|
+
string(APPEND _TABLE_CONTENT "#include \"${ARG_SYMBOL_PREFIX}_${_mod_safe}.h\"\n")
|
|
116
|
+
endforeach()
|
|
117
|
+
string(APPEND _TABLE_CONTENT "\nstatic const mik_builtin_t ${ARG_SYMBOL_PREFIX}_builtins[] = {\n")
|
|
118
|
+
foreach(mod ${ARG_MODULES})
|
|
119
|
+
string(REGEX REPLACE "[^a-zA-Z0-9]" "_" _mod_safe "${mod}")
|
|
120
|
+
string(APPEND _TABLE_CONTENT " {\"${ARG_MODULE_PREFIX}/${mod}\", ${ARG_SYMBOL_PREFIX}_${_mod_safe}_bytecode, ${ARG_SYMBOL_PREFIX}_${_mod_safe}_bytecode_size},\n")
|
|
121
|
+
endforeach()
|
|
122
|
+
string(APPEND _TABLE_CONTENT " {NULL, NULL, 0},\n};\n")
|
|
123
|
+
file(GENERATE OUTPUT ${_TABLE_HEADER} CONTENT "${_TABLE_CONTENT}")
|
|
124
|
+
list(APPEND _HEADERS ${_TABLE_HEADER})
|
|
125
|
+
|
|
126
|
+
# Step 4: Create custom target
|
|
127
|
+
add_custom_target(${ARG_TARGET} DEPENDS ${_HEADERS})
|
|
128
|
+
|
|
129
|
+
# Export to caller's scope
|
|
130
|
+
set(${ARG_TARGET}_HEADERS ${_HEADERS} PARENT_SCOPE)
|
|
131
|
+
set(${ARG_TARGET}_GEN_DIR ${_GEN_DIR} PARENT_SCOPE)
|
|
132
|
+
# Include the parent of gen/ so #include "gen/foo.h" works
|
|
133
|
+
set(${ARG_TARGET}_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
|
|
134
|
+
endfunction()
|
|
135
|
+
|
|
136
|
+
function(mikrojs_force_include_modules)
|
|
137
|
+
foreach(id ${ARGN})
|
|
138
|
+
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mik__mod_desc_${id}")
|
|
139
|
+
endforeach()
|
|
140
|
+
endfunction()
|
|
141
|
+
|
|
142
|
+
function(mikrojs_force_include_builtins)
|
|
143
|
+
foreach(id ${ARGN})
|
|
144
|
+
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u mik__builtin_${id}")
|
|
145
|
+
endforeach()
|
|
146
|
+
endfunction()
|
package/cmake.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {dirname, join} from 'node:path'
|
|
2
|
+
import {fileURLToPath} from 'node:url'
|
|
3
|
+
|
|
4
|
+
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
5
|
+
|
|
6
|
+
/** Path to the main CMakeLists.txt */
|
|
7
|
+
export const cmakePath = join(__dirname, 'CMakeLists.txt')
|
|
8
|
+
|
|
9
|
+
/** Path to the public include directory */
|
|
10
|
+
export const includePath = join(__dirname, 'include')
|
|
11
|
+
|
|
12
|
+
/** Path to the C++ source directory */
|
|
13
|
+
export const srcPath = join(__dirname, 'src')
|
|
14
|
+
|
|
15
|
+
/** Path to the build scripts directory */
|
|
16
|
+
export const scriptsPath = join(__dirname, 'scripts')
|
|
17
|
+
|
|
18
|
+
/** Path to the runtime TypeScript modules directory */
|
|
19
|
+
export const runtimePath = join(__dirname, 'runtime')
|
|
20
|
+
|
|
21
|
+
/** Path to the reusable bytecode generation CMake module */
|
|
22
|
+
export const bytecodeCmakePath = join(__dirname, 'cmake', 'mikrojs_bytecode.cmake')
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { HostMessage, MikroRuntimeOptions, ProfileEntry } from './types.js';
|
|
2
|
+
export declare class MikroRuntime {
|
|
3
|
+
private native;
|
|
4
|
+
constructor(options?: MikroRuntimeOptions);
|
|
5
|
+
evalModule(filename: string, isMain?: boolean): void;
|
|
6
|
+
/** Evaluate module source code directly, bypassing filesystem path resolution. */
|
|
7
|
+
evalModuleContent(filename: string, content: string): void;
|
|
8
|
+
/** Evaluate a script (not module) and return the stringified result. Returns undefined if the result is undefined/null. */
|
|
9
|
+
evalScript(code: string): string | undefined;
|
|
10
|
+
loop(): Promise<void>;
|
|
11
|
+
/** Run one iteration of the event loop synchronously. Returns 0 on success. */
|
|
12
|
+
loopOnce(): number;
|
|
13
|
+
stop(): void;
|
|
14
|
+
dispose(): void;
|
|
15
|
+
/** Register a JS source string as a named virtual module.
|
|
16
|
+
* Virtual modules are checked by the loader before builtin bytecode,
|
|
17
|
+
* allowing JS-based mocks to override any native:* C module. */
|
|
18
|
+
registerModuleSource(name: string, source: string): void;
|
|
19
|
+
/** Drain all outbound messages sent from QuickJS via native:host.send().
|
|
20
|
+
* Returns and clears the queue. Call after each loopOnce(). */
|
|
21
|
+
drainMessages(): HostMessage[];
|
|
22
|
+
/** Post a message from Node.js into the QuickJS runtime.
|
|
23
|
+
* Delivered to the native:host.onMessage() callback on the next loop tick. */
|
|
24
|
+
postMessage(type: string, data: string): void;
|
|
25
|
+
/** Set a preprocessor function called on module source before compilation.
|
|
26
|
+
* Return a string to replace the source, or undefined to use the original.
|
|
27
|
+
* Useful for stripping TypeScript types from .ts files. */
|
|
28
|
+
setPreprocessor(fn: (filename: string, source: string) => string | undefined): void;
|
|
29
|
+
/** Set a synchronous RPC handler called from QuickJS via native:host.call().
|
|
30
|
+
* The handler receives a method name (e.g. 'pin.pinMode') and JSON-encoded args,
|
|
31
|
+
* and must return a JSON-encoded result string (or a Promise of one for async). */
|
|
32
|
+
setRpcHandler(handler: (method: string, argsJson: string) => string | Promise<string>): void;
|
|
33
|
+
/** Enable per-module memory profiling. Must be called before any module loads
|
|
34
|
+
* to capture the full import graph. Profile storage lives outside QuickJS's
|
|
35
|
+
* tracked heap so instrumentation does not pollute the numbers being measured. */
|
|
36
|
+
enableProfiling(): void;
|
|
37
|
+
/** Return the collected profile entries. Each entry records the QuickJS heap
|
|
38
|
+
* delta observed while loading a specific module. */
|
|
39
|
+
getProfile(): ProfileEntry[];
|
|
40
|
+
/** Return the QuickJS heap baseline (bytes) at the time profiling was enabled.
|
|
41
|
+
* This is the cost of the runtime + context + built-in prototypes, before
|
|
42
|
+
* any user modules are loaded. */
|
|
43
|
+
getProfileBaseline(): number;
|
|
44
|
+
}
|
|
45
|
+
/** Serialize a JSON string to QuickJS binary JSON (bjson) format. */
|
|
46
|
+
export declare function jsonToBjson(json: string): Buffer;
|
|
47
|
+
/** Compile a JS module to QuickJS bytecode. External imports must be declared to avoid resolution errors. */
|
|
48
|
+
export declare function compileBytecode(source: string, moduleName: string, externals?: string[]): Buffer;
|
|
49
|
+
/** Compile a JS module to bytecode and return as a C header string (equivalent to qjsc -o header.h). */
|
|
50
|
+
export declare function compileBytecodeToHeader(source: string, moduleName: string, symbolName: string, externals?: string[]): string;
|
|
51
|
+
export type { HostMessage, MikroRuntimeOptions, NativeMikroRuntime, ProfileEntry } from './types.ts';
|
|
52
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../addon/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,WAAW,EACX,mBAAmB,EAGnB,YAAY,EACb,MAAM,YAAY,CAAA;AAuBnB,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAoB;gBAEtB,OAAO,CAAC,EAAE,mBAAmB;IAIzC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,UAAO,GAAG,IAAI;IAIjD,kFAAkF;IAClF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAI1D,2HAA2H;IAC3H,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAIrB,+EAA+E;IAC/E,QAAQ,IAAI,MAAM;IAIlB,IAAI,IAAI,IAAI;IAIZ,OAAO,IAAI,IAAI;IAIf;;oEAEgE;IAChE,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;IAIxD;mEAC+D;IAC/D,aAAa,IAAI,WAAW,EAAE;IAI9B;kFAC8E;IAC9E,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAI7C;;+DAE2D;IAC3D,eAAe,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI;IAInF;;uFAEmF;IACnF,aAAa,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI;IAI5F;;sFAEkF;IAClF,eAAe,IAAI,IAAI;IAIvB;yDACqD;IACrD,UAAU,IAAI,YAAY,EAAE;IAI5B;;sCAEkC;IAClC,kBAAkB,IAAI,MAAM;CAG7B;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,6GAA6G;AAC7G,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAEhG;AAED,wGAAwG;AACxG,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,MAAM,EAAE,GACnB,MAAM,CA4BR;AAED,YAAY,EAAC,WAAW,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,YAAY,EAAC,MAAM,YAAY,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
const require = createRequire(import.meta.url);
|
|
4
|
+
const nodeGypBuild = require('node-gyp-build');
|
|
5
|
+
function loadBindings() {
|
|
6
|
+
const pkgRoot = join(import.meta.dirname, '..');
|
|
7
|
+
try {
|
|
8
|
+
return nodeGypBuild(pkgRoot);
|
|
9
|
+
}
|
|
10
|
+
catch (prebuildErr) {
|
|
11
|
+
// Dev fallback: cmake-js builds to addon/build/Release/, which is outside
|
|
12
|
+
// the paths node-gyp-build probes by default.
|
|
13
|
+
const devPath = join(pkgRoot, 'addon', 'build', 'Release', 'mikrojs_node.node');
|
|
14
|
+
try {
|
|
15
|
+
return require(devPath);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw prebuildErr;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
const bindings = loadBindings();
|
|
23
|
+
export class MikroRuntime {
|
|
24
|
+
native;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.native = new bindings.MikroRuntime(options);
|
|
27
|
+
}
|
|
28
|
+
evalModule(filename, isMain = true) {
|
|
29
|
+
this.native.evalModule(filename, isMain);
|
|
30
|
+
}
|
|
31
|
+
/** Evaluate module source code directly, bypassing filesystem path resolution. */
|
|
32
|
+
evalModuleContent(filename, content) {
|
|
33
|
+
this.native.evalModuleContent(filename, content);
|
|
34
|
+
}
|
|
35
|
+
/** Evaluate a script (not module) and return the stringified result. Returns undefined if the result is undefined/null. */
|
|
36
|
+
evalScript(code) {
|
|
37
|
+
return this.native.evalScript(code);
|
|
38
|
+
}
|
|
39
|
+
loop() {
|
|
40
|
+
return this.native.loop();
|
|
41
|
+
}
|
|
42
|
+
/** Run one iteration of the event loop synchronously. Returns 0 on success. */
|
|
43
|
+
loopOnce() {
|
|
44
|
+
return this.native.loopOnce();
|
|
45
|
+
}
|
|
46
|
+
stop() {
|
|
47
|
+
this.native.stop();
|
|
48
|
+
}
|
|
49
|
+
dispose() {
|
|
50
|
+
this.native.dispose();
|
|
51
|
+
}
|
|
52
|
+
/** Register a JS source string as a named virtual module.
|
|
53
|
+
* Virtual modules are checked by the loader before builtin bytecode,
|
|
54
|
+
* allowing JS-based mocks to override any native:* C module. */
|
|
55
|
+
registerModuleSource(name, source) {
|
|
56
|
+
this.native.registerModuleSource(name, source);
|
|
57
|
+
}
|
|
58
|
+
/** Drain all outbound messages sent from QuickJS via native:host.send().
|
|
59
|
+
* Returns and clears the queue. Call after each loopOnce(). */
|
|
60
|
+
drainMessages() {
|
|
61
|
+
return this.native.drainMessages();
|
|
62
|
+
}
|
|
63
|
+
/** Post a message from Node.js into the QuickJS runtime.
|
|
64
|
+
* Delivered to the native:host.onMessage() callback on the next loop tick. */
|
|
65
|
+
postMessage(type, data) {
|
|
66
|
+
this.native.postMessage(type, data);
|
|
67
|
+
}
|
|
68
|
+
/** Set a preprocessor function called on module source before compilation.
|
|
69
|
+
* Return a string to replace the source, or undefined to use the original.
|
|
70
|
+
* Useful for stripping TypeScript types from .ts files. */
|
|
71
|
+
setPreprocessor(fn) {
|
|
72
|
+
this.native.setPreprocessor(fn);
|
|
73
|
+
}
|
|
74
|
+
/** Set a synchronous RPC handler called from QuickJS via native:host.call().
|
|
75
|
+
* The handler receives a method name (e.g. 'pin.pinMode') and JSON-encoded args,
|
|
76
|
+
* and must return a JSON-encoded result string (or a Promise of one for async). */
|
|
77
|
+
setRpcHandler(handler) {
|
|
78
|
+
this.native.setRpcHandler(handler);
|
|
79
|
+
}
|
|
80
|
+
/** Enable per-module memory profiling. Must be called before any module loads
|
|
81
|
+
* to capture the full import graph. Profile storage lives outside QuickJS's
|
|
82
|
+
* tracked heap so instrumentation does not pollute the numbers being measured. */
|
|
83
|
+
enableProfiling() {
|
|
84
|
+
this.native.enableProfiling();
|
|
85
|
+
}
|
|
86
|
+
/** Return the collected profile entries. Each entry records the QuickJS heap
|
|
87
|
+
* delta observed while loading a specific module. */
|
|
88
|
+
getProfile() {
|
|
89
|
+
return this.native.getProfile();
|
|
90
|
+
}
|
|
91
|
+
/** Return the QuickJS heap baseline (bytes) at the time profiling was enabled.
|
|
92
|
+
* This is the cost of the runtime + context + built-in prototypes, before
|
|
93
|
+
* any user modules are loaded. */
|
|
94
|
+
getProfileBaseline() {
|
|
95
|
+
return this.native.getProfileBaseline();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/** Serialize a JSON string to QuickJS binary JSON (bjson) format. */
|
|
99
|
+
export function jsonToBjson(json) {
|
|
100
|
+
return bindings.jsonToBjson(json);
|
|
101
|
+
}
|
|
102
|
+
/** Compile a JS module to QuickJS bytecode. External imports must be declared to avoid resolution errors. */
|
|
103
|
+
export function compileBytecode(source, moduleName, externals) {
|
|
104
|
+
return bindings.compileBytecode(source, moduleName, externals);
|
|
105
|
+
}
|
|
106
|
+
/** Compile a JS module to bytecode and return as a C header string (equivalent to qjsc -o header.h). */
|
|
107
|
+
export function compileBytecodeToHeader(source, moduleName, symbolName, externals) {
|
|
108
|
+
const buf = bindings.compileBytecode(source, moduleName, externals);
|
|
109
|
+
// Match qjsc dump_hex format: " 0xNN," with newline every 8 bytes
|
|
110
|
+
let hex = '';
|
|
111
|
+
let col = 0;
|
|
112
|
+
for (let i = 0; i < buf.length; i++) {
|
|
113
|
+
hex += ` 0x${buf[i].toString(16).padStart(2, '0')},`;
|
|
114
|
+
if (++col === 8) {
|
|
115
|
+
hex += '\n';
|
|
116
|
+
col = 0;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (col !== 0) {
|
|
120
|
+
hex += '\n';
|
|
121
|
+
}
|
|
122
|
+
return (`/* File generated automatically by the QuickJS-ng compiler. */\n` +
|
|
123
|
+
`\n` +
|
|
124
|
+
`#include <inttypes.h>\n` +
|
|
125
|
+
`\n` +
|
|
126
|
+
`const uint32_t ${symbolName}_size = ${buf.length};\n` +
|
|
127
|
+
`\n` +
|
|
128
|
+
`const uint8_t ${symbolName}[${buf.length}] = {\n` +
|
|
129
|
+
hex +
|
|
130
|
+
`};\n`);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../addon/index.ts"],"names":[],"mappings":"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"}
|