@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.
Files changed (109) hide show
  1. package/CMakeLists.txt +198 -0
  2. package/LICENSE +21 -0
  3. package/README.md +49 -0
  4. package/cmake/mikrojs_bytecode.cmake +146 -0
  5. package/cmake.js +22 -0
  6. package/dist/index.d.ts +52 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +132 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/types.d.ts +43 -0
  11. package/dist/types.d.ts.map +1 -0
  12. package/dist/types.js +2 -0
  13. package/dist/types.js.map +1 -0
  14. package/include/byteorder_apple.h +11 -0
  15. package/include/byteorder_windows.h +12 -0
  16. package/include/mikrojs/cbor_helpers.h +24 -0
  17. package/include/mikrojs/cutils_wrap.h +59 -0
  18. package/include/mikrojs/errors.h +144 -0
  19. package/include/mikrojs/mem.h +11 -0
  20. package/include/mikrojs/mik_color.h +32 -0
  21. package/include/mikrojs/mikrojs.h +331 -0
  22. package/include/mikrojs/platform.h +82 -0
  23. package/include/mikrojs/private.h +281 -0
  24. package/include/mikrojs/utils.h +125 -0
  25. package/package.json +100 -0
  26. package/prebuilds/darwin-arm64/mikrojs.napi.node +0 -0
  27. package/prebuilds/linux-arm64/mikrojs.napi.node +0 -0
  28. package/prebuilds/linux-x64/mikrojs.napi.node +0 -0
  29. package/runtime/ble/ble.ts +231 -0
  30. package/runtime/ble/types.ts +194 -0
  31. package/runtime/ble/uuid.ts +89 -0
  32. package/runtime/ble/validators.ts +61 -0
  33. package/runtime/cbor/cbor.ts +1 -0
  34. package/runtime/cbor/types.ts +8 -0
  35. package/runtime/console/types.ts +50 -0
  36. package/runtime/env/env.ts +17 -0
  37. package/runtime/env/types.ts +12 -0
  38. package/runtime/format/types.ts +4 -0
  39. package/runtime/fs/fs.ts +93 -0
  40. package/runtime/fs/types.ts +92 -0
  41. package/runtime/globals.d.ts +87 -0
  42. package/runtime/http/helpers.ts +222 -0
  43. package/runtime/http/native.ts +151 -0
  44. package/runtime/http/request.ts +25 -0
  45. package/runtime/i2c/i2c.ts +35 -0
  46. package/runtime/i2c/types.ts +55 -0
  47. package/runtime/inspect/types.ts +10 -0
  48. package/runtime/internal.d.ts +456 -0
  49. package/runtime/kv/nvs.ts +17 -0
  50. package/runtime/kv/rtc.ts +17 -0
  51. package/runtime/kv/shared.ts +107 -0
  52. package/runtime/kv/types.ts +150 -0
  53. package/runtime/neopixel/neopixel.ts +38 -0
  54. package/runtime/neopixel/types.ts +27 -0
  55. package/runtime/pin/pin.ts +51 -0
  56. package/runtime/pin/types.ts +49 -0
  57. package/runtime/pwm/pwm.ts +32 -0
  58. package/runtime/pwm/types.ts +29 -0
  59. package/runtime/reader/reader.ts +167 -0
  60. package/runtime/reader/types.ts +34 -0
  61. package/runtime/result/native-result.node-shim.ts +44 -0
  62. package/runtime/result/result.ts +26 -0
  63. package/runtime/result/types.ts +60 -0
  64. package/runtime/schema/schema.ts +321 -0
  65. package/runtime/schema/types.ts +152 -0
  66. package/runtime/sleep/sleep.ts +14 -0
  67. package/runtime/sleep/types.ts +44 -0
  68. package/runtime/sntp/sntp.ts +54 -0
  69. package/runtime/sntp/types.ts +38 -0
  70. package/runtime/spi/spi.ts +31 -0
  71. package/runtime/spi/types.ts +42 -0
  72. package/runtime/stdio/stdio.ts +44 -0
  73. package/runtime/stdio/types.ts +22 -0
  74. package/runtime/stream/stream.ts +150 -0
  75. package/runtime/stream/types.ts +47 -0
  76. package/runtime/sys/sys.ts +90 -0
  77. package/runtime/sys/types.ts +131 -0
  78. package/runtime/test/test.ts +595 -0
  79. package/runtime/test/types.ts +97 -0
  80. package/runtime/uart/types.ts +75 -0
  81. package/runtime/uart/uart.ts +51 -0
  82. package/runtime/wifi/types.ts +156 -0
  83. package/runtime/wifi/wifi.ts +208 -0
  84. package/scripts/bundle-runtime.js +149 -0
  85. package/scripts/compare-minifiers.js +189 -0
  86. package/scripts/compile-bytecode.sh +38 -0
  87. package/scripts/copy-prebuild.js +20 -0
  88. package/scripts/generate-symbol-map.js +146 -0
  89. package/src/builtins.cpp +82 -0
  90. package/src/cutils_compat.c +38 -0
  91. package/src/eval_bytecode.cpp +42 -0
  92. package/src/fs.cpp +878 -0
  93. package/src/mem.cpp +63 -0
  94. package/src/mik_abort.cpp +160 -0
  95. package/src/mik_app_config.cpp +358 -0
  96. package/src/mik_cbor.cpp +334 -0
  97. package/src/mik_color.cpp +46 -0
  98. package/src/mik_console.cpp +422 -0
  99. package/src/mik_inspect.cpp +850 -0
  100. package/src/mik_repl.cpp +1122 -0
  101. package/src/mik_result.cpp +344 -0
  102. package/src/mik_stdio.cpp +147 -0
  103. package/src/mik_sys.cpp +239 -0
  104. package/src/mik_text_encoding.cpp +443 -0
  105. package/src/mikrojs.cpp +942 -0
  106. package/src/modules.cpp +944 -0
  107. package/src/platform_posix.cpp +134 -0
  108. package/src/timers.cpp +208 -0
  109. package/src/utils.cpp +173 -0
