@mentra/crust 3.2.0-dev.116 → 3.2.0-dev.121

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.
@@ -459,15 +459,14 @@ class JSCRuntime private constructor(private val appContext: Context) {
459
459
  */
460
460
  fun dispatchToJs(packageName: String, envelopeJson: String) {
461
461
  val record = contexts[packageName] ?: return
462
- // Steady-state NACK — re-arm so a wedged QuickJS context surfaces
463
- // an __error/ready_nack frame after 3s instead of silently
464
- // swallowing the delivery. Skipped during cold-start (timer still
465
- // ticking from spawn).
466
- if (record.readyAcked) {
467
- armReadyNackTimer(record, STEADY_STATE_NACK_TIMEOUT_MS, cold = false)
468
- }
469
462
  try {
470
463
  record.executor.submit {
464
+ // Arm only once evaluate is about to run. Queue wait during a
465
+ // long previous turn (WHIP start, etc.) must not count — that
466
+ // was firing ready_nack while the context was merely busy.
467
+ if (record.readyAcked) {
468
+ armReadyNackTimer(record, STEADY_STATE_NACK_TIMEOUT_MS, cold = false)
469
+ }
471
470
  // Soft watchdog around evaluate: warn at 5s, kill at 30s.
472
471
  val warn = timerScheduler.schedule({
473
472
  Log.i(TAG, "watchdog: $packageName __deliver blocked >${WATCHDOG_WARN_MS}ms")
@@ -495,12 +494,12 @@ class JSCRuntime private constructor(private val appContext: Context) {
495
494
  runBlocking {
496
495
  record.qjs.evaluate<Any?>(source, filename = "mentrajs:deliver.js")
497
496
  }
498
- // Successful delivery — context is responsive.
499
- record.readyNackTimer?.cancel(false)
500
- record.readyNackTimer = null
501
497
  } catch (e: Throwable) {
502
498
  Log.w(TAG, "dispatchToJs threw in $packageName: ${e.message}", e)
503
499
  } finally {
500
+ // Success or throw: the host observed the turn end.
501
+ record.readyNackTimer?.cancel(false)
502
+ record.readyNackTimer = null
504
503
  warn.cancel(false)
505
504
  killTimer.cancel(false)
506
505
  if (record.watchdogTimer === killTimer) record.watchdogTimer = null
@@ -63,8 +63,9 @@ public final class JSCRuntime: NSObject {
63
63
  /// Monotonic per-context counter for native-issued reqIds.
64
64
  var nextTimerToken: Int = 1
65
65
  /// signalReady NACK timer. Armed at spawn (15s cold-start) and
66
- /// on every dispatchToJs (3s steady-state). Disarmed when the
67
- /// polyfill calls __runtime.ready or when the call completes.
66
+ /// when a __deliver evaluate actually starts (3s steady-state).
67
+ /// Disarmed when the polyfill calls __runtime.ready or when the
68
+ /// evaluate returns (success or throw).
68
69
  var readyNackTimer: DispatchSourceTimer?
69
70
  /// True once the polyfill has signalled ready. Cleared on respawn.
70
71
  var readyAcked: Bool = false
@@ -304,14 +305,13 @@ public final class JSCRuntime: NSObject {
304
305
  os_log("MentraJS: bad envelope, drop", log: Self.log, type: .error)
305
306
  return
306
307
  }
307
- // Steady-state NACK: re-arm the timer so a wedged JSContext
308
- // surfaces a __error/ready_nack frame after 3s instead of silently
309
- // swallowing the delivery. Only fires if a cold-start ack already
310
- // landed — otherwise the cold-start timer is still ticking.
311
- if record.readyAcked {
312
- armReadyNackTimer(record: record, timeoutSeconds: Self.steadyStateNackTimeoutSeconds, cold: false)
313
- }
314
308
  record.queue.async {
309
+ // Arm only once evaluate is about to run. Queue wait during a
310
+ // long previous turn must not count — that was firing
311
+ // ready_nack while the context was merely busy.
312
+ if record.readyAcked {
313
+ self.armReadyNackTimer(record: record, timeoutSeconds: Self.steadyStateNackTimeoutSeconds, cold: false)
314
+ }
315
315
  let escaped = Self.jsStringLiteral(json)
316
316
  // Soft watchdog: every evaluateScript outside spawn gets a
317
317
  // wall-clock timer. If the eval is still running at the warn
@@ -319,16 +319,16 @@ public final class JSCRuntime: NSObject {
319
319
  // the context down and emit __error/watchdog_kill so the
320
320
  // crash controller (if wired) can drive respawn.
321
321
  self.armSoftWatchdog(record: record, label: "__deliver")
322
+ defer {
323
+ self.disarmSoftWatchdog(record: record)
324
+ record.readyNackTimer?.cancel()
325
+ record.readyNackTimer = nil
326
+ }
322
327
  _ = self.evaluateCatching(
323
328
  record: record,
324
329
  label: "__deliver",
325
330
  source: "globalThis.__deliver(\(escaped));",
326
331
  )
327
- self.disarmSoftWatchdog(record: record)
328
- // On a successful delivery, clear the NACK — the host
329
- // observed the eval complete, so the context is responsive.
330
- record.readyNackTimer?.cancel()
331
- record.readyNackTimer = nil
332
332
  }
333
333
  }
334
334
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mentra/crust",
3
- "version": "3.2.0-dev.116",
3
+ "version": "3.2.0-dev.121",
4
4
  "description": "Mentra Native Module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "license": "Apache-2.0",
36
36
  "homepage": "https://github.com/Mentra-Community/MentraOS/tree/dev/mobile/modules/crust#readme",
37
37
  "dependencies": {
38
- "@mentra/jspolyfill": "3.2.0-dev.116"
38
+ "@mentra/jspolyfill": "3.2.0-dev.121"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@expo/config-plugins": ">=8.0.0",
@@ -15,6 +15,9 @@ const MAPBOX_REPO = [
15
15
  " username = 'mapbox'",
16
16
  " password = System.getenv('MAPBOX_DOWNLOADS_TOKEN') ?: (findProperty('MAPBOX_DOWNLOADS_TOKEN') ?: '')",
17
17
  " }",
18
+ " content {",
19
+ " includeGroupByRegex 'com\\\\.mapbox.*'",
20
+ " }",
18
21
  " }",
19
22
  ].join("\n");
20
23
  const PROTOBUF_EXCLUDE = "exclude group: 'com.google.protobuf', module: 'protobuf-javalite'";