@mikrojs/native 0.18.2 → 0.19.0-pr-352.20260829215534

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 (43) hide show
  1. package/CMakeLists.txt +25 -2
  2. package/include/mikrojs/mem.h +4 -0
  3. package/include/mikrojs/ota_client.h +3 -3
  4. package/include/mikrojs/platform.h +8 -0
  5. package/include/mikrojs/private.h +28 -0
  6. package/package.json +4 -5
  7. package/prebuilds/darwin-arm64/mikrojs.napi.node +0 -0
  8. package/prebuilds/linux-arm64/mikrojs.napi.node +0 -0
  9. package/prebuilds/linux-x64/mikrojs.napi.node +0 -0
  10. package/runtime/http/helpers.ts +5 -0
  11. package/runtime/internal.d.ts +41 -2
  12. package/runtime/ota/client.ts +4 -0
  13. package/runtime/ota/ota.ts +4 -0
  14. package/runtime/ota/types.ts +75 -0
  15. package/runtime/schema/schema.ts +25 -3
  16. package/runtime/schema/types.ts +193 -15
  17. package/runtime/sys/types.ts +11 -1
  18. package/runtime/test/test.ts +6 -2
  19. package/runtime/wifi/types.ts +3 -0
  20. package/scripts/gen-schema-fixtures.js +317 -0
  21. package/src/mem.cpp +83 -37
  22. package/src/mik_app_config.cpp +9 -1
  23. package/src/mik_http_client.cpp +1357 -0
  24. package/src/mik_ota_client.cpp +3 -3
  25. package/src/mik_repl.cpp +44 -5
  26. package/src/mik_schema.cpp +892 -0
  27. package/src/mik_sys.cpp +9 -1
  28. package/src/mik_wifi_client.cpp +742 -0
  29. package/src/mikrojs.cpp +34 -8
  30. package/src/modules.cpp +66 -0
  31. package/dist/runtime/schema/core.d.ts +0 -115
  32. package/dist/runtime/schema/core.d.ts.map +0 -1
  33. package/dist/runtime/schema/core.js +0 -259
  34. package/dist/runtime/schema/core.js.map +0 -1
  35. package/dist/runtime/schema/shared.d.ts +0 -54
  36. package/dist/runtime/schema/shared.d.ts.map +0 -1
  37. package/dist/runtime/schema/shared.js +0 -489
  38. package/dist/runtime/schema/shared.js.map +0 -1
  39. package/runtime/http/native.ts +0 -160
  40. package/runtime/http/request.ts +0 -25
  41. package/runtime/schema/core.ts +0 -539
  42. package/runtime/schema/shared.ts +0 -494
  43. package/runtime/wifi/wifi.ts +0 -191
package/src/mem.cpp CHANGED
@@ -9,15 +9,56 @@
9
9
 
10
10
  /*
11
11
  * QuickJS uses malloc_usable_size to track memory consumption against its
12
- * memory limit. ESP-IDF lacks a standard malloc_usable_size, and the
13
- * heap_caps_get_allocated_size alternative reports block sizes including
14
- * allocator overhead, causing QuickJS to over-count usage.
12
+ * memory limit. When the platform reports live-allocation sizes
13
+ * (malloc_usable_size hook: libc malloc_usable_size / malloc_size,
14
+ * heap_caps_get_allocated_size on ESP-IDF), allocations are returned as-is
15
+ * and QuickJS accounts blocks by their real (rounded-up) size.
15
16
  *
16
- * We prepend each allocation with a size_t header storing the requested size.
17
+ * Without the hook, each allocation is prepended with a size_t header
18
+ * storing the requested size. That costs one word of RAM per live block —
19
+ * ~13 KB across a loaded app's ~3400 blocks on a 32-bit device — which is
20
+ * why the hook path is preferred.
21
+ *
22
+ * The mode is latched at the first allocation and never changes, so every
23
+ * pointer is freed the same way it was allocated. Platforms install before
24
+ * the first runtime exists (ESP32 and node have theirs as the compile-time
25
+ * default), so the latch sees the final platform. The latch is a single
26
+ * word-sized store (null = unlatched, mik__hdr_usable_size = header mode),
27
+ * so concurrent first allocations on a dual-core target can at worst both
28
+ * compute and store the same value — there is no two-variable ordering to
29
+ * observe half-done.
17
30
  */
18
31
 
19
32
  #define HDR_SIZE sizeof(size_t)
20
33
 
