@mikrojs/firmware 0.20.1 → 0.20.2-next.20260907205905

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.
@@ -746,24 +746,19 @@ void MIK_Main(void) {
746
746
  if (safe_mode) {
747
747
  ESP_LOGW(TAG, "Safe mode: skipping entry point %s", app_config.entry_point);
748
748
  } else {
749
- /* Catch async fatals (unhandled rejections) during an OTA trial. */
749
+ /* Catch fatals during an OTA trial: MIK_RunEntry hands a synchronous
750
+ * throw to this handler itself, the loop's rejection flush hands it
751
+ * unhandled rejections. Both note the failure and arm the panic
752
+ * restart so reconcile reverts on the next (clean-looking) boot. */
750
753
  MIK_SetErrorHandler(mik_rt, ota_trial_error_handler, nullptr);
751
- char entry_err[160] = {0};
752
- int rc = MIK_RunEntryErr(mik_rt, app_config.entry_point, entry_err, sizeof(entry_err));
754
+ int rc = MIK_RunEntry(mik_rt, app_config.entry_point);
753
755
  if (rc == -EINVAL) {
754
756
  ESP_LOGW(TAG, "No entry point configured (no \"main\" field in package.json)");
755
757
  } else if (rc == -ENOENT) {
756
758
  ESP_LOGW(TAG, "Entry point not found: %s", app_config.entry_point);
757
759
  } else if (rc == -EFAULT) {
760
+ /* Already reported to the console by the runtime. */
758
761
  ESP_LOGE(TAG, "Failed to evaluate %s", app_config.entry_point);
759
- /* A synchronous top-level throw doesn't reach the rejection handler
760
- * above. If this is a trial build, flag it and arm the panic restart
761
- * so reconcile reverts on the next (clean-looking) boot. */
762
- if (mik__ota_in_trial()) {
763
- mik__ota_note_trial_failure(entry_err[0] ? entry_err
764
- : "entry failed to evaluate");
765
- MIK_Stop(mik_rt);
766
- }
767
762
  }
768
763
  }
769
764
  }
@@ -75,6 +75,10 @@ struct MIKOtaClientState {
75
75
  * only copy left after ota.reconcile() ran. settle() marks it delivered. */
76
76
  bool has_last_install = false;
77
77
  MIKOtaDiagnostic last_install = {};
78
+ /* Set by report() when the stored decline made it into the body, so settle()
79
+ * clears only a record the registry has seen. A read that failed leaves the
80
+ * record for the next round. */
81
+ bool decline_reported = false;
78
82
  };
79
83
 
80
84
  int mik__ota_client_slot = -1;
