kitchen-simulator 5.10.7-react.18 → 5.10.9-react.18

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 (2) hide show
  1. package/es/index.js +430 -82
  2. package/package.json +1 -1
package/es/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
1
2
  import _extends from "@babel/runtime/helpers/esm/extends";
2
3
  import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
3
4
  import _createClass from "@babel/runtime/helpers/esm/createClass";
@@ -5,6 +6,9 @@ import _possibleConstructorReturn from "@babel/runtime/helpers/esm/possibleConst
5
6
  import _getPrototypeOf from "@babel/runtime/helpers/esm/getPrototypeOf";
6
7
  import _inherits from "@babel/runtime/helpers/esm/inherits";
7
8
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
9
+ import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
10
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
11
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
12
  function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
9
13
  function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
10
14
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
@@ -17,6 +21,66 @@ import LiteRenderer from "./LiteRenderer";
17
21
  import { createRoot } from 'react-dom/client';
18
22
  var ROOT_KEY = '__kitchenSimulatorRoot__';
19
23
  var API_KEY = '__kitchenSimulatorApi__';
24
+
25
+ /**
26
+ * Debug logging
27
+ * - Enable via:
28
+ * - window.__kitchenSimulatorDebug__ = true
29
+ * - or pass props.debug = true to renderKitchenSimulator(container, { debug: true })
30
+ */
31
+ function makeLogger(getEnabled) {
32
+ var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '[kitchen-simulator]';
33
+ var now = function now() {
34
+ return (typeof performance !== 'undefined' && performance.now ? performance.now() : Date.now()).toFixed(1);
35
+ };
36
+ var safe = function safe(v) {
37
+ try {
38
+ if (v == null) return v;
39
+ if (typeof v === 'string') return v;
40
+ if (typeof v === 'number' || typeof v === 'boolean') return v;
41
+ // avoid huge logs
42
+ return JSON.stringify(v, function (k, val) {
43
+ if (k === 'children' || k === 'parent') return '[omitted]';
44
+ if (typeof val === 'function') return '[fn]';
45
+ return val;
46
+ });
47
+ } catch (_unused) {
48
+ return '[unserializable]';
49
+ }
50
+ };
51
+ var log = function log() {
52
+ var _console;
53
+ if (!getEnabled()) return;
54
+ // eslint-disable-next-line no-console
55
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
56
+ args[_key] = arguments[_key];
57
+ }
58
+ (_console = console).log.apply(_console, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
59
+ };
60
+ var warn = function warn() {
61
+ var _console2;
62
+ if (!getEnabled()) return;
63
+ // eslint-disable-next-line no-console
64
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
65
+ args[_key2] = arguments[_key2];
66
+ }
67
+ (_console2 = console).warn.apply(_console2, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
68
+ };
69
+ var error = function error() {
70
+ var _console3;
71
+ if (!getEnabled()) return;
72
+ // eslint-disable-next-line no-console
73
+ for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
74
+ args[_key3] = arguments[_key3];
75
+ }
76
+ (_console3 = console).error.apply(_console3, ["".concat(prefix, " ").concat(now(), "ms")].concat(_toConsumableArray(args.map(safe))));
77
+ };
78
+ return {
79
+ log: log,
80
+ warn: warn,
81
+ error: error
82
+ };
83
+ }
20
84
  function nextFrame() {
21
85
  return new Promise(function (resolve) {
22
86
  return requestAnimationFrame(resolve);
@@ -40,6 +104,7 @@ Three.TextureLoader.prototype.load = function (url, onLoad, onProgress, onError)
40
104
  * Ref-counted global install so multiple instances don't clobber each other.
41
105
  */
42
106
  function installGltfTracker() {
107
+ var debug = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
43
108
  if (typeof window === 'undefined') {
44
109
  var _subscribe = function _subscribe() {
45
110
  return function () {};
@@ -70,6 +135,7 @@ function installGltfTracker() {
70
135
  };
71
136
  }
72
137
  var GLOBAL_KEY = '__kitchenSimulatorGltfTracker__';
138
+ var TRACKER_DEBUG_KEY = '__kitchenSimulatorDebug__';
73
139
  if (!window[GLOBAL_KEY]) {
74
140
  window[GLOBAL_KEY] = {
75
141
  refCount: 0,
@@ -82,13 +148,20 @@ function installGltfTracker() {
82
148
  };
83
149
  }
84
150
  var g = window[GLOBAL_KEY];
151
+ var isDebug = function isDebug() {
152
+ return !!debug || !!window[TRACKER_DEBUG_KEY];
153
+ };
154
+ var _makeLogger = makeLogger(isDebug, '[kitchen-simulator:gltf]'),
155
+ log = _makeLogger.log,
156
+ warn = _makeLogger.warn,
157
+ error = _makeLogger.error;
85
158
  var is3dAssetUrl = function is3dAssetUrl(url) {
86
159
  try {
87
160
  var _url$toString, _url$toString2;
88
161
  var s = typeof url === 'string' ? url : (_url$toString = url === null || url === void 0 || (_url$toString2 = url.toString) === null || _url$toString2 === void 0 ? void 0 : _url$toString2.call(url)) !== null && _url$toString !== void 0 ? _url$toString : '';
89
162
  var u = s.toLowerCase().split('?')[0]; // ignore cache params
90
163
  return u.endsWith('.gltf') || u.endsWith('.glb') || u.endsWith('.bin') || u.endsWith('.ktx2') || u.endsWith('.hdr') || u.endsWith('.exr') || u.endsWith('.png') || u.endsWith('.jpg') || u.endsWith('.jpeg') || u.endsWith('.webp');
91
- } catch (_unused) {
164
+ } catch (_unused2) {
92
165
  return false;
93
166
  }
94
167
  };
@@ -116,6 +189,7 @@ function installGltfTracker() {
116
189
  var installIfNeeded = function installIfNeeded() {
117
190
  var _XHR$prototype, _XHR$prototype2;
118
191
  if (g.installed) return;
192
+ log('Installing GLTF tracker hooks');
119
193
 
120
194
  // ---- XHR hook ----
121
195
  var XHR = window.XMLHttpRequest;
@@ -125,8 +199,14 @@ function installGltfTracker() {
125
199
  XHR.prototype.open = function (method, url) {
126
200
  var _g$originalOpen;
127
201
  this.__is3dAssetRequest = is3dAssetUrl(url);
128
- for (var _len = arguments.length, rest = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
129
- rest[_key - 2] = arguments[_key];
202
+ if (this.__is3dAssetRequest) {
203
+ log('XHR open (3D asset)', {
204
+ method: method,
205
+ url: url
206
+ });
207
+ }
208
+ for (var _len4 = arguments.length, rest = new Array(_len4 > 2 ? _len4 - 2 : 0), _key4 = 2; _key4 < _len4; _key4++) {
209
+ rest[_key4 - 2] = arguments[_key4];
130
210
  }
131
211
  return (_g$originalOpen = g.originalOpen).call.apply(_g$originalOpen, [this, method, url].concat(rest));
132
212
  };
@@ -134,10 +214,12 @@ function installGltfTracker() {
134
214
  var _this = this;
135
215
  if (this.__is3dAssetRequest) {
136
216
  g.inFlight += 1;
217
+ log('XHR send -> inFlight++', g.inFlight);
137
218
  notify();
138
219
  var _done = function done() {
139
220
  g.inFlight -= 1;
140
221
  if (g.inFlight < 0) g.inFlight = 0;
222
+ log('XHR done -> inFlight--', g.inFlight);
141
223
  notify();
142
224
  _this.removeEventListener('loadend', _done);
143
225
  _this.removeEventListener('error', _done);
@@ -149,30 +231,38 @@ function installGltfTracker() {
149
231
  this.addEventListener('abort', _done);
150
232
  this.addEventListener('timeout', _done);
151
233
  }
152
- for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
153
- args[_key2] = arguments[_key2];
234
+ for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) {
235
+ args[_key5] = arguments[_key5];
154
236
  }
155
237
  return g.originalSend.apply(this, args);
156
238
  };
239
+ } else {
240
+ warn('XHR hooks not installed (missing open/send)');
157
241
  }
158
242
 
159
243
  // ---- fetch hook ----
160
244
  g.originalFetch = window.fetch;
161
245
  if (typeof g.originalFetch === 'function') {
162
246
  window.fetch = /*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
163
- var _len3,
247
+ var _input;
248
+ var _len6,
164
249
  args,
165
- _key3,
250
+ _key6,
166
251
  input,
167
252
  init,
168
253
  newUrl,
169
254
  track,
170
- _args2 = arguments;
255
+ _input2,
256
+ res,
257
+ _input3,
258
+ _e$message,
259
+ _args2 = arguments,
260
+ _t;
171
261
  return _regeneratorRuntime.wrap(function (_context2) {
172
262
  while (1) switch (_context2.prev = _context2.next) {
173
263
  case 0:
174
- for (_len3 = _args2.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
175
- args[_key3] = _args2[_key3];
264
+ for (_len6 = _args2.length, args = new Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {
265
+ args[_key6] = _args2[_key6];
176
266
  }
177
267
  input = args[0], init = args[1]; // DIY-714 [Temp Fix] Rewrite API URLs
178
268
  if (typeof input === 'string') {
@@ -189,24 +279,44 @@ function installGltfTracker() {
189
279
  return _context2.abrupt("return", g.originalFetch.call(this, input, init));
190
280
  case 1:
191
281
  g.inFlight += 1;
282
+ log('fetch (3D asset) -> inFlight++', g.inFlight, {
283
+ url: typeof input === 'string' ? input : (_input = input) === null || _input === void 0 ? void 0 : _input.url
284
+ });
192
285
  notify();
193
286
  _context2.prev = 2;
194
287
  _context2.next = 3;
195
288
  return g.originalFetch.call(this, input, init);
196
289
  case 3:
197
- return _context2.abrupt("return", _context2.sent);
290
+ res = _context2.sent;
291
+ log('fetch response (3D asset)', {
292
+ url: typeof input === 'string' ? input : (_input2 = input) === null || _input2 === void 0 ? void 0 : _input2.url,
293
+ ok: res === null || res === void 0 ? void 0 : res.ok,
294
+ status: res === null || res === void 0 ? void 0 : res.status
295
+ });
296
+ return _context2.abrupt("return", res);
198
297
  case 4:
199
298
  _context2.prev = 4;
299
+ _t = _context2["catch"](2);
300
+ error('fetch error (3D asset)', {
301
+ url: typeof input === 'string' ? input : (_input3 = input) === null || _input3 === void 0 ? void 0 : _input3.url,
302
+ error: (_e$message = _t === null || _t === void 0 ? void 0 : _t.message) !== null && _e$message !== void 0 ? _e$message : _t
303
+ });
304
+ throw _t;
305
+ case 5:
306
+ _context2.prev = 5;
200
307
  g.inFlight -= 1;
201
308
  if (g.inFlight < 0) g.inFlight = 0;
309
+ log('fetch finally -> inFlight--', g.inFlight);
202
310
  notify();
203
- return _context2.finish(4);
204
- case 5:
311
+ return _context2.finish(5);
312
+ case 6:
205
313
  case "end":
206
314
  return _context2.stop();
207
315
  }
208
- }, _callee2, this, [[2,, 4, 5]]);
316
+ }, _callee2, this, [[2, 4, 5, 6]]);
209
317
  }));
318
+ } else {
319
+ warn('fetch hook not installed (window.fetch not a function)');
210
320
  }
211
321
  g.installed = true;
212
322
  };
@@ -251,6 +361,12 @@ function installGltfTracker() {
251
361
  while (1) switch (_context4.prev = _context4.next) {
252
362
  case 0:
253
363
  _ref3 = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {}, _ref3$timeoutMs = _ref3.timeoutMs, timeoutMs = _ref3$timeoutMs === void 0 ? 30000 : _ref3$timeoutMs;
364
+ log('waitForIdle start', {
365
+ timeoutMs: timeoutMs,
366
+ inFlight: g.inFlight
367
+ });
368
+
369
+ // Fast path
254
370
  _context4.next = 1;
255
371
  return waitStableIdle2Frames();
256
372
  case 1:
@@ -258,6 +374,7 @@ function installGltfTracker() {
258
374
  _context4.next = 2;
259
375
  break;
260
376
  }
377
+ log('waitForIdle fast-path resolved');
261
378
  return _context4.abrupt("return", true);
262
379
  case 2:
263
380
  return _context4.abrupt("return", new Promise(function (resolve, reject) {
@@ -268,13 +385,16 @@ function installGltfTracker() {
268
385
  finished = true;
269
386
  if (unsub) unsub();
270
387
  clearTimeout(timer);
388
+ log('waitForIdle resolved');
271
389
  resolve(true);
272
390
  };
273
391
  var finishErr = function finishErr(err) {
392
+ var _err$message;
274
393
  if (finished) return;
275
394
  finished = true;
276
395
  if (unsub) unsub();
277
396
  clearTimeout(timer);
397
+ error('waitForIdle timeout/reject', (_err$message = err === null || err === void 0 ? void 0 : err.message) !== null && _err$message !== void 0 ? _err$message : err);
278
398
  reject(err);
279
399
  };
280
400
 
@@ -294,6 +414,9 @@ function installGltfTracker() {
294
414
  }
295
415
  return _context3.abrupt("return");
296
416
  case 1:
417
+ log('waitForIdle inFlight change', count);
418
+
419
+ // Only care when it hits zero; otherwise we just wait
297
420
  if (!(count !== 0)) {
298
421
  _context3.next = 2;
299
422
  break;
@@ -304,6 +427,7 @@ function installGltfTracker() {
304
427
  return waitStableIdle2Frames();
305
428
  case 3:
306
429
  stable = _context3.sent;
430
+ log('waitForIdle stable check', stable);
307
431
  if (stable) finishOk();
308
432
  // else keep waiting
309
433
  case 4:
@@ -331,7 +455,9 @@ function installGltfTracker() {
331
455
  var uninstall = function uninstall() {
332
456
  var _XHR$prototype3, _XHR$prototype4;
333
457
  g.refCount -= 1;
458
+ log('uninstall tracker refCount--', g.refCount);
334
459
  if (g.refCount > 0) return;
460
+ log('uninstall tracker (final) restoring hooks');
335
461
  var XHR = window.XMLHttpRequest;
336
462
  if (XHR !== null && XHR !== void 0 && (_XHR$prototype3 = XHR.prototype) !== null && _XHR$prototype3 !== void 0 && _XHR$prototype3.open && g.originalOpen) XHR.prototype.open = g.originalOpen;
337
463
  if (XHR !== null && XHR !== void 0 && (_XHR$prototype4 = XHR.prototype) !== null && _XHR$prototype4 !== void 0 && _XHR$prototype4.send && g.originalSend) XHR.prototype.send = g.originalSend;
@@ -344,6 +470,7 @@ function installGltfTracker() {
344
470
  g.originalSend = null;
345
471
  };
346
472
  g.refCount += 1;
473
+ log('install tracker refCount++', g.refCount);
347
474
  installIfNeeded();
348
475
  return {
349
476
  getInFlight: function getInFlight() {
@@ -358,10 +485,19 @@ export function renderKitchenSimulator(container) {
358
485
  var _props$framesPerEvent, _props$waitForGltfIdl, _props$gltfTimeoutMs;
359
486
  var props = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
360
487
  if (!container) throw new Error('renderKitchenSimulator: container is required');
488
+ var DEBUG_KEY = '__kitchenSimulatorDebug__';
489
+ var debugEnabled = !!props.debug || typeof window !== 'undefined' && !!window[DEBUG_KEY];
490
+ var _makeLogger2 = makeLogger(function () {
491
+ return debugEnabled;
492
+ }),
493
+ log = _makeLogger2.log,
494
+ warn = _makeLogger2.warn,
495
+ error = _makeLogger2.error;
361
496
 
362
497
  // ✅ Reuse existing API
363
498
  if (container[API_KEY]) {
364
499
  var _container$API_KEY$__, _container$API_KEY;
500
+ log('Reusing existing API; calling __render with new props');
365
501
  (_container$API_KEY$__ = (_container$API_KEY = container[API_KEY]).__render) === null || _container$API_KEY$__ === void 0 || _container$API_KEY$__.call(_container$API_KEY, props);
366
502
  return container[API_KEY];
367
503
  }
@@ -371,38 +507,83 @@ export function renderKitchenSimulator(container) {
371
507
  if (!root) {
372
508
  root = createRoot(container);
373
509
  container[ROOT_KEY] = root;
510
+ log('Created new React root');
511
+ } else {
512
+ log('Reusing existing React root');
374
513
  }
375
514
  var setExternalEventFn = null;
376
515
  var destroyed = false;
377
516
  var queue = [];
378
517
  var pendingMarkers = new Set();
379
518
  var MARKER = Symbol('marker');
380
- var gltfTracker = installGltfTracker();
519
+ var gltfTracker = installGltfTracker(debugEnabled);
381
520
 
382
521
  // FAST defaults (safe)
383
522
  var defaultFramesPerEvent = (_props$framesPerEvent = props.framesPerEvent) !== null && _props$framesPerEvent !== void 0 ? _props$framesPerEvent : 1;
384
523
  var waitForAssets = (_props$waitForGltfIdl = props.waitForGltfIdleAfterEachEvent) !== null && _props$waitForGltfIdl !== void 0 ? _props$waitForGltfIdl : true;
385
524
  var defaultTimeout = (_props$gltfTimeoutMs = props.gltfTimeoutMs) !== null && _props$gltfTimeoutMs !== void 0 ? _props$gltfTimeoutMs : 30000;
386
-
387
- // If you want ultra-fast UI responsiveness, you can disable waiting per-event
388
- // and only wait on “important” events, see comment in settle() below.
389
-
390
525
  var draining = false;
526
+
527
+ // ---- Loop detection / profiling helpers ----
528
+ var drainRunId = 0;
529
+ var eventSeq = 0;
530
+ var lastEvents = [];
531
+ var LAST_N = 40;
532
+ function summarizeEvent(ev) {
533
+ var _ref5, _ref6, _ev$type, _ev$payload, _ref7, _ev$id, _ev$payload2;
534
+ if (!ev) return ev;
535
+ var t = (_ref5 = (_ref6 = (_ev$type = ev === null || ev === void 0 ? void 0 : ev.type) !== null && _ev$type !== void 0 ? _ev$type : ev === null || ev === void 0 || (_ev$payload = ev.payload) === null || _ev$payload === void 0 ? void 0 : _ev$payload.mode) !== null && _ref6 !== void 0 ? _ref6 : ev === null || ev === void 0 ? void 0 : ev.name) !== null && _ref5 !== void 0 ? _ref5 : 'unknown';
536
+ var id = (_ref7 = (_ev$id = ev === null || ev === void 0 ? void 0 : ev.id) !== null && _ev$id !== void 0 ? _ev$id : ev === null || ev === void 0 || (_ev$payload2 = ev.payload) === null || _ev$payload2 === void 0 ? void 0 : _ev$payload2.id) !== null && _ref7 !== void 0 ? _ref7 : null;
537
+ return {
538
+ type: t,
539
+ id: id,
540
+ framesPerEvent: ev === null || ev === void 0 ? void 0 : ev.framesPerEvent,
541
+ waitForGltfIdleAfterEachEvent: ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent,
542
+ gltfTimeoutMs: ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs
543
+ };
544
+ }
545
+ function recordEvent(ev) {
546
+ var s = summarizeEvent(ev);
547
+ lastEvents.push(s);
548
+ if (lastEvents.length > LAST_N) lastEvents.shift();
549
+ }
550
+ function dumpLoopHint() {
551
+ var context = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
552
+ warn('Possible infinite loop / stall detected', {
553
+ context: context,
554
+ destroyed: destroyed,
555
+ draining: draining,
556
+ queueLength: queue.length,
557
+ pendingMarkers: pendingMarkers.size,
558
+ gltfInFlight: gltfTracker.getInFlight(),
559
+ lastEvents: lastEvents
560
+ });
561
+ }
391
562
  function isSyncScene(ev) {
392
- var _ev$payload;
393
- return (ev === null || ev === void 0 ? void 0 : ev.type) === 'EXTERNAL_EVENT_SYNC_SCENE' || (ev === null || ev === void 0 || (_ev$payload = ev.payload) === null || _ev$payload === void 0 ? void 0 : _ev$payload.mode) === 'sync-scene' || (ev === null || ev === void 0 ? void 0 : ev.__sync) === true;
563
+ var _ev$payload3;
564
+ return (ev === null || ev === void 0 ? void 0 : ev.type) === 'EXTERNAL_EVENT_SYNC_SCENE' || (ev === null || ev === void 0 || (_ev$payload3 = ev.payload) === null || _ev$payload3 === void 0 ? void 0 : _ev$payload3.mode) === 'sync-scene' || (ev === null || ev === void 0 ? void 0 : ev.__sync) === true;
394
565
  }
395
- function settle(_x2) {
566
+ function settle(_x2, _x3) {
396
567
  return _settle.apply(this, arguments);
397
568
  }
398
569
  function _settle() {
399
- _settle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7(ev) {
400
- var _ev$framesPerEvent, _ev$waitForGltfIdleAf;
401
- var frames, i, shouldWait, _ev$gltfTimeoutMs, timeoutMs;
570
+ _settle = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee7(ev, meta) {
571
+ var _ev$framesPerEvent, _ev$waitForGltfIdleAf, _ev$gltfTimeoutMs;
572
+ var frames, shouldWait, timeoutMs, i, start, _e$message2, _t2;
402
573
  return _regeneratorRuntime.wrap(function (_context7) {
403
574
  while (1) switch (_context7.prev = _context7.next) {
404
575
  case 0:
405
- frames = (_ev$framesPerEvent = ev === null || ev === void 0 ? void 0 : ev.framesPerEvent) !== null && _ev$framesPerEvent !== void 0 ? _ev$framesPerEvent : defaultFramesPerEvent; // (1) allow react/reducers to run (fixes “must zoom to see updates”)
576
+ frames = (_ev$framesPerEvent = ev === null || ev === void 0 ? void 0 : ev.framesPerEvent) !== null && _ev$framesPerEvent !== void 0 ? _ev$framesPerEvent : defaultFramesPerEvent;
577
+ shouldWait = (_ev$waitForGltfIdleAf = ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent) !== null && _ev$waitForGltfIdleAf !== void 0 ? _ev$waitForGltfIdleAf : waitForAssets;
578
+ timeoutMs = (_ev$gltfTimeoutMs = ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs) !== null && _ev$gltfTimeoutMs !== void 0 ? _ev$gltfTimeoutMs : defaultTimeout;
579
+ log('settle:start', _objectSpread(_objectSpread({}, meta), {}, {
580
+ frames: frames,
581
+ shouldWait: shouldWait,
582
+ timeoutMs: timeoutMs,
583
+ gltfInFlight: gltfTracker.getInFlight()
584
+ }));
585
+
586
+ // (1) allow react/reducers to run (fixes “must zoom to see updates”)
406
587
  i = 0;
407
588
  case 1:
408
589
  if (!(i < frames)) {
@@ -416,34 +597,52 @@ export function renderKitchenSimulator(container) {
416
597
  _context7.next = 1;
417
598
  break;
418
599
  case 3:
419
- // (2) optionally wait for assets
420
- // fastest safe approach: keep ON for events that add/replace/load models
421
- // You can override per-event via ev.waitForGltfIdleAfterEachEvent = false
422
- shouldWait = (_ev$waitForGltfIdleAf = ev === null || ev === void 0 ? void 0 : ev.waitForGltfIdleAfterEachEvent) !== null && _ev$waitForGltfIdleAf !== void 0 ? _ev$waitForGltfIdleAf : waitForAssets;
423
600
  if (!shouldWait) {
424
- _context7.next = 4;
601
+ _context7.next = 8;
425
602
  break;
426
603
  }
427
- timeoutMs = (_ev$gltfTimeoutMs = ev === null || ev === void 0 ? void 0 : ev.gltfTimeoutMs) !== null && _ev$gltfTimeoutMs !== void 0 ? _ev$gltfTimeoutMs : defaultTimeout;
428
- _context7.next = 4;
604
+ start = Date.now();
605
+ _context7.prev = 4;
606
+ _context7.next = 5;
429
607
  return gltfTracker.waitForIdle({
430
608
  timeoutMs: timeoutMs
431
609
  });
432
- case 4:
433
- _context7.next = 5;
434
- return nextFrame();
435
610
  case 5:
611
+ _context7.next = 7;
612
+ break;
613
+ case 6:
614
+ _context7.prev = 6;
615
+ _t2 = _context7["catch"](4);
616
+ error('settle:waitForIdle failed', _objectSpread(_objectSpread({}, meta), {}, {
617
+ err: (_e$message2 = _t2 === null || _t2 === void 0 ? void 0 : _t2.message) !== null && _e$message2 !== void 0 ? _e$message2 : _t2,
618
+ waitedMs: Date.now() - start,
619
+ gltfInFlight: gltfTracker.getInFlight()
620
+ }));
621
+ // Don’t throw unless you want the whole queue to stop.
622
+ // Keeping behavior: let it bubble so caller catches and continues.
623
+ throw _t2;
624
+ case 7:
625
+ log('settle:waitForIdle done', _objectSpread(_objectSpread({}, meta), {}, {
626
+ waitedMs: Date.now() - start,
627
+ gltfInFlight: gltfTracker.getInFlight()
628
+ }));
629
+ case 8:
630
+ _context7.next = 9;
631
+ return nextFrame();
632
+ case 9:
436
633
  if (!isSyncScene(ev)) {
437
- _context7.next = 6;
634
+ _context7.next = 10;
438
635
  break;
439
636
  }
440
- _context7.next = 6;
637
+ _context7.next = 10;
441
638
  return nextFrame();
442
- case 6:
639
+ case 10:
640
+ log('settle:done', _objectSpread({}, meta));
641
+ case 11:
443
642
  case "end":
444
643
  return _context7.stop();
445
644
  }
446
- }, _callee7);
645
+ }, _callee7, null, [[4, 6]]);
447
646
  }));
448
647
  return _settle.apply(this, arguments);
449
648
  }
@@ -452,7 +651,7 @@ export function renderKitchenSimulator(container) {
452
651
  }
453
652
  function _drain() {
454
653
  _drain = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee8() {
455
- var item, _t;
654
+ var myRunId, start, watchdogEveryMs, watchdog, MAX_ITERATIONS, iterations, item, seq, meta, _err$message2, _t3;
456
655
  return _regeneratorRuntime.wrap(function (_context8) {
457
656
  while (1) switch (_context8.prev = _context8.next) {
458
657
  case 0:
@@ -460,57 +659,131 @@ export function renderKitchenSimulator(container) {
460
659
  _context8.next = 1;
461
660
  break;
462
661
  }
662
+ log('drain:skip', {
663
+ draining: draining,
664
+ destroyed: destroyed,
665
+ queueLength: queue.length
666
+ });
463
667
  return _context8.abrupt("return");
464
668
  case 1:
465
669
  draining = true;
670
+ myRunId = drainRunId += 1;
671
+ start = Date.now();
672
+ log('drain:start', {
673
+ runId: myRunId,
674
+ queueLength: queue.length,
675
+ pendingMarkers: pendingMarkers.size,
676
+ gltfInFlight: gltfTracker.getInFlight()
677
+ });
678
+
679
+ // Watchdog: if drain runs too long, dump state (helps spot infinite loops)
680
+ watchdogEveryMs = 4000;
681
+ watchdog = setInterval(function () {
682
+ dumpLoopHint("drain watchdog runId=".concat(myRunId));
683
+ }, watchdogEveryMs); // Hard cap of iterations in one drain call (fail-open) to prevent true infinite loops
684
+ MAX_ITERATIONS = 5000;
685
+ iterations = 0;
466
686
  _context8.prev = 2;
467
687
  case 3:
468
688
  if (!(!destroyed && queue.length)) {
469
- _context8.next = 10;
689
+ _context8.next = 12;
690
+ break;
691
+ }
692
+ iterations += 1;
693
+ if (!(iterations >= MAX_ITERATIONS)) {
694
+ _context8.next = 4;
470
695
  break;
471
696
  }
697
+ dumpLoopHint("MAX_ITERATIONS reached runId=".concat(myRunId));
698
+ // fail-open: stop draining; future drain() calls can continue
699
+ return _context8.abrupt("continue", 12);
700
+ case 4:
472
701
  if (setExternalEventFn) {
473
- _context8.next = 5;
702
+ _context8.next = 6;
474
703
  break;
475
704
  }
476
- _context8.next = 4;
705
+ log('drain:waiting for setExternalEventFn');
706
+ _context8.next = 5;
477
707
  return nextFrame();
478
- case 4:
479
- return _context8.abrupt("continue", 3);
480
708
  case 5:
709
+ return _context8.abrupt("continue", 3);
710
+ case 6:
481
711
  item = queue.shift();
482
712
  if (!(item && item.__marker === MARKER)) {
483
- _context8.next = 6;
713
+ _context8.next = 7;
484
714
  break;
485
715
  }
486
716
  pendingMarkers["delete"](item.token);
717
+ log('drain:marker consumed', {
718
+ runId: myRunId,
719
+ pendingMarkers: pendingMarkers.size,
720
+ queueLength: queue.length
721
+ });
487
722
  return _context8.abrupt("continue", 3);
488
- case 6:
489
- _context8.prev = 6;
490
- setExternalEventFn(item);
491
- _context8.next = 7;
492
- return settle(item);
493
723
  case 7:
494
- _context8.next = 9;
495
- break;
496
- case 8:
724
+ seq = eventSeq += 1;
725
+ recordEvent(item);
726
+ meta = {
727
+ runId: myRunId,
728
+ seq: seq,
729
+ queueLengthAfterShift: queue.length,
730
+ pendingMarkers: pendingMarkers.size,
731
+ gltfInFlightBefore: gltfTracker.getInFlight(),
732
+ event: summarizeEvent(item)
733
+ };
734
+ log('drain:event begin', meta);
497
735
  _context8.prev = 8;
498
- _t = _context8["catch"](6);
499
- console.error('[kitchen-simulator] event failed:', item, _t);
500
- // IMPORTANT: continue so we can eventually consume the marker
501
- // Optionally you can decide to clear remaining queue here.
736
+ setExternalEventFn(item);
737
+ log('drain:setExternalEventFn called', meta);
738
+ _context8.next = 9;
739
+ return settle(item, meta);
502
740
  case 9:
503
- _context8.next = 3;
741
+ log('drain:event done', _objectSpread(_objectSpread({}, meta), {}, {
742
+ gltfInFlightAfter: gltfTracker.getInFlight()
743
+ }));
744
+ _context8.next = 11;
504
745
  break;
505
746
  case 10:
506
747
  _context8.prev = 10;
507
- draining = false;
508
- return _context8.finish(10);
748
+ _t3 = _context8["catch"](8);
749
+ error('drain:event failed', _objectSpread(_objectSpread({}, meta), {}, {
750
+ err: (_err$message2 = _t3 === null || _t3 === void 0 ? void 0 : _t3.message) !== null && _err$message2 !== void 0 ? _err$message2 : _t3,
751
+ gltfInFlight: gltfTracker.getInFlight()
752
+ }));
753
+ // IMPORTANT: continue so we can eventually consume the marker
509
754
  case 11:
755
+ // If queue never drains (e.g. events enqueue more events endlessly),
756
+ // these logs help identify repeating patterns:
757
+ if (debugEnabled && seq % 50 === 0) {
758
+ warn('drain:progress snapshot', {
759
+ runId: myRunId,
760
+ processedEvents: seq,
761
+ queueLength: queue.length,
762
+ pendingMarkers: pendingMarkers.size,
763
+ gltfInFlight: gltfTracker.getInFlight(),
764
+ lastEvents: lastEvents
765
+ });
766
+ }
767
+ _context8.next = 3;
768
+ break;
769
+ case 12:
770
+ _context8.prev = 12;
771
+ clearInterval(watchdog);
772
+ draining = false;
773
+ log('drain:done', {
774
+ runId: myRunId,
775
+ ms: Date.now() - start,
776
+ destroyed: destroyed,
777
+ queueLength: queue.length,
778
+ pendingMarkers: pendingMarkers.size,
779
+ gltfInFlight: gltfTracker.getInFlight()
780
+ });
781
+ return _context8.finish(12);
782
+ case 13:
510
783
  case "end":
511
784
  return _context8.stop();
512
785
  }
513
- }, _callee8, null, [[2,, 10, 11], [6, 8]]);
786
+ }, _callee8, null, [[2,, 12, 13], [8, 10]]);
514
787
  }));
515
788
  return _drain.apply(this, arguments);
516
789
  }
@@ -531,8 +804,14 @@ export function renderKitchenSimulator(container) {
531
804
  value: function componentDidMount() {
532
805
  var _this3 = this;
533
806
  this._mounted = true;
807
+ log('Wrapper mounted');
534
808
  setExternalEventFn = function setExternalEventFn(newEvent) {
535
- if (!_this3._mounted) return;
809
+ if (!_this3._mounted) {
810
+ warn('setExternalEventFn called while unmounted (ignored)');
811
+ return;
812
+ }
813
+ // This is the most important log to see if you’re triggering re-renders endlessly:
814
+ log('Wrapper setState(externalEvent)', summarizeEvent(newEvent));
536
815
  _this3.setState({
537
816
  externalEvent: newEvent
538
817
  });
@@ -541,12 +820,18 @@ export function renderKitchenSimulator(container) {
541
820
  }, {
542
821
  key: "componentWillUnmount",
543
822
  value: function componentWillUnmount() {
823
+ log('Wrapper will unmount');
544
824
  this._mounted = false;
545
825
  setExternalEventFn = null;
546
826
  }
547
827
  }, {
548
828
  key: "render",
549
829
  value: function render() {
830
+ // Render spam can indicate infinite render loop; keep it lightweight
831
+ if (debugEnabled) log('Wrapper render', {
832
+ hasExternalEvent: !!this.state.externalEvent,
833
+ externalEvent: summarizeEvent(this.state.externalEvent)
834
+ });
550
835
  return /*#__PURE__*/React.createElement(LiteRenderer, _extends({}, this.props, {
551
836
  externalEvent: this.state.externalEvent
552
837
  }));
@@ -555,21 +840,40 @@ export function renderKitchenSimulator(container) {
555
840
  }(React.Component);
556
841
  var api = {
557
842
  __render: function __render(nextProps) {
843
+ log('__render called', {
844
+ debug: !!(nextProps !== null && nextProps !== void 0 && nextProps.debug),
845
+ framesPerEvent: nextProps === null || nextProps === void 0 ? void 0 : nextProps.framesPerEvent,
846
+ waitForGltfIdleAfterEachEvent: nextProps === null || nextProps === void 0 ? void 0 : nextProps.waitForGltfIdleAfterEachEvent,
847
+ gltfTimeoutMs: nextProps === null || nextProps === void 0 ? void 0 : nextProps.gltfTimeoutMs
848
+ });
558
849
  root.render(/*#__PURE__*/React.createElement(Wrapper, nextProps));
559
850
  },
560
851
  // ✅ host can query current inFlight
561
852
  getGltfInFlight: function getGltfInFlight() {
562
- return gltfTracker.getInFlight();
853
+ var v = gltfTracker.getInFlight();
854
+ log('getGltfInFlight', v);
855
+ return v;
563
856
  },
564
857
  // ✅ host can subscribe to inFlight changes (loader)
565
858
  subscribeGltfInFlight: function subscribeGltfInFlight(cb) {
566
- return gltfTracker.subscribe(cb);
859
+ log('subscribeGltfInFlight');
860
+ return gltfTracker.subscribe(function (count) {
861
+ if (debugEnabled) log('gltf inFlight changed', count);
862
+ cb(count);
863
+ });
567
864
  },
568
865
  sendExternalEvents: function sendExternalEvents(eventOrEvents) {
569
- var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
570
- _ref5$timeoutMs = _ref5.timeoutMs,
571
- timeoutMs = _ref5$timeoutMs === void 0 ? 60000 : _ref5$timeoutMs;
866
+ var _ref8 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
867
+ _ref8$timeoutMs = _ref8.timeoutMs,
868
+ timeoutMs = _ref8$timeoutMs === void 0 ? 60000 : _ref8$timeoutMs;
572
869
  var events = Array.isArray(eventOrEvents) ? eventOrEvents : [eventOrEvents];
870
+ var batchId = Math.random().toString(16).slice(2);
871
+ log('sendExternalEvents:enqueue', {
872
+ batchId: batchId,
873
+ count: events.length,
874
+ timeoutMs: timeoutMs,
875
+ events: events.map(summarizeEvent)
876
+ });
573
877
  var _iterator2 = _createForOfIteratorHelper(events),
574
878
  _step2;
575
879
  try {
@@ -588,73 +892,112 @@ export function renderKitchenSimulator(container) {
588
892
  __marker: MARKER,
589
893
  token: token
590
894
  });
895
+ log('sendExternalEvents:marker added', {
896
+ batchId: batchId,
897
+ queueLength: queue.length,
898
+ pendingMarkers: pendingMarkers.size
899
+ });
591
900
  drain();
592
901
 
593
902
  // resolve when marker cleared
594
903
  return new Promise(function (resolve) {
595
904
  var start = Date.now();
596
905
  var check = /*#__PURE__*/function () {
597
- var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
906
+ var _ref9 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee6() {
907
+ var spins;
598
908
  return _regeneratorRuntime.wrap(function (_context6) {
599
909
  while (1) switch (_context6.prev = _context6.next) {
600
910
  case 0:
911
+ spins = 0;
912
+ case 1:
601
913
  if (destroyed) {
602
- _context6.next = 4;
914
+ _context6.next = 5;
603
915
  break;
604
916
  }
917
+ spins += 1;
605
918
  if (pendingMarkers.has(token)) {
606
- _context6.next = 1;
919
+ _context6.next = 2;
607
920
  break;
608
921
  }
922
+ log('sendExternalEvents:resolved', {
923
+ batchId: batchId,
924
+ ms: Date.now() - start,
925
+ spins: spins,
926
+ queueLength: queue.length
927
+ });
609
928
  resolve(true);
610
929
  return _context6.abrupt("return");
611
- case 1:
930
+ case 2:
612
931
  if (!(Date.now() - start > timeoutMs)) {
613
- _context6.next = 2;
932
+ _context6.next = 3;
614
933
  break;
615
934
  }
616
- console.error('[kitchen-simulator] sendExternalEvents timed out');
935
+ error('sendExternalEvents timed out', {
936
+ batchId: batchId,
937
+ timeoutMs: timeoutMs,
938
+ ms: Date.now() - start,
939
+ spins: spins,
940
+ queueLength: queue.length,
941
+ pendingMarkers: pendingMarkers.size,
942
+ gltfInFlight: gltfTracker.getInFlight(),
943
+ lastEvents: lastEvents
944
+ });
617
945
  pendingMarkers["delete"](token); // fail-open
618
946
  resolve(false);
619
947
  return _context6.abrupt("return");
620
- case 2:
621
- _context6.next = 3;
622
- return nextFrame();
623
948
  case 3:
624
- _context6.next = 0;
625
- break;
949
+ // Periodic “I might be stuck” hint
950
+ if (debugEnabled && spins % 240 === 0) {
951
+ dumpLoopHint("sendExternalEvents waiting batchId=".concat(batchId));
952
+ }
953
+ _context6.next = 4;
954
+ return nextFrame();
626
955
  case 4:
627
- resolve(false);
956
+ _context6.next = 1;
957
+ break;
628
958
  case 5:
959
+ warn('sendExternalEvents:destroyed while waiting', {
960
+ batchId: batchId
961
+ });
962
+ resolve(false);
963
+ case 6:
629
964
  case "end":
630
965
  return _context6.stop();
631
966
  }
632
967
  }, _callee6);
633
968
  }));
634
969
  return function check() {
635
- return _ref6.apply(this, arguments);
970
+ return _ref9.apply(this, arguments);
636
971
  };
637
972
  }();
638
973
  check();
639
974
  });
640
975
  },
641
976
  updateExternalEvent: function updateExternalEvent(e) {
977
+ log('updateExternalEvent', summarizeEvent(e));
642
978
  return api.sendExternalEvents(e);
643
979
  },
644
980
  clearQueue: function clearQueue() {
981
+ log('clearQueue', {
982
+ queueLength: queue.length,
983
+ pendingMarkers: pendingMarkers.size
984
+ });
645
985
  queue.length = 0;
646
986
  pendingMarkers.clear();
647
987
  },
648
988
  unmount: function unmount() {
989
+ log('unmount called');
649
990
  destroyed = true;
650
991
  api.clearQueue();
651
992
  gltfTracker.uninstall();
652
993
  var doUnmount = function doUnmount() {
653
994
  try {
995
+ log('root.unmount()');
654
996
  root.unmount();
655
997
  } finally {
656
998
  container[ROOT_KEY] = null;
657
999
  container[API_KEY] = null;
1000
+ log('unmounted + cleared container keys');
658
1001
  }
659
1002
  };
660
1003
  if (typeof queueMicrotask === 'function') queueMicrotask(doUnmount);else setTimeout(doUnmount, 0);
@@ -662,6 +1005,11 @@ export function renderKitchenSimulator(container) {
662
1005
  };
663
1006
  api.__render(props);
664
1007
  container[API_KEY] = api;
1008
+
1009
+ // Helpful: show how to enable debug quickly at runtime
1010
+ if (debugEnabled) {
1011
+ log('Debug enabled. Tip: window.__kitchenSimulatorDebug__ = true (global)');
1012
+ }
665
1013
  return api;
666
1014
  }
667
1015
  export default renderKitchenSimulator;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kitchen-simulator",
3
- "version": "5.10.7-react.18",
3
+ "version": "5.10.9-react.18",
4
4
  "description": "It is a kitchen simulator (self-contained micro-frontend).",
5
5
  "license": "MIT",
6
6
  "module": "es/index.js",