34
+ static inline size_t hdr_read(void* user) {
35
+ size_t sz;
36
+ memcpy(&sz, static_cast<char*>(user) - HDR_SIZE, sizeof(sz));
37
+ return sz;
38
+ }
39
+
40
+ /* Header-mode usable_size; doubles as the latch marker for that mode. */
41
+ static size_t mik__hdr_usable_size(const void* ptr) {
42
+ return hdr_read(const_cast<void*>(ptr));
43
+ }
44
+
45
+ typedef size_t (*MIKUsableSizeFn)(const void*);
46
+ static MIKUsableSizeFn g_usable_size_fn = nullptr; /* null = not latched yet */
47
+
48
+ static inline MIKUsableSizeFn usable_size_fn(void) {
49
+ MIKUsableSizeFn fn = g_usable_size_fn;
50
+ if (!fn) {
51
+ const MIKPlatform* p = MIK_GetPlatform();
52
+ fn = (p && p->malloc_usable_size) ? p->malloc_usable_size : mik__hdr_usable_size;
53
+ g_usable_size_fn = fn;
54
+ }
55
+ return fn;
56
+ }
57
+
58
+ static inline size_t hdr_size(void) {
59
+ return usable_size_fn() == mik__hdr_usable_size ? HDR_SIZE : 0;
60
+ }
61
+
21
62
  /* Fault injection for the host OOM tests: fail the JS-heap allocators after
22
63
  * a countdown, and keep a net live-allocation counter across every allocator
23
64
  * here (all of them free through mik__free, so one counter balances). */
@@ -39,6 +80,11 @@ static bool oom_inject_should_fail(void) {
39
80
  g_oom_countdown--;
40
81
  return false;
41
82
  }
83
+
84
+ void mik__usable_size_latch_override(size_t (*fn)(const void*)) {
85
+ g_usable_size_fn = fn ? fn : mik__hdr_usable_size;
86
+ }
87
+
42
88
  #define OOM_INJECT_FAIL() oom_inject_should_fail()
43
89
  #define LIVE_ALLOCS_ADD(d) (g_live_allocs += (d))
44
90
  #else