@@ -350,7 +354,8 @@ JSValue kv_string_or_undefined(JSContext* ctx, const char* key) {
350
354
  MIKOtaClientState* state = state_of(ctx);
351
355
  if (!state || !state->env || !state->env->kv_get_str) return JS_UNDEFINED;
352
356
  char buf[256] = {};
353
- if (!state->env->kv_get_str(state->env->opaque, key, buf, sizeof(buf)) || buf[0] == '\0') {
357
+ if (state->env->kv_get_str(state->env->opaque, key, buf, sizeof(buf)) != MIK_OTA_KV_OK ||
358
+ buf[0] == '\0') {
354
359
  return JS_UNDEFINED;
355
360
  }
356
361
  return JS_NewString(ctx, buf);
@@ -911,7 +916,8 @@ JSValue ota_report(JSContext* ctx, JSValue, int, JSValue*) {
911
916
  * decline(). Without it a registry cannot tell a device still working
912
917
  * through a download from one that has stopped. */
913
918
  MIKOtaDeclineRecord declined;
914
- if (mikrojs::MIKOtaStore(env).GetDecline(&declined)) {
919
+ state->decline_reported = mikrojs::MIKOtaStore(env).GetDecline(&declined);
920
+ if (state->decline_reported) {
915
921
  JSValue last = JS_NewObject(ctx);
916
922
  JS_SetPropertyStr(ctx, last, "checksum", JS_NewString(ctx, declined.checksum));
917
923
  JS_SetPropertyStr(ctx, last, "reason", JS_NewString(ctx, declined.reason));
@@ -960,10 +966,13 @@ JSValue ota_settle(JSContext* ctx, JSValue, int argc, JSValue* argv) {
960
966
  /* Confirm before the deliveries, as the built-in does: it must settle the
961
967
  * document held BEFORE this round, never the one about to be armed. */
962
968
  mikrojs::mik__ota_policy_confirm(state->env);
963
- /* The round completed, so the cached install report and the stored decline
964
- * record were delivered. */
969
+ /* The round completed, so the cached install report was delivered, and so
970
+ * was the stored decline record if report() carried it. */
965
971
  state->has_last_install = false;
966
- mikrojs::MIKOtaStore(state->env).ClearDecline();
972
+ if (state->decline_reported) {
973
+ mikrojs::MIKOtaStore(state->env).ClearDecline();
974
+ state->decline_reported = false;
975
+ }
967
976
 
968
977
  bool renamed = false;
969
978
  if (usable) {
@@ -105,11 +105,13 @@ bool env_kv_set_blob(void*, const char* key, const uint8_t* data, size_t len) {
105
105
  return kv_write_blob(key, data, len);
106
106
  }
107
107
 
108
- bool env_kv_get_str(void*, const char* key, char* out, size_t max_len) {
108
+ MIKOtaKvStatus env_kv_get_str(void*, const char* key, char* out, size_t max_len) {
109
109
  uint8_t buf[320];
110
110
  size_t len = sizeof(buf);
111
- if (kv_read_blob(key, buf, &len) != MIK_OTA_KV_OK) return false;
112
- return mik__kv_decode_str(buf, len, out, max_len);
111
+ MIKOtaKvStatus status = kv_read_blob(key, buf, &len);
112
+ if (status != MIK_OTA_KV_OK) return status;
113
+ /* Stored bytes that will not decode are corruption, not absence. */
114
+ return mik__kv_decode_str(buf, len, out, max_len) ? MIK_OTA_KV_OK : MIK_OTA_KV_ERROR;
113
115
  }
114
116
 
115
117
  bool env_kv_set_str(void*, const char* key, const char* value) {
@@ -119,11 +121,12 @@ bool env_kv_set_str(void*, const char* key, const char* value) {
119
121
  return kv_write_blob(key, buf, needed);
120
122
  }
121
123
 
122
- bool env_kv_get_i32(void*, const char* key, int32_t* out) {
124
+ MIKOtaKvStatus env_kv_get_i32(void*, const char* key, int32_t* out) {
123
125
  uint8_t buf[16];
124
126
  size_t len = sizeof(buf);
125
- if (kv_read_blob(key, buf, &len) != MIK_OTA_KV_OK) return false;
126
- return mik__kv_decode_i32(buf, len, out);
127
+ MIKOtaKvStatus status = kv_read_blob(key, buf, &len);
128
+ if (status != MIK_OTA_KV_OK) return status;
129
+ return mik__kv_decode_i32(buf, len, out) ? MIK_OTA_KV_OK : MIK_OTA_KV_ERROR;
127
130
  }
128
131
 
129
132
  bool env_kv_set_i32(void*, const char* key, int32_t value) {
@@ -0,0 +1,2 @@
1
+ .build/
2
+ .cache/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mikrojs/firmware",
3
- "version": "0.20.1",
3
+ "version": "0.20.2-next.20260907205905",
4
4
  "description": "Mikro.js ESP32 firmware: ESP-IDF component, build tools, and project template",
5
5
  "keywords": [
6
6
  "esp-idf",
@@ -46,9 +46,9 @@
46
46
  "./package.json": "./package.json"
47
47
  },
48
48
  "dependencies": {
49
- "esbuild": "^0.28.0",
50
- "@mikrojs/native": "0.20.1",
51
- "@mikrojs/quickjs": "0.20.1"
49
+ "@mikrojs/native": "0.20.2-next.20260907205905+8b6f502",
50
+ "@mikrojs/quickjs": "0.20.2-next.20260907205905+8b6f502",
51
+ "esbuild": "^0.28.2"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=24.0.0"
Binary file
Binary file
Binary file
Binary file
Binary file