@mikrojs/native 0.21.1-next.20260927212749 → 0.22.0

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 CHANGED
@@ -37,7 +37,6 @@ set(MIKROJS_CORE_SOURCES
37
37
  src/fs.cpp
38
38
  src/mem.cpp
39
39
  src/utils.cpp
40
- src/eval_bytecode.cpp
41
40
  src/mik_inspect.cpp
42
41
  src/mik_stdio.cpp
43
42
  src/mik_text_encoding.cpp
@@ -47,6 +46,7 @@ set(MIKROJS_CORE_SOURCES
47
46
  src/mik_wifi_client.cpp
48
47
  src/mik_cbor.cpp
49
48
  src/mik_schema.cpp
49
+ src/mik_test.cpp
50
50
  src/mik_result.cpp
51
51
  src/mik_console.cpp
52
52
  src/mik_sys.cpp
@@ -222,7 +222,6 @@ if(BUILD_TESTING)
222
222
  test/fs_test.cpp
223
223
  test/console_stdio_test.cpp
224
224
  test/cbor_js_test.cpp
225
- test/eval_bytecode_test.cpp
226
225
  test/result_utils_test.cpp
227
226
  test/modules_fs_test.cpp
228
227
  test/sys_test.cpp
@@ -246,6 +245,7 @@ if(BUILD_TESTING)
246
245
  test/sys_codec_test.cpp
247
246
  test/watchdog_test.cpp
248
247
  test/gpio_claim_test.cpp
248
+ test/test_runner_test.cpp
249
249
  )
250
250
 
251
251
  # ── Check-in wire fixtures ───────────────────────────────────────
package/dist/index.d.ts CHANGED
@@ -12,10 +12,11 @@ export declare class MikroRuntime {
12
12
  * as `globalThis._` for follow-up expressions. Mirrors the firmware
13
13
  * REPL's eval path. Returns undefined for `undefined` results. */
14
14
  evalForRepl(code: string, depth?: number): string | undefined;
15
- loop(): Promise<void>;
16
15
  /** Run one iteration of the event loop synchronously. Returns 0 on success. */
17
16
  loopOnce(): number;
18
- stop(): void;
17
+ /** Microseconds until the loop next has work: 0 when it has work now, -1
18
+ * when nothing is scheduled. Lets the caller sleep between loopOnce() calls. */
19
+ nextWakeUs(): number;
19
20
  dispose(): void;
20
21
  /** Register a JS source string as a named virtual module.
21
22
  * Virtual modules are checked by the loader before builtin bytecode,
@@ -1 +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;;;uEAGmE;IACnE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,GAAG,SAAS;IAIxD,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;wFACoF;IACpF,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;IAI5B;;oDAEgD;IAChD,WAAW,IAAI;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC;IAIpD;4DACwD;IACxD,EAAE,IAAI,IAAI;IAIV;;;wCAGoC;IACpC,iBAAiB,IAAI,IAAI;CAG1B;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAC,GAClC,WAAW,GAAG,SAAS,CAEzB;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"}
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;;;uEAGmE;IACnE,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,MAAM,GAAG,SAAS;IAIxD,+EAA+E;IAC/E,QAAQ,IAAI,MAAM;IAIlB;qFACiF;IACjF,UAAU,IAAI,MAAM;IAIpB,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;wFACoF;IACpF,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;IAI5B;;oDAEgD;IAChD,WAAW,IAAI;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC;IAIpD;4DACwD;IACxD,EAAE,IAAI,IAAI;IAIV;;;wCAGoC;IACpC,iBAAiB,IAAI,IAAI;CAG1B;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAC,GAClC,WAAW,GAAG,SAAS,CAEzB;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 CHANGED
@@ -43,15 +43,14 @@ export class MikroRuntime {
43
43
  evalForRepl(code, depth = 2) {
44
44
  return this.native.evalForRepl(code, depth);
45
45
  }
46
- loop() {
47
- return this.native.loop();
48
- }
49
46
  /** Run one iteration of the event loop synchronously. Returns 0 on success. */
50
47
  loopOnce() {
51
48
  return this.native.loopOnce();
52
49
  }
53
- stop() {
54
- this.native.stop();
50
+ /** Microseconds until the loop next has work: 0 when it has work now, -1
51
+ * when nothing is scheduled. Lets the caller sleep between loopOnce() calls. */
52
+ nextWakeUs() {
53
+ return this.native.nextWakeUs();
55
54
  }
56
55
  dispose() {
57
56
  this.native.dispose();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../addon/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../addon/index.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -22,9 +22,8 @@ export interface NativeMikroRuntime {
22
22
  evalModule(filename: string, isMain?: boolean): void;
23
23
  evalModuleContent(filename: string, content: string): void;
24
24
  evalScript(code: string): string | undefined;
25
- loop(): Promise<void>;
26
25
  loopOnce(): number;
27
- stop(): void;
26
+ nextWakeUs(): number;
28
27
  dispose(): void;
29
28
  registerModuleSource(name: string, source: string): void;
30
29
  drainMessages(): HostMessage[];
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../addon/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACrB,QAAQ,IAAI,MAAM,CAAA;IAClB,IAAI,IAAI,IAAI,CAAA;IACZ,OAAO,IAAI,IAAI,CAAA;IACf,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACxD,aAAa,IAAI,WAAW,EAAE,CAAA;IAC9B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;IACnF,aAAa,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5F,eAAe,IAAI,IAAI,CAAA;IACvB,UAAU,IAAI,YAAY,EAAE,CAAA;IAC5B,kBAAkB,IAAI,MAAM,CAAA;IAC5B,WAAW,IAAI;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,CAAA;IACpD,EAAE,IAAI,IAAI,CAAA;IACV,iBAAiB,IAAI,IAAI,CAAA;IACzB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,KAAK,OAAO,CAAC,EAAE,mBAAmB,KAAK,kBAAkB,CAAA;IACvE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACjC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IACjF,UAAU,CACR,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAC,GAClC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG,SAAS,CAAA;CAC7D"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../addon/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAA;IACpD,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1D,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,QAAQ,IAAI,MAAM,CAAA;IAClB,UAAU,IAAI,MAAM,CAAA;IACpB,OAAO,IAAI,IAAI,CAAA;IACf,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACxD,aAAa,IAAI,WAAW,EAAE,CAAA;IAC9B,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7C,eAAe,CAAC,EAAE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,GAAG,IAAI,CAAA;IACnF,aAAa,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5F,eAAe,IAAI,IAAI,CAAA;IACvB,UAAU,IAAI,YAAY,EAAE,CAAA;IAC5B,kBAAkB,IAAI,MAAM,CAAA;IAC5B,WAAW,IAAI;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAC,CAAA;IACpD,EAAE,IAAI,IAAI,CAAA;IACV,iBAAiB,IAAI,IAAI,CAAA;IACzB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;CAC9D;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,KAAK,OAAO,CAAC,EAAE,mBAAmB,KAAK,kBAAkB,CAAA;IACvE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;IACjC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAA;IACjF,UAAU,CACR,IAAI,EAAE,OAAO,EACb,OAAO,CAAC,EAAE;QAAC,aAAa,CAAC,EAAE,OAAO,CAAA;KAAC,GAClC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAC,GAAG,SAAS,CAAA;CAC7D"}
@@ -25,7 +25,6 @@ void* mik__js_realloc(void* ptr, size_t size);
25
25
  * mik__js_realloc relies on the flag staying consistent with the heap
26
26
  * the original pointer came from. */
27
27
  void mik__set_quickjs_heap_psram(bool enable);
28
- bool mik__is_quickjs_heap_psram(void);
29
28
 
30
29
  #ifdef MIK_OOM_INJECT
31
30
  #include <stdint.h>
@@ -19,7 +19,8 @@ typedef struct MIKRunOptions {
19
19
  * IO-bound workloads this is invisible against networking and IO
20
20
  * costs. No effect on hosts and chips without PSRAM. Defaults false
21
21
  * for backward compatibility; the firmware bootstrap flips it on
22
- * when CONFIG_MIKROJS_QUICKJS_HEAP_PSRAM is set. */
22
+ * when CONFIG_MIKROJS_QUICKJS_HEAP_PSRAM is set and PSRAM was found
23
+ * at boot. */
23
24
  bool use_psram_heap;
24
25
  } MIKRunOptions;
25
26
 
@@ -125,6 +126,10 @@ void MIK_SetFSLimit(MIKRuntime* mik_rt, size_t limit);
125
126
  * the default (65536). */
126
127
  void MIK_SetFSReadMax(MIKRuntime* mik_rt, size_t bytes);
127
128
  int MIK_Loop(MIKRuntime* mik_rt);
129
+ /* End the serve loop's wait so work just queued from another task runs now.
130
+ * Call after the enqueue; no-op without the platform hook. Interrupt handlers
131
+ * use the platform's own ISR variant (MIK_WakeFromISR on ESP32). */
132
+ void MIK_Wake(void);
128
133
  void MIK_Stop(MIKRuntime* mik_rt);
129
134
 
130
135
  /* True once the runtime has entered a halted state — set by the promise
@@ -139,11 +144,6 @@ bool MIK_IsStopRequested(MIKRuntime* mik_rt);
139
144
  void MIK_SetEnvVar(MIKRuntime* mik_rt, const char* key, const char* value);
140
145
  void MIK_RebuildEnv(MIKRuntime* mik_rt);
141
146
 
142
- /* Native module registration */
143
- typedef void (*MIKNativeModuleInitFn)(JSContext* ctx);
144
- void MIK_RegisterNativeModuleInit(MIKRuntime* mik_rt, const char* name,
145
- MIKNativeModuleInitFn init_fn);
146
-
147
147
  /* Loop consumer registration */
148
148
  typedef void (*MIKLoopConsumeFn)(JSContext* ctx);
149
149
  typedef void (*MIKLoopDestroyFn)(JSContext* ctx);
@@ -19,6 +19,13 @@ typedef struct MIKPlatform {
19
19
  * deep sleep (hosts), where callers fall back to restart(). */
20
20
  void (*deep_sleep_us)(uint64_t us);
21
21
  void (*yield)(void);
22
+ /** Block the calling task until wake() is called or `timeout_us` elapses.
23
+ * A wake that arrives before the wait is kept: the next wait returns at
24
+ * once. NULL where the platform has no blocking primitive; the serve
25
+ * loop then falls back to yield() between passes. */
26
+ void (*wait)(int64_t timeout_us);
27
+ /** End a wait in progress, from task context. NULL when wait is NULL. */
28
+ void (*wake)(void);
22
29
  /** Feed the hardware task watchdog for the calling task. NULL where the
23
30
  * platform has none (hosts) or the watchdog is compiled out. */
24
31
  void (*feed_watchdog)(void);
@@ -93,6 +100,12 @@ typedef struct MIKPlatform {
93
100
  * "unknown". The returned pointer must remain valid for the lifetime
94
101
  * of the platform. */
95
102
  const char* (*get_reset_reason)(void);
103
+ /** Bring up the TCP/IP stack if the platform has one that starts on
104
+ * demand. Called before a networking module creates its first socket;
105
+ * idempotent. NULL where sockets need no setup (hosts). On ESP32 the
106
+ * stack otherwise starts only as a side effect of the wifi or http
107
+ * module loading, and lwip aborts on a socket call before that. */
108
+ void (*net_init)(void);
96
109
  } MIKPlatform;
97
110
 
98
111
  /* Log levels (matching ESP-IDF ESP_LOG_xxx values) */
@@ -36,12 +36,6 @@ typedef struct MIKTimers {
36
36
  uint32_t next_timer_id = 1;
37
37
  } MIKTimerRegistry;
38
38
 
39
- /* Registered native module init function */
40
- struct MIKNativeModuleEntry {
41
- std::string name;
42
- MIKNativeModuleInitFn init_fn;
43
- };
44
-
45
39
  /* Registered loop consumer */
46
40
  struct MIKLoopConsumerEntry {
47
41
  MIKLoopConsumeFn consume_fn;
@@ -60,12 +54,32 @@ struct MIKRejectedPromise {
60
54
  /* Observable dispatch queue (defined in mik_observable.cpp). */
61
55
  struct MIKObservableDispatch;
62
56
 
57
+ /* Result property names, atomized once so building a Result skips hashing
58
+ * the C string. JS_ATOM_NULL until mik__result_init has run. */
59
+ struct MIKResultAtoms {
60
+ JSAtom ok;
61
+ JSAtom value;
62
+ JSAtom error;
63
+ JSAtom err;
64
+ JSAtom code;
65
+ JSAtom message;
66
+ JSAtom name;
67
+ };
68
+
69
+ /* Lookups mik_inspect would otherwise repeat for every value; filled by
70
+ * mik__inspect_register. */
71
+ struct MIKInspectCache {
72
+ JSAtom inspect_symbol; /* Symbol.for('mikrojs.inspect') */
73
+ JSAtom to_string_tag; /* Symbol.toStringTag */
74
+ JSValue object_proto; /* Object.prototype */
75
+ JSClassID object_class_id; /* class of plain objects */
76
+ };
77
+
63
78
  struct MIKRuntime {
64
79
  MIKRunOptions options;
65
80
  MIKConfig config;
66
81
  JSRuntime* rt;
67
82
  JSContext* ctx;
68
- bool is_worker;
69
83
  bool freeing;
70
84
  bool stop_requested; /* Set by promise rejection tracker to stop the loop */
71
85
  /* Set by MIK_EnableTestHelpers — the test supervisor wants stop_requested
@@ -108,7 +122,6 @@ struct MIKRuntime {
108
122
  * this throw FSError(EFBIG); callers use open() for streaming. */
109
123
  size_t fs_read_max;
110
124
  MIKTimerRegistry* timers;
111
- std::vector<MIKNativeModuleEntry> native_modules;
112
125
  std::vector<MIKLoopConsumerEntry> loop_consumers;
113
126
  /* Handles kept alive by MIK_KeepHandle; each entry owns a reference. */
114
127
  std::vector<JSValue> kept_handles;
@@ -132,6 +145,10 @@ struct MIKRuntime {
132
145
  * mik__result_ok_void. Safe to share because Result is immutable by
133
146
  * convention, and the singleton is frozen + non-extensible. */
134
147
  JSValue result_ok_void_singleton;
148
+ /* Freed in MIK_FreeRuntime after JS_FreeContext, once nothing can build a Result. */
149
+ MIKResultAtoms result_atoms;
150
+ /* Values freed before JS_FreeContext, atoms after it. */
151
+ MIKInspectCache inspect_cache;
135
152
  /* Shared BodyConsumedError constructor for the native mikro/http/helpers
136
153
  * module. Created lazily on first http module init, freed in
137
154
  * MIK_FreeRuntime. */
@@ -203,10 +220,20 @@ struct MIKRuntime {
203
220
  void mik__pub_fs_register(JSContext* ctx);
204
221
  void mik__stdio_init(JSContext* ctx, JSValue ns);
205
222
  void mik__sys_api_init(JSContext* ctx, JSValue ns);
206
- /* Board name of this build: MIK_BOARD_NAME if defined, else "<chip>-generic"
207
- * on device, "generic" on host. Static storage, never NULL. */
223
+ /* Name of this build: MIK_BOARD_NAME if defined, else "<chip>-generic" on
224
+ * device, "generic" on host. Static storage, never NULL. */
225
+ const char* mik__firmware_name(void);
226
+ /* The board: the name `mikro flash` wrote into the image when it flashed the
227
+ * generic firmware for a board, else mik__firmware_name(). Static storage,
228
+ * never NULL. */
208
229
  const char* mik__board_name(void);
209
230
  void mik__text_encoding_init(JSContext* ctx, JSValue global);
231
+ /* UTF-8 pass shared by TextDecoder and the http body drain: each invalid byte
232
+ * becomes U+FFFD. A null `out` only counts; returns the output length. With
233
+ * `hold_tail`, an incomplete final sequence is left out and its byte count
234
+ * stored in *tail. */
235
+ size_t mik__utf8_replace(const uint8_t* in, size_t len, bool hold_tail, uint8_t* out,
236
+ size_t* tail);
210
237
  void mik__abort_init(JSContext* ctx, JSValue global_obj);
211
238
 
212
239
  JSValue mik_new_error(JSContext* ctx, int err);
@@ -215,6 +242,10 @@ JSValue mik_throw_errno(JSContext* ctx, int err);
215
242
  void mik__execute_jobs(JSContext* ctx);
216
243
  /* End-of-turn unhandled-rejection check; called after each microtask drain. */
217
244
  void mik__flush_unhandled_rejections(JSContext* ctx);
245
+ /* Microseconds until MIK_Loop next has work: 0 now, -1 none. Counts timers, the
246
+ * restart, feed and awake deadlines and the UDP poll. Code that queues work for a
247
+ * loop consumer calls MIK_Wake; a consumer's own deadlines wait for the caller's cap. */
248
+ int64_t mik__next_wake_us(MIKRuntime* mik_rt);
218
249
  JSModuleDef* mik__load_builtin(JSContext* ctx, const char* name);
219
250
  int mik__load_file(JSContext* ctx, DynBuf* dbuf, const char* filename);
220
251
  void mik__resolve_fs_path(JSContext* ctx, const char* module_name, char* out, size_t out_size);
@@ -244,16 +275,7 @@ bool mik__is_unloadable_namespace(JSContext* ctx, JSValueConst ns);
244
275
 
245
276
  int js_module_set_import_meta(JSContext* ctx, JSValue func_val, bool use_realpath, bool is_main);
246
277
 
247
- JSValue mik__get_args(JSContext* ctx);
248
-
249
- int mik__eval_bytecode(JSContext* ctx, const uint8_t* buf, size_t buf_len, bool check_promise);
250
-
251
-
252
- void mik__sab_free(void* opaque, void* ptr);
253
- void mik__sab_dup(void* opaque, void* ptr);
254
-
255
278
  MIKTimerRegistry* MIK_NewTimerRegistry(void);
256
- MIKRuntime* MIK_NewRuntimeWorker(void);
257
279
  MIKRuntime* MIK_NewRuntimeInternal(MIKRunOptions* options);
258
280
  JSValue MIK_EvalScript(JSContext* ctx, const char* filename);
259
281
  JSValue MIK_EvalModule(JSContext* ctx, const char* filename, bool is_main);
@@ -311,6 +333,9 @@ JSModuleDef* mik__result_init(JSContext* ctx);
311
333
 
312
334
  /* UDP module (mik_udp.cpp) */
313
335
  JSModuleDef* mik__udp_init(JSContext* ctx);
336
+ /* True while a bound socket is open on ctx. Its datagrams are polled with
337
+ * recvfrom once per loop pass, so mik__next_wake_us caps the wait meanwhile. */
338
+ bool mik__udp_has_open_sockets(JSContext* ctx);
314
339
 
315
340
  /* Observable module (mik_observable.cpp) */
316
341
  JSModuleDef* mik__observable_init(JSContext* ctx);
@@ -323,6 +348,9 @@ JSModuleDef* mik__observable_operators_load(JSContext* ctx);
323
348
  int mik__observable_multicast_new(JSContext* ctx, JSValue* observable, JSValue* next,
324
349
  JSValue* complete);
325
350
 
351
+ /* Test runner module (mik_test.cpp): mikro/test, C-module table in modules.cpp. */
352
+ JSModuleDef* mik__test_load(JSContext* ctx);
353
+
326
354
  /* Watchdog (mik_watchdog.cpp). */
327
355
  /* Start a fresh blocking budget: top of each MIK_Loop pass, eval entry
328
356
  * points, REPL eval, and on return from a deliberately blocking native
@@ -369,6 +397,11 @@ void mik__repl_set_paused(bool paused);
369
397
  /* Header size: 1 (type) + 4 (u32le length) */
370
398
  #define MIK_PROTO_HEADER_SIZE 5
371
399
 
400
+ /* Revision of this command set, sent in MSG_READY as "proto" so the host
401
+ * knows which commands the device answers. Absent means 0.
402
+ * 1: MIK_CMD_DEPLOY_CHECKSUM_LIST and MIK_CMD_DEPLOY_KEEP_MANY. */
403
+ #define MIK_PROTO_REV 1
404
+
372
405
  /* Device → CLI message types */
373
406
  #define MIK_MSG_READY 0x01
374
407
  #define MIK_MSG_LOG 0x02
@@ -437,6 +470,14 @@ void mik__repl_set_paused(bool paused);
437
470
  * u8 status (0 none | 1 ok | 2 fail) | u16le chk_len | chk
438
471
  * | u16le reason_len | reason | u16le detail_len | detail. */
439
472
  #define MIK_CMD_DEPLOY_RESULT 0x2E
473
+ /* Every checksum the device holds, in one reply. No payload. Reply is
474
+ * MIK_MSG_OK with: u16le file_count | one "<sha256 hex> <name>\n" line per
475
+ * manifest entry whose file is on disk. file_count counts every manifest
476
+ * entry, so the host can tell the device holds files the build no longer has. */
477
+ #define MIK_CMD_DEPLOY_CHECKSUM_LIST 0x2F
478
+ /* KEEP for several files. Payload: repeated u16le name_len | name. Staged in
479
+ * order; the first failure ends the batch and MIK_MSG_ERR names the file. */
480
+ #define MIK_CMD_DEPLOY_KEEP_MANY 0x30
440
481
 
441
482
  #define MIK_CMD_CONFIG_LIST 0x40
442
483
  #define MIK_CMD_CONFIG_SET 0x41
@@ -11,19 +11,24 @@
11
11
  struct AssertionInfo {
12
12
  const char* file_line; // filename:line
13
13
  const char* message;
14
- const char* function;
15
14
  };
16
15
 
17
- #define ERROR_AND_ABORT(expr) \
18
- do { \
19
- static const struct AssertionInfo args = {__FILE__ ":" STRINGIFY(__LINE__), #expr, \
20
- PRETTY_FUNCTION_NAME}; \
21
- mik_assert(args); \
16
+ /* Base name only: __FILE__ would put the build machine's absolute path in flash at every
17
+ * call site. */
18
+ #ifdef __FILE_NAME__
19
+ #define MIK__FILE_NAME __FILE_NAME__
20
+ #else
21
+ #define MIK__FILE_NAME __FILE__
22
+ #endif
23
+
24
+ #define ERROR_AND_ABORT(expr) \
25
+ do { \
26
+ static const struct AssertionInfo args = {MIK__FILE_NAME ":" STRINGIFY(__LINE__), #expr}; \
27
+ mik_assert(args); \
22
28
  } while (0)
23
29
 
24
30
  #define MIK__LIKELY(expr) __builtin_expect(!!(expr), 1)
25
31
  #define MIK__UNLIKELY(expr) __builtin_expect(!!(expr), 0)
26
- #define PRETTY_FUNCTION_NAME __PRETTY_FUNCTION__
27
32
 
28
33
  #define STRINGIFY_(x) #x
29
34
  #define STRINGIFY(x) STRINGIFY_(x)
@@ -110,13 +115,13 @@ bool MIK_IsPromisePending(JSContext* ctx, MIKPromise* p);
110
115
  void MIK_FreePromise(JSContext* ctx, MIKPromise* p);
111
116
  void MIK_FreePromiseRT(JSRuntime* rt, MIKPromise* p);
112
117
  void MIK_ClearPromise(JSContext* ctx, MIKPromise* p);
113
- void MIK_MarkPromise(JSRuntime* rt, MIKPromise* p, JS_MarkFunc* mark_func);
114
118
  void MIK_SettlePromise(JSContext* ctx, MIKPromise* p, bool is_reject, int argc, JSValue* argv);
115
119
  void MIK_ResolvePromise(JSContext* ctx, MIKPromise* p, int argc, JSValue* argv);
116
120
  void MIK_RejectPromise(JSContext* ctx, MIKPromise* p, int argc, JSValue* argv);
117
121
  JSValue MIK_NewResolvedPromise(JSContext* ctx, int argc, JSValue* argv);
118
122
  JSValue MIK_NewRejectedPromise(JSContext* ctx, int argc, JSValue* argv);
119
123
 
124
+ /* A Uint8Array over `data` (js_malloc'd). Takes ownership of `data`, also on failure. */
120
125
  JSValue MIK_NewUint8Array(JSContext* ctx, uint8_t* data, size_t size);
121
126
 
122
127
  #define MIK_THROW_ARG_ERR(ctx, argno, expected) \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikrojs/native",
3
- "version": "0.21.1-next.20260927212749",
3
+ "version": "0.22.0",
4
4
  "description": "Mikro.js C++ runtime library and Node.js native addon",
5
5
  "keywords": [
6
6
  "esp32",
@@ -86,14 +86,14 @@
86
86
  "./runtime/wifi/types": "./runtime/wifi/types.ts"
87
87
  },
88
88
  "dependencies": {
89
- "@mikrojs/quickjs": "0.21.1-next.20260927212749+7f87381",
89
+ "@mikrojs/quickjs": "0.22.0",
90
90
  "cmake-js": "^8.0.0",
91
91
  "node-addon-api": "^8.9.2",
92
92
  "node-gyp-build": "^4.8.4"
93
93
  },
94
94
  "devDependencies": {
95
- "@mikrojs/registry": "0.21.1-next.20260927212749+7f87381",
96
- "@mikrojs/schema": "0.21.1-next.20260927212749+7f87381",
95
+ "@mikrojs/registry": "0.22.0",
96
+ "@mikrojs/schema": "0.22.0",
97
97
  "@swc/core": "^1.16.2",
98
98
  "@types/node": "^24.12.2",
99
99
  "esbuild": "^0.28.2",
@@ -23,7 +23,6 @@
23
23
  {"name": "stdio"},
24
24
  {"name": "stream"},
25
25
  {"name": "sys"},
26
- {"name": "test"},
27
26
  {"name": "udp"},
28
27
  {"name": "watchdog"},
29
28
  {"name": "ble", "native": "ble", "feature": "ble", "when": "ble"},
@@ -38,6 +37,7 @@
38
37
  {"name": "http/helpers", "bytecode": false},
39
38
  {"name": "observable/operators", "bytecode": false},
40
39
  {"name": "inspect", "bytecode": false},
40
+ {"name": "test", "bytecode": false},
41
41
  {"name": "wifi", "bytecode": false, "native": "wifi", "feature": "wifi", "when": "wifi"}
42
42
  ]
43
43
  }
@@ -98,8 +98,9 @@ export declare const version: string
98
98
  export type BoardFeature = 'wifi' | 'ble' | 'bt' | 'ieee802154'
99
99
 
100
100
  export interface BoardInfo {
101
- /** Board name from the firmware build (e.g. "xiao-esp32c6"). A build for no
102
- * particular board is "<chip>-generic" (e.g. "esp32c6-generic"). */
101
+ /** The board (e.g. "@acme/devboard"). The generic firmware reports
102
+ * "<chip>-generic" (e.g. "esp32c6-generic"), or the name of the board it was
103
+ * flashed for. */
103
104
  name: string
104
105
  /** Chip target (e.g. "esp32c6") or "host" */
105
106
  chip: string
@@ -148,6 +149,8 @@ export declare function setDeviceName(value: DeviceName): void
148
149
 
149
150
  /** Firmware build identifiers */
150
151
  export declare const firmware: {
152
+ /** The build (e.g. "esp32c6-generic", "@acme/devboard") */
153
+ readonly name: string
151
154
  /** ELF SHA256 hash on ESP32, "dev" on host */
152
155
  readonly hash: string
153
156
  /** Build date and time */
package/src/mem.cpp CHANGED
@@ -143,8 +143,8 @@ void* mik__realloc(void* ptr, size_t size) {
143
143
  * platform's malloc_psram first; if the platform can't satisfy the request
144
144
  * (no PSRAM, or PSRAM exhausted), fall back to libc malloc so the runtime
145
145
  * keeps working. The fallback only matters on host builds and in PSRAM-OOM
146
- * edge cases. Under normal ESP32 operation with CONFIG_SPIRAM=y, every
147
- * allocation lands in PSRAM. */
146
+ * edge cases: the ESP32 firmware sets the flag only when PSRAM was found
147
+ * at boot, so every allocation lands in PSRAM. */
148
148
 
149
149
  static bool g_quickjs_heap_psram = false;
150
150
 
@@ -152,10 +152,6 @@ void mik__set_quickjs_heap_psram(bool enable) {
152
152
  g_quickjs_heap_psram = enable;
153
153
  }
154
154
 
155
- bool mik__is_quickjs_heap_psram(void) {
156
- return g_quickjs_heap_psram;
157
- }
158
-
159
155
  void* mik__js_malloc(size_t size) {
160
156
  if (OOM_INJECT_FAIL()) return nullptr;
161
157
  size_t hdr = hdr_size();
@@ -382,6 +382,8 @@ void hc_iterator_close(JSContext* ctx, JSValue it) {
382
382
  void hc_drain_finalize(JSContext* ctx, JSValue st) {
383
383
  JSValue resolve = JS_GetPropertyStr(ctx, st, "res");
384
384
  JSValue arr = JS_GetPropertyStr(ctx, st, "arr");
385
+ /* The state stops keeping the chunks alive: freeing `arr` after the copy frees them. */
386
+ JS_SetPropertyStr(ctx, st, "arr", JS_UNDEFINED);
385
387
  JSValue mode_v = JS_GetPropertyStr(ctx, st, "mode");
386
388
  int32_t mode = 0;
387
389
  JS_ToInt32(ctx, &mode, mode_v);
@@ -401,7 +403,8 @@ void hc_drain_finalize(JSContext* ctx, JSValue st) {
401
403
  return;
402
404
  }
403
405
 
404
- /* Merge chunks into one contiguous buffer. */
406
+ /* Merge chunks into one contiguous buffer. The spare byte NUL-terminates
407
+ * the buffer for the JSON parser. */
405
408
  size_t total = 0;
406
409
  for (uint32_t i = 0; i < nchunks; i++) {
407
410
  JSValue chunk = JS_GetPropertyUint32(ctx, arr, i);
@@ -414,7 +417,7 @@ void hc_drain_finalize(JSContext* ctx, JSValue st) {
414
417
  }
415
418
  JS_FreeValue(ctx, chunk);
416
419
  }
417
- uint8_t* buf = static_cast<uint8_t*>(js_malloc(ctx, total ? total : 1));
420
+ uint8_t* buf = static_cast<uint8_t*>(js_malloc(ctx, total + 1));
418
421
  if (!buf) {
419
422
  JS_FreeValue(ctx, arr);
420
423
  JS_FreeValue(ctx, resolve);
@@ -439,44 +442,58 @@ void hc_drain_finalize(JSContext* ctx, JSValue st) {
439
442
 
440
443
  JSValue settled = JS_UNDEFINED;
441
444
  if (mode == DRAIN_BYTES) {
442
- settled = mik__result_ok(ctx, JS_NewUint8ArrayCopy(ctx, buf, total));
443
- } else {
444
- /* Decode through the runtime's TextDecoder for exact TS parity
445
- * (invalid-sequence replacement included). */
446
- JSValue g = JS_GetGlobalObject(ctx);
447
- JSValue td_ctor = JS_GetPropertyStr(ctx, g, "TextDecoder");
448
- JS_FreeValue(ctx, g);
449
- JSValue td = JS_CallConstructor(ctx, td_ctor, 0, nullptr);
450
- JS_FreeValue(ctx, td_ctor);
451
- JSValue u8 = JS_NewUint8ArrayCopy(ctx, buf, total);
452
- JSValue text = hc_invoke(ctx, td, "decode", 1, &u8);
453
- JS_FreeValue(ctx, u8);
454
- JS_FreeValue(ctx, td);
455
- if (JS_IsException(text)) {
445
+ /* MIK_NewUint8Array takes ownership of buf, also on failure. */
446
+ JSValue u8 = MIK_NewUint8Array(ctx, buf, total);
447
+ if (JS_IsException(u8)) {
448
+ JS_FreeValue(ctx, resolve);
449
+ hc_drain_reject_exception(ctx, st);
450
+ return;
451
+ }
452
+ hc_settle(ctx, resolve, mik__result_ok(ctx, u8));
453
+ JS_FreeValue(ctx, resolve);
454
+ return;
455
+ }
456
+
457
+ /* Invalid UTF-8 is repaired the way this runtime's TextDecoder does it (U+FFFD per bad
458
+ * byte), so text() and json() match TextDecoder.decode(). */
459
+ size_t tail = 0;
460
+ size_t fixed_len = mik__utf8_replace(buf, total, false, nullptr, &tail);
461
+ if (fixed_len != total) {
462
+ uint8_t* fixed = static_cast<uint8_t*>(js_malloc(ctx, fixed_len + 1));
463
+ if (!fixed) {
456
464
  js_free(ctx, buf);
457
465
  JS_FreeValue(ctx, resolve);
458
466
  hc_drain_reject_exception(ctx, st);
459
467
  return;
460
468
  }
461
- if (mode == DRAIN_TEXT) {
462
- settled = mik__result_ok(ctx, text);
469
+ mik__utf8_replace(buf, total, false, fixed, &tail);
470
+ js_free(ctx, buf);
471
+ buf = fixed;
472
+ total = fixed_len;
473
+ }
474
+
475
+ if (mode == DRAIN_TEXT) {
476
+ JSValue text = JS_NewStringLen(ctx, reinterpret_cast<const char*>(buf), total);
477
+ js_free(ctx, buf);
478
+ if (JS_IsException(text)) {
479
+ JS_FreeValue(ctx, resolve);
480
+ hc_drain_reject_exception(ctx, st);
481
+ return;
482
+ }
483
+ settled = mik__result_ok(ctx, text);
484
+ } else {
485
+ buf[total] = 0;
486
+ JSValue parsed = JS_ParseJSON(ctx, reinterpret_cast<const char*>(buf), total, "<json>");
487
+ js_free(ctx, buf);
488
+ if (JS_IsException(parsed)) {
489
+ JSValue exc = JS_GetException(ctx);
490
+ std::string msg = hc_error_message(ctx, exc);
491
+ JS_FreeValue(ctx, exc);
492
+ settled = mik__result_err_named(ctx, "InvalidJson", "%s", msg.c_str());
463
493
  } else {
464
- size_t tlen = 0;
465
- const char* ts = JS_ToCStringLen(ctx, &tlen, text);
466
- JSValue parsed = JS_ParseJSON(ctx, ts ? ts : "", tlen, "<json>");
467
- JS_FreeCString(ctx, ts);
468
- JS_FreeValue(ctx, text);
469
- if (JS_IsException(parsed)) {
470
- JSValue exc = JS_GetException(ctx);
471
- std::string msg = hc_error_message(ctx, exc);
472
- JS_FreeValue(ctx, exc);
473
- settled = mik__result_err_named(ctx, "InvalidJson", "%s", msg.c_str());
474
- } else {
475
- settled = mik__result_ok(ctx, parsed);
476
- }
494
+ settled = mik__result_ok(ctx, parsed);
477
495
  }
478
496
  }
479
- js_free(ctx, buf);
480
497
  hc_settle(ctx, resolve, settled);
481
498
  JS_FreeValue(ctx, resolve);
482
499
  }