@@ -0,0 +1,331 @@
1
+ #pragma once
2
+ #include <quickjs.h>
3
+
4
+ #ifdef __cplusplus
5
+ extern "C" {
6
+ #endif
7
+
8
+ typedef struct MIKRuntime MIKRuntime;
9
+
10
+ typedef struct MIKRunOptions {
11
+ int mem_limit;
12
+ size_t stack_size;
13
+ } MIKRunOptions;
14
+
15
+ typedef struct MIKConfig {
16
+ bool restart_on_uncaught_exception;
17
+ int restart_delay_ms;
18
+ size_t stack_size;
19
+ uint32_t mem_reserved;
20
+ uint32_t fs_read_max; /* 0 = keep runtime default (65536) */
21
+ char entry_point[128];
22
+ char wifi_country[3]; /* Two-letter country code + NUL, e.g. "NO" */
23
+ } MIKConfig;
24
+
25
+ void MIK_DefaultConfig(MIKConfig* config);
26
+ int MIK_LoadConfig(const char* base_path, MIKConfig* config);
27
+ void MIK_SetConfig(MIKRuntime* mik_rt, const MIKConfig* config);
28
+
29
+ /* Load the "tests" string array from package.json at `base_path`, applying
30
+ * the same prefix as MIK_LoadConfig so paths are resolved relative to the
31
+ * app directory. Presence of this array is the supervisor's sole "test
32
+ * mode" signal — normal deploys never write it.
33
+ * Returns 0 on success (including when the array is absent or empty),
34
+ * nonzero on malloc failure. On success, `*out_paths` is NULL when the
35
+ * array was absent, otherwise a malloc'd array of `*out_count` malloc'd
36
+ * strings that the caller frees via MIK_FreeTests. */
37
+ int MIK_LoadTests(const char* base_path, char*** out_paths, size_t* out_count);
38
+ void MIK_FreeTests(char** paths, size_t count);
39
+
40
+ void MIK_DefaultOptions(MIKRunOptions* options);
41
+ MIKRuntime* MIK_NewRuntime(void);
42
+ MIKRuntime* MIK_NewRuntimeOptions(MIKRunOptions* options);
43
+ void MIK_FreeRuntime(MIKRuntime* mik_rt);
44
+
45
+ /* Evaluate `entry` as this runtime's main module. Probes the filesystem
46
+ * (under the configured fs_base_path) for `entry` and, if the entry is a
47
+ * `.js` path, also for the adjacent `.bjs` bytecode variant. Returns:
48
+ * 0 success
49
+ * -EINVAL runtime or entry is null/empty
50
+ * -ENOENT entry (and its .bjs variant) not on disk
51
+ * -EFAULT module evaluation threw
52
+ * Emits no diagnostic output — callers decide whether and how to log. */
53
+ int MIK_RunEntry(MIKRuntime* mik_rt, const char* entry);
54
+
55
+ JSContext* MIK_GetJSContext(MIKRuntime* mik_rt);
56
+ MIKRuntime* MIK_GetRuntime(JSContext* ctx);
57
+ void MIK_SetFSBasePath(MIKRuntime* mik_rt, const char* base_path);
58
+ void MIK_SetFSRoot(MIKRuntime* mik_rt, const char* fs_root);
59
+ void MIK_SetFSLimit(MIKRuntime* mik_rt, size_t limit);
60
+ /* Maximum size (bytes) for a single readFile() call. Larger files throw
61
+ * FSError with code EFBIG — callers use open() for streaming. 0 resets to
62
+ * the default (65536). */
63
+ void MIK_SetFSReadMax(MIKRuntime* mik_rt, size_t bytes);
64
+ int MIK_Loop(MIKRuntime* mik_rt);
65
+ void MIK_Stop(MIKRuntime* mik_rt);
66
+
67
+ /* True once the runtime has entered a halted state — set by the promise
68
+ * rejection tracker when an unhandled rejection is observed with no
69
+ * host dispatcher to cancel it. MIK_Loop() returns 1 immediately in
70
+ * this state and no further pumping happens. The supervisor uses this
71
+ * to detect that a per-test runtime has crashed and move to the next. */
72
+ bool MIK_IsStopRequested(MIKRuntime* mik_rt);
73
+
74
+ /* Environment variables — call MIK_SetEnvVar() before MIK_RebuildEnv(),
75
+ * or before any module evaluation if env vars need to be available. */
76
+ void MIK_SetEnvVar(MIKRuntime* mik_rt, const char* key, const char* value);
77
+ void MIK_RebuildEnv(MIKRuntime* mik_rt);
78
+
79
+ /* Native module registration */
80
+ typedef void (*MIKNativeModuleInitFn)(JSContext* ctx);
81
+ void MIK_RegisterNativeModuleInit(MIKRuntime* mik_rt, const char* name,
82
+ MIKNativeModuleInitFn init_fn);
83
+
84
+ /* Loop consumer registration */
85
+ typedef void (*MIKLoopConsumeFn)(JSContext* ctx);
86
+ typedef void (*MIKLoopDestroyFn)(JSContext* ctx);
87
+ void MIK_RegisterLoopConsumer(MIKRuntime* mik_rt, MIKLoopConsumeFn consume_fn,
88
+ MIKLoopDestroyFn destroy_fn);
89
+
90
+ /* Virtual module registration — allows registering JS source as named modules,
91
+ * checked by the module loader before the builtin bytecode table. */
92
+ void MIK_RegisterVirtualModule(MIKRuntime* mik_rt, const char* name, const char* source,
93
+ size_t source_len);
94
+
95
+ /* Error handler — called with the exception JSValue before it is consumed.
96
+ * The handler receives a borrowed JSValue (do NOT free it). */
97
+ typedef void (*MIKErrorHandlerFn)(JSContext* ctx, JSValue error, void* opaque);
98
+ void MIK_SetErrorHandler(MIKRuntime* mik_rt, MIKErrorHandlerFn fn, void* opaque);
99
+
100
+ /* Module source preprocessor — called on source files before compilation.
101
+ * The callback receives filename, source, and source_len. It should return
102
+ * a malloc'd string and set *out_len, or return NULL to use the original source.
103
+ * The caller frees the returned string with free(). */
104
+ typedef char* (*MIKPreprocessFn)(const char* filename, const char* source, size_t source_len,
105
+ size_t* out_len, void* opaque);
106
+ void MIK_SetPreprocessor(MIKRuntime* mik_rt, MIKPreprocessFn fn, void* opaque);
107
+
108
+ /* Install the two test-helper globals on a runtime:
109
+ * __testEmit(jsonStr) — sends MSG_TEST TLV frames to the host
110
+ * __testFileDone() — signals MIK_ProtocolExit so a supervisor can
111
+ * tear down this runtime and move to the next
112
+ *
113
+ * Must be called before user code runs (ordinary runtimes never see these
114
+ * globals). The test-runner supervisor calls this per-file in test mode;
115
+ * the mikrojs/test built-in falls back to a console.log path when absent. */
116
+ void MIK_EnableTestHelpers(MIKRuntime* mik_rt);
117
+
118
+ /* Memory profiling — records per-module QuickJS heap growth. Storage lives
119
+ * outside the tracked runtime heap so instrumentation does not pollute the
120
+ * numbers being measured. Enable before loading user code; read entries at
121
+ * shutdown. */
122
+ #define MIK_PROFILE_NAME_MAX 96
123
+
124
+ typedef struct MIKProfileEntry {
125
+ char name[MIK_PROFILE_NAME_MAX]; /* Module name, truncated if longer */
126
+ size_t delta_bytes; /* QuickJS malloc_size delta across load */
127
+ size_t order; /* Load order, starting at 0 */
128
+ } MIKProfileEntry;
129
+
130
+ void MIK_EnableProfiling(MIKRuntime* mik_rt);
131
+ size_t MIK_GetProfileEntryCount(MIKRuntime* mik_rt);
132
+ const MIKProfileEntry* MIK_GetProfileEntries(MIKRuntime* mik_rt);
133
+ size_t MIK_GetProfileBaseline(MIKRuntime* mik_rt);
134
+
135
+ /* OOM signalling — reports to the host when QuickJS's memory budget is
136
+ * at or past the point where module evaluation is likely to fail, OR after
137
+ * the fact when a null/primitive exception correlates with low headroom
138
+ * (which is almost always a recursive-OOM where QuickJS couldn't even
139
+ * allocate an Error object to throw).
140
+ *
141
+ * Two access patterns are supported:
142
+ *
143
+ * 1. Polling via `MIK_ConsumeOOMFlag()`: cheap "did OOM happen recently?"
144
+ * boolean check. Automatically clears the flag on read, so each call
145
+ * returns true at most once per event. Useful for host code that
146
+ * checks after each `MIK_EvalModule` / `MIK_Loop` iteration.
147
+ *
148
+ * 2. Async callback via `MIK_SetOOMHandler()`: fires synchronously at
149
+ * the detection point with a struct carrying the filename and heap
150
+ * stats. Useful for host code that wants to react immediately (log
151
+ * to a file, flash an LED, trigger a reset, forward to a telemetry
152
+ * channel).
153
+ *
154
+ * Both mechanisms operate entirely on C-level state and a C function
155
+ * pointer — zero QuickJS allocations, safe to use when the JS heap is
156
+ * exhausted. Hot paths are unaffected: the detection points are
157
+ * boot/failure paths that already existed, so the added flag-set and
158
+ * conditional callback invocation are in cold code. */
159
+ enum {
160
+ MIK_OOM_PRE_EVAL_WARN = 1, /* headroom crossed low-water mark before eval */
161
+ MIK_OOM_POST_EVAL_DETECTED = 2, /* null/primitive exception + low headroom after eval */
162
+ };
163
+
164
+ typedef struct MIKOOMEvent {
165
+ int phase; /* one of MIK_OOM_* above */
166
+ const char* filename; /* module being evaluated (borrowed, not owned) */
167
+ size_t malloc_size; /* QuickJS heap used */
168
+ size_t malloc_limit; /* QuickJS heap soft cap */
169
+ size_t headroom; /* malloc_limit - malloc_size (clamped at 0) */
170
+ } MIKOOMEvent;
171
+
172
+ typedef void (*MIKOOMHandlerFn)(const MIKOOMEvent* event, void* opaque);
173
+ void MIK_SetOOMHandler(MIKRuntime* mik_rt, MIKOOMHandlerFn fn, void* opaque);
174
+
175
+ /* Returns true at most once per OOM event: the flag is cleared on read.
176
+ * Callers should poll this between operations to catch events missed by
177
+ * the synchronous handler path. */
178
+ bool MIK_ConsumeOOMFlag(MIKRuntime* mik_rt);
179
+
180
+ /* Internal: fires the handler and sets the flag. Called from detection
181
+ * points inside libmikrojs and from addons that do their own detection
182
+ * (e.g. the Node addon's post-eval null-exception reporter). */
183
+ void MIK_ReportOOM(MIKRuntime* mik_rt, const MIKOOMEvent* event);
184
+
185
+ /* Per-module opaque data slots (for platform-specific modules to store state).
186
+ * Slots are allocated dynamically via MIK_AllocModuleSlot(). */
187
+ #define MIK_MODULE_DATA_SLOTS 16
188
+ void MIK_SetModuleData(MIKRuntime* mik_rt, int slot, void* data);
189
+ void* MIK_GetModuleData(MIKRuntime* mik_rt, int slot);
190
+ int MIK_AllocModuleSlot(MIKRuntime* mik_rt);
191
+
192
+ /* Self-registration for native modules (ESP32, board, driver modules).
193
+ * Modules call MIK_REGISTER_MODULE() at file scope. The module loader
194
+ * discovers registered modules and initializes them lazily on first import. */
195
+ typedef JSModuleDef* (*MIKModuleInitFn)(JSContext* ctx);
196
+
197
+ typedef struct mik_module_desc_t {
198
+ const char* name; /* module name, e.g. "native:pin" */
199
+ MIKModuleInitFn init; /* called on first import; returns the JSModuleDef */
200
+ MIKLoopConsumeFn consume; /* event loop consumer (nullable) */
201
+ MIKLoopDestroyFn destroy; /* cleanup on shutdown (nullable) */
202
+ struct mik_module_desc_t* next;
203
+ } mik_module_desc_t;
204
+
205
+ extern mik_module_desc_t* mik__module_registry_head;
206
+
207
+ /* NOLINTBEGIN(bugprone-macro-parentheses,cppcoreguidelines-avoid-non-const-global-variables) */
208
+ /* The descriptor has external linkage so the linker can be told to keep it
209
+ * via -u flags (static symbols in static libraries get stripped). */
210
+ #define MIK_REGISTER_MODULE(id, name_, init_, consume_, destroy_) \
211
+ mik_module_desc_t mik__mod_desc_##id = { \
212
+ name_, init_, consume_, destroy_, NULL}; \
213
+ static void __attribute__((constructor)) mik__register_mod_##id(void) { \
214
+ mik__mod_desc_##id.next = mik__module_registry_head; \
215
+ mik__module_registry_head = &mik__mod_desc_##id; \
216
+ }
217
+ /* Self-registration for bytecode builtins (board/driver JS runtime modules).
218
+ * Driver packages use MIK_REGISTER_BUILTIN() to embed their JS wrappers as
219
+ * firmware builtins, resolved by the real npm package name (e.g. "@mikrojs/your-driver"). */
220
+ typedef struct mik_ext_builtin_t {
221
+ const char* name; /* module name, e.g. "@mikrojs/your-driver" */
222
+ const uint8_t* data; /* compiled bytecode */
223
+ uint32_t data_size;
224
+ struct mik_ext_builtin_t* next;
225
+ } mik_ext_builtin_t;
226
+
227
+ extern mik_ext_builtin_t* mik__ext_builtin_head;
228
+
229
+ /* The descriptor has external linkage so the linker can keep it via -u flags. */
230
+ #define MIK_REGISTER_BUILTIN(id, name_, data_, size_) \
231
+ mik_ext_builtin_t mik__builtin_##id = { \
232
+ name_, data_, size_, NULL}; \
233
+ static void __attribute__((constructor)) mik__register_builtin_##id(void) { \
234
+ mik__builtin_##id.next = mik__ext_builtin_head; \
235
+ mik__ext_builtin_head = &mik__builtin_##id; \
236
+ }
237
+ /* NOLINTEND(bugprone-macro-parentheses,cppcoreguidelines-avoid-non-const-global-variables) */
238
+
239
+ /* REPL (mik_repl.cpp) */
240
+ bool MIK_IsReplActive(void);
241
+
242
+ /* Protocol transport abstraction */
243
+ typedef struct MIKReplTransport MIKReplTransport;
244
+
245
+ /**
246
+ * Command handler callback for platform-specific commands (deploy, config).
247
+ * Called by the protocol loop when it receives a command type it doesn't
248
+ * handle itself (i.e. anything outside the REPL command range 0x10-0x13).
249
+ *
250
+ * The handler receives the TLV header (type + payload_len) but the payload
251
+ * bytes have NOT been read yet. The handler must read exactly payload_len
252
+ * bytes from the transport using mik__proto_read_exact() before returning.
253
+ *
254
+ * Returns true if the command was handled, false to ignore it.
255
+ */
256
+ typedef bool (*MIKProtoCommandHandler)(MIKReplTransport* transport, uint8_t cmd_type,
257
+ uint32_t payload_len, void* ctx);
258
+
259
+ /**
260
+ * Session teardown hook. Called once from the protocol loop when it
261
+ * exits (transport error, client disconnect, or MIK_CMD_EXIT). Platform
262
+ * handlers use this to reset any per-session state — e.g. a partially
263
+ * staged deploy — so the next session starts clean.
264
+ */
265
+ typedef void (*MIKProtoSessionEnd)(void* ctx);
266
+
267
+ struct MIKReplTransport {
268
+ int (*read)(uint8_t* buf, size_t size, void* ctx); /* Non-blocking read */
269
+ void (*write)(const void* buf, size_t len, void* ctx); /* Write */
270
+ void* ctx; /* Opaque context */
271
+ const char* chip_name; /* e.g. "esp32c6" (optional) */
272
+ MIKProtoCommandHandler command_handler; /* Platform command handler */
273
+ void* command_handler_ctx; /* Handler context */
274
+ MIKProtoSessionEnd session_end; /* Called on loop exit (optional) */
275
+ void* session_end_ctx; /* session_end context */
276
+ };
277
+
278
+ /* Protocol transport helpers — blocking reads with event loop pumping.
279
+ * Used by command handlers to read payload bytes from the transport. */
280
+ bool mik__proto_read_exact(MIKReplTransport* transport, void* buf, size_t n);
281
+ bool mik__proto_drain(MIKReplTransport* transport, size_t n);
282
+
283
+ /* Send a TLV-framed message */
284
+ void mik__proto_send(MIKReplTransport* transport, uint8_t type, const void* data, size_t len);
285
+ void mik__proto_send_ok(MIKReplTransport* transport);
286
+ void mik__proto_send_err(MIKReplTransport* transport, const char* msg);
287
+
288
+ /* ── Session primitives ─────────────────────────────────────────────
289
+ * A protocol session is scoped to a transport (one client connection).
290
+ * Runtimes are attached/detached within the session; a supervisor can
291
+ * swap runtimes between serve loops without closing the transport or
292
+ * repeating the MSG_READY handshake. */
293
+
294
+ /* Open a protocol session on `transport`. Sends MSG_READY, enables TLV
295
+ * framing for console/stdio output. No-op if a session is already open. */
296
+ void MIK_ProtocolOpen(MIKReplTransport* transport);
297
+
298
+ /* Close the session. Fires the transport's session_end hook (used for
299
+ * deploy state cleanup), then clears all session state. Safe to call
300
+ * from any state. */
301
+ void MIK_ProtocolClose(void);
302
+
303
+ /* Bind a runtime to the active session. Required before serving any
304
+ * commands that evaluate JS. The caller retains ownership of the runtime
305
+ * and must detach before freeing. */
306
+ void MIK_ProtocolAttach(MIKRuntime* mik_rt);
307
+
308
+ /* Unbind the current runtime. Call before MIK_FreeRuntime when swapping
309
+ * runtimes mid-session. The session remains open. */
310
+ void MIK_ProtocolDetach(void);
311
+
312
+ /* Run the protocol loop until: (a) transport error, (b) CMD_EXIT from
313
+ * client, or (c) MIK_ProtocolExit() is called from elsewhere (e.g. a
314
+ * supervisor responding to a JS-side event). Handshake state persists
315
+ * across invocations, so the MSG_READY ping dance only happens once
316
+ * per session even if the serve loop is entered repeatedly. */
317
+ void MIK_ProtocolServeLoop(void);
318
+
319
+ /* Signal the active serve loop to return after the current iteration.
320
+ * Does not close the session — the caller can re-attach a new runtime
321
+ * and call MIK_ProtocolServeLoop() again. */
322
+ void MIK_ProtocolExit(void);
323
+
324
+ #ifdef __cplusplus
325
+ }
326
+ #endif
327
+
328
+ JSValue MIK_EvalScriptContent(JSContext* ctx, const char* content, size_t len);
329
+ JSValue MIK_EvalModule(JSContext* ctx, const char* filename, bool is_main);
330
+ JSValue MIK_EvalModuleContent(JSContext* ctx, const char* filename, const char* content,
331
+ size_t len);
@@ -0,0 +1,82 @@
1
+ #pragma once
2
+
3
+ #include <stdarg.h>
4
+ #include <stdbool.h>
5
+ #include <stddef.h>
6
+ #include <stdint.h>
7
+
8
+ #ifdef __cplusplus
9
+ extern "C" {
10
+ #endif
11
+
12
+ typedef struct MIKPlatform {
13
+ int64_t (*get_boot_us)(void); /* High-res timer, resets on deep sleep */
14
+ int64_t (*get_rtc_us)(void); /* RTC timer, survives deep sleep */
15
+ uint32_t (*random)(void);
16
+ void (*restart)(void);
17
+ void (*yield)(void);
18
+ size_t (*get_free_system_mem)(void);
19
+ size_t (*get_min_free_system_mem)(void); /* All-time low watermark */
20
+ size_t (*get_total_system_mem)(void);
21
+ /** Largest contiguous free block (for diagnosing heap fragmentation —
22
+ * an allocation larger than this fails even if total free is bigger).
23
+ * On platforms without a native largest-block API, implementations
24
+ * may return the same value as get_free_system_mem. */
25
+ size_t (*get_largest_free_system_mem)(void);
26
+ bool (*get_fs_info)(const char* label, size_t* total, size_t* used);
27
+ void (*log)(int level, const char* tag, const char* fmt, ...);
28
+ int (*stdout_write)(const void* buf, size_t len);
29
+ int (*stderr_write)(const void* buf, size_t len);
30
+ int (*stdin_read)(void* buf, size_t len);
31
+ /** Return a unique device identifier string, or NULL if unavailable.
32
+ * On ESP32 this is the base MAC address encoded as Crockford's Base32
33
+ * (10 lowercase chars). The encoding is lossless: decoding yields the
34
+ * original 6 MAC bytes. The returned pointer must remain valid for the
35
+ * lifetime of the platform. */
36
+ const char* (*get_device_id)(void);
37
+ } MIKPlatform;
38
+
39
+ /* Log levels (matching ESP-IDF ESP_LOG_xxx values) */
40
+ #define MIK_LOG_NONE 0
41
+ #define MIK_LOG_ERROR 1
42
+ #define MIK_LOG_WARN 2
43
+ #define MIK_LOG_INFO 3
44
+ #define MIK_LOG_DEBUG 4
45
+ #define MIK_LOG_VERBOSE 5
46
+
47
+ /* Return the canonical uppercase name for a log level ("ERROR", "WARN",
48
+ * "INFO", "DEBUG", "VERBOSE", or "?" for unknown). Used by platform log
49
+ * implementations to produce a consistent `[LEVEL] tag: message` prefix
50
+ * across every target. Keeping this in libmikrojs (rather than letting
51
+ * each platform roll its own) is what makes the format cross-platform:
52
+ * add a new platform port and it inherits the format for free. */
53
+ static inline const char* mik_log_level_name(int level) {
54
+ switch (level) {
55
+ case MIK_LOG_ERROR:
56
+ return "ERROR";
57
+ case MIK_LOG_WARN:
58
+ return "WARN";
59
+ case MIK_LOG_INFO:
60
+ return "INFO";
61
+ case MIK_LOG_DEBUG:
62
+ return "DEBUG";
63
+ case MIK_LOG_VERBOSE:
64
+ return "VERBOSE";
65
+ default:
66
+ return "?";
67
+ }
68
+ }
69
+
70
+ /* Set the platform implementation for the runtime. Must be called before
71
+ * MIK_NewRuntime(). If not called, a default POSIX implementation is used. */
72
+ void MIK_SetPlatform(const MIKPlatform* platform);
73
+
74
+ /* Get the current platform (returns default POSIX if none was set) */
75
+ const MIKPlatform* MIK_GetPlatform(void);
76
+
77
+ /* Default POSIX implementation */
78
+ const MIKPlatform* MIK_DefaultPOSIXPlatform(void);
79
+
80
+ #ifdef __cplusplus
81
+ }
82
+ #endif