@@ -46,27 +92,22 @@ static bool oom_inject_should_fail(void) {
46
92
  #define LIVE_ALLOCS_ADD(d) ((void)0)
47
93
  #endif
48
94
 
49
- static inline size_t hdr_read(void* user) {
50
- size_t sz;
51
- memcpy(&sz, static_cast<char*>(user) - HDR_SIZE, sizeof(sz));
52
- return sz;
53
- }
54
-
55
- static inline void hdr_write(void* raw, size_t sz) {
56
- memcpy(raw, &sz, sizeof(sz));
95
+ static inline void hdr_write(void* raw, size_t size, size_t hdr) {
96
+ if (hdr) memcpy(raw, &size, sizeof(size));
57
97
  }
58
98
 
59
99
  size_t mik__malloc_usable_size(const void* ptr) {
60
100
  if (!ptr) return 0;
61
- return hdr_read(const_cast<void*>(ptr));
101
+ return usable_size_fn()(ptr);
62
102
  }
63
103
 
64
104
  void* mik__malloc(size_t size) {
65
- void* raw = malloc(size + HDR_SIZE);
105
+ size_t hdr = hdr_size();
106
+ void* raw = malloc(size + hdr);
66
107
  if (!raw) return nullptr;
67
- hdr_write(raw, size);
108
+ hdr_write(raw, size, hdr);
68
109
  LIVE_ALLOCS_ADD(1);
69
- return static_cast<char*>(raw) + HDR_SIZE;
110
+ return static_cast<char*>(raw) + hdr;
70
111
  }
71
112
 
72
113
  void* mik__mallocz(size_t size) { return mik__calloc(1, size); }
@@ -74,26 +115,28 @@ void* mik__mallocz(size_t size) { return mik__calloc(1, size); }
74
115
  void* mik__calloc(size_t count, size_t size) {
75
116
  if (size && count > SIZE_MAX / size) return nullptr;
76
117
  size_t total = count * size;
77
- void* raw = calloc(1, total + HDR_SIZE);
118
+ size_t hdr = hdr_size();
119
+ void* raw = calloc(1, total + hdr);
78
120
  if (!raw) return nullptr;
79
- hdr_write(raw, total);
121
+ hdr_write(raw, total, hdr);
80
122
  LIVE_ALLOCS_ADD(1);
81
- return static_cast<char*>(raw) + HDR_SIZE;
123
+ return static_cast<char*>(raw) + hdr;
82
124
  }
83
125
 
84
126
  void mik__free(void* ptr) {
85
127
  if (!ptr) return;
86
128
  LIVE_ALLOCS_ADD(-1);
87
- free(static_cast<char*>(ptr) - HDR_SIZE);
129
+ free(static_cast<char*>(ptr) - hdr_size());
88
130
  }
89
131
 
90
132
  void* mik__realloc(void* ptr, size_t size) {
91
- void* raw = ptr ? static_cast<char*>(ptr) - HDR_SIZE : nullptr;
92
- raw = realloc(raw, size + HDR_SIZE);
133
+ size_t hdr = hdr_size();
134
+ void* raw = ptr ? static_cast<char*>(ptr) - hdr : nullptr;
135
+ raw = realloc(raw, size + hdr);
93
136
  if (!raw) return nullptr;
94
- hdr_write(raw, size);
137
+ hdr_write(raw, size, hdr);
95
138
  if (!ptr) LIVE_ALLOCS_ADD(1);
96
- return static_cast<char*>(raw) + HDR_SIZE;
139
+ return static_cast<char*>(raw) + hdr;
97
140
  }
98
141
 
99
142
  /* QuickJS-heap allocator. When the PSRAM flag is set, route through the
@@ -115,51 +158,54 @@ bool mik__is_quickjs_heap_psram(void) {
115
158
 
116
159
  void* mik__js_malloc(size_t size) {
117
160
  if (OOM_INJECT_FAIL()) return nullptr;
161
+ size_t hdr = hdr_size();
118
162
  void* raw = nullptr;
119
163
  if (g_quickjs_heap_psram) {
120
164
  const MIKPlatform* p = MIK_GetPlatform();
121
165
  if (p && p->malloc_psram) {
122
- raw = p->malloc_psram(size + HDR_SIZE);
166
+ raw = p->malloc_psram(size + hdr);
123
167
  }
124
168
  }
125
- if (!raw) raw = malloc(size + HDR_SIZE);
169
+ if (!raw) raw = malloc(size + hdr);
126
170
  if (!raw) return nullptr;
127
- hdr_write(raw, size);
171
+ hdr_write(raw, size, hdr);
128
172
  LIVE_ALLOCS_ADD(1);
129
- return static_cast<char*>(raw) + HDR_SIZE;
173
+ return static_cast<char*>(raw) + hdr;
130
174
  }
131
175
 
132
176
  void* mik__js_calloc(size_t count, size_t size) {
133
177
  if (OOM_INJECT_FAIL()) return nullptr;
134
178
  if (size && count > SIZE_MAX / size) return nullptr;
135
179
  size_t total = count * size;
180
+ size_t hdr = hdr_size();
136
181
  void* raw = nullptr;
137
182
  if (g_quickjs_heap_psram) {
138
183
  const MIKPlatform* p = MIK_GetPlatform();
139
184
  if (p && p->calloc_psram) {
140
- raw = p->calloc_psram(1, total + HDR_SIZE);
185
+ raw = p->calloc_psram(1, total + hdr);
141
186
  }
142
187
  }
143
- if (!raw) raw = calloc(1, total + HDR_SIZE);
188
+ if (!raw) raw = calloc(1, total + hdr);
144
189
  if (!raw) return nullptr;
145
- hdr_write(raw, total);
190
+ hdr_write(raw, total, hdr);
146
191
  LIVE_ALLOCS_ADD(1);
147
- return static_cast<char*>(raw) + HDR_SIZE;
192
+ return static_cast<char*>(raw) + hdr;
148
193
  }
149
194
 
150
195
  void* mik__js_realloc(void* ptr, size_t size) {
151
196
  if (OOM_INJECT_FAIL()) return nullptr;
152
- void* raw = ptr ? static_cast<char*>(ptr) - HDR_SIZE : nullptr;
197
+ size_t hdr = hdr_size();
198
+ void* raw = ptr ? static_cast<char*>(ptr) - hdr : nullptr;
153
199
  void* new_raw = nullptr;
154
200
  if (g_quickjs_heap_psram) {
155
201
  const MIKPlatform* p = MIK_GetPlatform();
156
202
  if (p && p->realloc_psram) {
157
- new_raw = p->realloc_psram(raw, size + HDR_SIZE);
203
+ new_raw = p->realloc_psram(raw, size + hdr);
158
204
  }
159
205
  }
160
- if (!new_raw) new_raw = realloc(raw, size + HDR_SIZE);
206
+ if (!new_raw) new_raw = realloc(raw, size + hdr);
161
207
  if (!new_raw) return nullptr;
162
- hdr_write(new_raw, size);
208
+ hdr_write(new_raw, size, hdr);
163
209
  if (!ptr) LIVE_ALLOCS_ADD(1);
164
- return static_cast<char*>(new_raw) + HDR_SIZE;
210
+ return static_cast<char*>(new_raw) + hdr;
165
211
  }
@@ -337,7 +337,15 @@ int MIK_LoadConfig(const char* base_path, MIKConfig* config) {
337
337
  config->stack_size = (size_t)num_val;
338
338
  }
339
339
  if (mik__json_get_number(buf, "memReserved", &num_val)) {
340
- config->mem_reserved = (uint32_t)num_val;
340
+ /* The uint32 cast would wrap a negative value into a ~4 GB
341
+ * reserve; keep the default instead. */
342
+ if (num_val < 0) {
343
+ platform->log(MIK_LOG_WARN, TAG,
344
+ "Ignoring negative memReserved (%ld); using default",
345
+ (long)num_val);
346
+ } else {
347
+ config->mem_reserved = (uint32_t)num_val;
348
+ }
341
349
  }
342
350
  if (mik__json_get_number(buf, "fsReadMax", &num_val)) {
343
351
  config->fs_read_max = (uint32_t)num_val;