@casual-simulation/aux-common 3.1.16 → 3.1.19

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 (41) hide show
  1. package/bots/Bot.d.ts +13 -1
  2. package/bots/Bot.js +8 -0
  3. package/bots/Bot.js.map +1 -1
  4. package/bots/BotCalculations.d.ts +7 -5
  5. package/bots/BotCalculations.js +14 -11
  6. package/bots/BotCalculations.js.map +1 -1
  7. package/bots/BotEvents.d.ts +126 -22
  8. package/bots/BotEvents.js +22 -1
  9. package/bots/BotEvents.js.map +1 -1
  10. package/bots/StoredAux.d.ts +52 -0
  11. package/bots/StoredAux.js +49 -0
  12. package/bots/StoredAux.js.map +1 -0
  13. package/bots/index.d.ts +1 -0
  14. package/bots/index.js +1 -0
  15. package/bots/index.js.map +1 -1
  16. package/bots/test/BotCalculationContextTests.js +2 -0
  17. package/bots/test/BotCalculationContextTests.js.map +1 -1
  18. package/package.json +4 -4
  19. package/partitions/PartitionUtils.d.ts +11 -0
  20. package/partitions/PartitionUtils.js +37 -0
  21. package/partitions/PartitionUtils.js.map +1 -0
  22. package/partitions/RemoteYjsPartition.js +7 -4
  23. package/partitions/RemoteYjsPartition.js.map +1 -1
  24. package/runtime/AuxCompiler.d.ts +4 -0
  25. package/runtime/AuxCompiler.js +16 -1
  26. package/runtime/AuxCompiler.js.map +1 -1
  27. package/runtime/AuxGlobalContext.js +2 -0
  28. package/runtime/AuxGlobalContext.js.map +1 -1
  29. package/runtime/AuxLibrary.d.ts +4 -2
  30. package/runtime/AuxLibrary.js +102 -15
  31. package/runtime/AuxLibrary.js.map +1 -1
  32. package/runtime/AuxLibraryDefinitions.def +156 -2
  33. package/runtime/AuxResults.d.ts +1 -0
  34. package/runtime/AuxRuntime.d.ts +7 -1
  35. package/runtime/AuxRuntime.js +348 -123
  36. package/runtime/AuxRuntime.js.map +1 -1
  37. package/runtime/RuntimeBot.d.ts +5 -1
  38. package/runtime/RuntimeBot.js +109 -7
  39. package/runtime/RuntimeBot.js.map +1 -1
  40. package/runtime/test/TestScriptBotFactory.js +1 -0
  41. package/runtime/test/TestScriptBotFactory.js.map +1 -1
@@ -14,13 +14,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
14
14
  step((generator = generator.apply(thisArg, _arguments || [])).next());
15
15
  });
16
16
  };
17
- import { hasValue, tagsOnBot, isFormula, isScript, isNumber, BOT_SPACE_TAG, botUpdated, isBot, ORIGINAL_OBJECT, DEFAULT_ENERGY, getBotSpace, ON_ACTION_ACTION_NAME, breakIntoIndividualEvents, ON_BOT_ADDED_ACTION_NAME, ON_ANY_BOTS_ADDED_ACTION_NAME, ON_ANY_BOTS_REMOVED_ACTION_NAME, ON_BOT_CHANGED_ACTION_NAME, ON_ANY_BOTS_CHANGED_ACTION_NAME, updatedBot, TAG_MASK_SPACE_PRIORITIES, CLEAR_CHANGES_SYMBOL, DNA_TAG_PREFIX, isRuntimeBot, createBot, ON_ERROR, action, isBotInDimension, asyncResult, registerBuiltinPortal, defineGlobalBot, isBotLink, parseBotLink, isBotDate, parseBotDate, formatBotDate, isTaggedString, parseTaggedString, parseNumber, isTaggedNumber, isBotVector, parseBotVector, formatBotVector, isBotRotation, parseBotRotation, formatBotRotation, } from '../bots';
17
+ import { hasValue, tagsOnBot, isFormula, isScript, isNumber, BOT_SPACE_TAG, botUpdated, isBot, ORIGINAL_OBJECT, DEFAULT_ENERGY, getBotSpace, ON_ACTION_ACTION_NAME, breakIntoIndividualEvents, ON_BOT_ADDED_ACTION_NAME, ON_ANY_BOTS_ADDED_ACTION_NAME, ON_ANY_BOTS_REMOVED_ACTION_NAME, ON_BOT_CHANGED_ACTION_NAME, ON_ANY_BOTS_CHANGED_ACTION_NAME, updatedBot, TAG_MASK_SPACE_PRIORITIES, CLEAR_CHANGES_SYMBOL, DNA_TAG_PREFIX, isRuntimeBot, createBot, ON_ERROR, action, isBotInDimension, asyncResult, registerBuiltinPortal, defineGlobalBot, isBotLink, parseBotLink, isBotDate, parseBotDate, formatBotDate, isTaggedString, parseTaggedString, parseNumber, isTaggedNumber, isBotVector, parseBotVector, formatBotVector, isBotRotation, parseBotRotation, formatBotRotation, REPLACE_BOT_SYMBOL, } from '../bots';
18
18
  import { Subject, Subscription } from 'rxjs';
19
19
  import { AuxCompiler, getInterpretableFunction, isInterpretableFunction, } from './AuxCompiler';
20
20
  import { addToContext, MemoryGlobalContext, removeFromContext, isInContext, } from './AuxGlobalContext';
21
21
  import { createDefaultLibrary, GET_RUNTIME, } from './AuxLibrary';
22
22
  import { createRuntimeBot, RealtimeEditMode, } from './RuntimeBot';
23
- import { RanOutOfEnergyError } from './AuxResults';
23
+ import { RanOutOfEnergyError, } from './AuxResults';
24
24
  import { convertToCopiableValue, DeepObjectError, isPromise, isRuntimePromise, markAsRuntimePromise, } from './Utils';
25
25
  import { DefaultRealtimeEditModeProvider, } from './AuxRealtimeEditModeProvider';
26
26
  import { sortBy, forOwn, merge, union } from 'lodash';
@@ -33,6 +33,7 @@ import { Rotation, Vector2, Vector3 } from '../math';
33
33
  import { isGenerator, UNCOPIABLE, } from '@casual-simulation/js-interpreter/InterpreterUtils';
34
34
  import { v4 as uuid } from 'uuid';
35
35
  import { importInterpreter as _dynamicImportInterpreter } from './AuxRuntimeDynamicImports';
36
+ import { UNMAPPABLE, } from '../bots/BotEvents';
36
37
  let Interpreter;
37
38
  let DeclarativeEnvironmentRecord;
38
39
  let DefinePropertyOrThrow;
@@ -102,6 +103,16 @@ export class AuxRuntime {
102
103
  this._portalBots = new Map();
103
104
  this._builtinPortalBots = [];
104
105
  this._globalChanges = {};
106
+ this._beforeActionListeners = [];
107
+ this._scriptActionEnqueuedListeners = [];
108
+ this._scriptUpdatedTagListeners = [];
109
+ this._scriptUpdatedTagMaskListeners = [];
110
+ // private _beforeScriptEnterListeners: ((
111
+ // trace: DebuggerScriptEnterTrace
112
+ // ) => void)[] = [];
113
+ // private _afterScriptExitListeners: ((
114
+ // trace: DebuggerScriptExitTrace
115
+ // ) => void)[] = [];
105
116
  /**
106
117
  * The counter that is used to generate function names.
107
118
  */
@@ -281,9 +292,22 @@ export class AuxRuntime {
281
292
  * @param actions The actions to process.
282
293
  */
283
294
  process(actions) {
295
+ if (this._beforeActionListeners.length > 0) {
296
+ for (let func of this._beforeActionListeners) {
297
+ for (let action of actions) {
298
+ try {
299
+ func(action);
300
+ }
301
+ catch (err) {
302
+ console.error(err);
303
+ }
304
+ }
305
+ }
306
+ }
284
307
  this._processBatch();
285
- this._processCore(actions);
308
+ const result = this._processCore(actions);
286
309
  this._processBatch();
310
+ return result;
287
311
  }
288
312
  _getExecutingDebugger() {
289
313
  return this._currentDebugger;
@@ -296,7 +320,7 @@ export class AuxRuntime {
296
320
  yield importInterpreter();
297
321
  const interpreter = (options === null || options === void 0 ? void 0 : options.pausable) ? new Interpreter() : null;
298
322
  const runtime = new AuxRuntime(this._globalContext.version, this._globalContext.device, this._libraryFactory, this._editModeProvider, this._forceSignedScripts, this._exemptSpaces, forceSyncScripts, interpreter);
299
- runtime._autoBatch = false;
323
+ runtime._autoBatch = true;
300
324
  let idCount = 0;
301
325
  if (!(options === null || options === void 0 ? void 0 : options.useRealUUIDs)) {
302
326
  runtime._globalContext.uuid = () => {
@@ -381,7 +405,38 @@ export class AuxRuntime {
381
405
  const errors = runtime._processUnbatchedErrors();
382
406
  allErrors.push(...errors);
383
407
  return allErrors;
384
- }, setPauseTrigger(b, tag, options) {
408
+ }, onBeforeUserAction: (listener) => {
409
+ runtime._beforeActionListeners.push(listener);
410
+ }, onScriptActionEnqueued: (listener) => {
411
+ runtime._scriptActionEnqueuedListeners.push(listener);
412
+ }, onAfterScriptUpdatedTag: (listener) => {
413
+ runtime._scriptUpdatedTagListeners.push(listener);
414
+ }, onAfterScriptUpdatedTagMask: (listener) => {
415
+ runtime._scriptUpdatedTagMaskListeners.push(listener);
416
+ }, getCallStack() {
417
+ if (!interpreter) {
418
+ throw new Error('getCallStack() is only supported on pausable debuggers.');
419
+ }
420
+ return runtime._mapCallStack(interpreter.agent.executionContextStack);
421
+ },
422
+ performUserAction(...actions) {
423
+ return __awaiter(this, void 0, void 0, function* () {
424
+ const result = yield runtime.process(actions);
425
+ return result.map((r) => (r ? r.results : null));
426
+ });
427
+ },
428
+ // TODO: Determine whether to support this
429
+ // onBeforeScriptEnter: (
430
+ // listener: (trace: DebuggerScriptEnterTrace) => void
431
+ // ) => {
432
+ // runtime._beforeScriptEnterListeners.push(listener);
433
+ // },
434
+ // onAfterScriptExit: (
435
+ // listener: (trace: DebuggerScriptExitTrace) => void
436
+ // ) => {
437
+ // runtime._afterScriptExitListeners.push(listener);
438
+ // },
439
+ setPauseTrigger(b, tag, options) {
385
440
  var _a, _b, _c;
386
441
  if (typeof b === 'object' && 'triggerId' in b) {
387
442
  runtime.setBreakpoint({
@@ -485,113 +540,7 @@ export class AuxRuntime {
485
540
  const pause = {
486
541
  pauseId: stop.stopId,
487
542
  state: stop.state,
488
- callStack: stop.stack.map((s) => {
489
- const callSite = s.callSite;
490
- const funcName = callSite.getFunctionName();
491
- let funcLocation = {};
492
- if (funcName) {
493
- const f = runtime._functionMap.get(funcName);
494
- if (f) {
495
- funcLocation.name =
496
- f.metadata.diagnosticFunctionName;
497
- const location = runtime._compiler.calculateOriginalLineLocation(f, {
498
- lineNumber: callSite.lineNumber,
499
- column: callSite.columnNumber,
500
- });
501
- funcLocation.lineNumber =
502
- location.lineNumber + 1;
503
- funcLocation.columnNumber =
504
- location.column + 1;
505
- const tagName = f.metadata.context
506
- .tag;
507
- const bot = f.metadata.context.bot;
508
- if (bot) {
509
- funcLocation.botId = bot.id;
510
- }
511
- if (tagName) {
512
- funcLocation.tag = tagName;
513
- }
514
- }
515
- else {
516
- funcLocation.name = funcName;
517
- }
518
- }
519
- if (!hasValue(funcLocation.lineNumber) &&
520
- !hasValue(funcLocation.columnNumber) &&
521
- hasValue(callSite.lineNumber) &&
522
- hasValue(callSite.columnNumber)) {
523
- funcLocation.lineNumber = callSite.lineNumber;
524
- funcLocation.columnNumber =
525
- callSite.columnNumber;
526
- }
527
- if (!hasValue(funcLocation.lineNumber) &&
528
- !hasValue(funcLocation.columnNumber) &&
529
- !hasValue(funcLocation.name)) {
530
- funcLocation = null;
531
- }
532
- const ret = {
533
- location: funcLocation,
534
- listVariables() {
535
- let variables = [];
536
- if (s.LexicalEnvironment instanceof
537
- DeclarativeEnvironmentRecord) {
538
- addBindingsFromEnvironment(s.LexicalEnvironment, 'block');
539
- }
540
- if (s.VariableEnvironment instanceof
541
- DeclarativeEnvironmentRecord) {
542
- addBindingsFromEnvironment(s.VariableEnvironment, 'frame');
543
- let parent = s.VariableEnvironment.OuterEnv;
544
- while (parent) {
545
- if (parent instanceof
546
- DeclarativeEnvironmentRecord) {
547
- addBindingsFromEnvironment(parent, 'closure');
548
- }
549
- parent = parent.OuterEnv;
550
- }
551
- }
552
- return variables;
553
- function addBindingsFromEnvironment(env, scope) {
554
- for (let [nameValue, binding,] of env.bindings.entries()) {
555
- const name = interpreter.copyFromValue(nameValue);
556
- const initialized = !!binding.initialized;
557
- const mutable = !!binding.mutable;
558
- const value = initialized
559
- ? interpreter.reverseProxyObject(binding.value, false)
560
- : undefined;
561
- const variable = {
562
- name,
563
- value,
564
- writable: mutable,
565
- scope,
566
- };
567
- if (!initialized) {
568
- variable.initialized = false;
569
- }
570
- variables.push(variable);
571
- }
572
- }
573
- },
574
- setVariableValue(name, value) {
575
- if (s.LexicalEnvironment instanceof
576
- DeclarativeEnvironmentRecord) {
577
- const nameValue = interpreter.copyToValue(name);
578
- const proxiedValue = interpreter.proxyObject(value);
579
- if (nameValue.Type !== 'normal') {
580
- throw interpreter.copyFromValue(nameValue.Value);
581
- }
582
- if (proxiedValue.Type !== 'normal') {
583
- throw interpreter.copyFromValue(proxiedValue.Value);
584
- }
585
- const result = s.LexicalEnvironment.SetMutableBinding(nameValue.Value, proxiedValue.Value, Value.true);
586
- if (result.Type !== 'normal') {
587
- throw interpreter.copyFromValue(result.Value);
588
- }
589
- return interpreter.copyFromValue(result.Value);
590
- }
591
- },
592
- };
593
- return ret;
594
- }),
543
+ callStack: runtime._mapCallStack(stop.stack),
595
544
  trigger: {
596
545
  triggerId: stop.breakpoint.id,
597
546
  botId: stop.breakpoint.botId,
@@ -610,46 +559,193 @@ export class AuxRuntime {
610
559
  [GET_RUNTIME]() {
611
560
  return runtime;
612
561
  },
562
+ get configBot() {
563
+ return runtime.userBot;
564
+ },
565
+ getPortalBots() {
566
+ var _a;
567
+ let portalBots = new Map();
568
+ for (let [portal, id] of runtime._portalBots) {
569
+ portalBots.set(portal, (_a = runtime.currentState[id]) === null || _a === void 0 ? void 0 : _a.script);
570
+ }
571
+ return portalBots;
572
+ },
613
573
  create });
614
574
  runtime._currentDebugger = debug;
615
575
  this._scheduleJobQueueCheck();
616
576
  return debug;
617
577
  });
618
578
  }
579
+ _mapCallStack(stack) {
580
+ const interpreter = this._interpreter;
581
+ return stack.map((s) => {
582
+ const callSite = s.callSite;
583
+ const funcName = callSite.getFunctionName();
584
+ let funcLocation = {};
585
+ if (funcName) {
586
+ const f = this._functionMap.get(funcName);
587
+ if (f) {
588
+ funcLocation.name = f.metadata.diagnosticFunctionName;
589
+ const location = this._compiler.calculateOriginalLineLocation(f, {
590
+ lineNumber: callSite.lineNumber,
591
+ column: callSite.columnNumber,
592
+ });
593
+ funcLocation.lineNumber = location.lineNumber + 1;
594
+ funcLocation.columnNumber = location.column + 1;
595
+ const tagName = f.metadata.context.tag;
596
+ const bot = f.metadata.context.bot;
597
+ if (bot) {
598
+ funcLocation.botId = bot.id;
599
+ }
600
+ if (tagName) {
601
+ funcLocation.tag = tagName;
602
+ }
603
+ }
604
+ else {
605
+ funcLocation.name = funcName;
606
+ }
607
+ }
608
+ if (!hasValue(funcLocation.lineNumber) &&
609
+ !hasValue(funcLocation.columnNumber) &&
610
+ hasValue(callSite.lineNumber) &&
611
+ hasValue(callSite.columnNumber)) {
612
+ funcLocation.lineNumber = callSite.lineNumber;
613
+ funcLocation.columnNumber = callSite.columnNumber;
614
+ }
615
+ if (!hasValue(funcLocation.lineNumber) &&
616
+ !hasValue(funcLocation.columnNumber) &&
617
+ !hasValue(funcLocation.name)) {
618
+ funcLocation = null;
619
+ }
620
+ const ret = {
621
+ location: funcLocation,
622
+ listVariables() {
623
+ let variables = [];
624
+ if (s.LexicalEnvironment instanceof
625
+ DeclarativeEnvironmentRecord) {
626
+ addBindingsFromEnvironment(s.LexicalEnvironment, 'block');
627
+ }
628
+ if (s.VariableEnvironment instanceof
629
+ DeclarativeEnvironmentRecord) {
630
+ addBindingsFromEnvironment(s.VariableEnvironment, 'frame');
631
+ let parent = s.VariableEnvironment.OuterEnv;
632
+ while (parent) {
633
+ if (parent instanceof DeclarativeEnvironmentRecord) {
634
+ addBindingsFromEnvironment(parent, 'closure');
635
+ }
636
+ parent = parent.OuterEnv;
637
+ }
638
+ }
639
+ return variables;
640
+ function addBindingsFromEnvironment(env, scope) {
641
+ for (let [nameValue, binding,] of env.bindings.entries()) {
642
+ const name = interpreter.copyFromValue(nameValue);
643
+ const initialized = !!binding.initialized;
644
+ const mutable = !!binding.mutable;
645
+ const value = initialized
646
+ ? interpreter.reverseProxyObject(binding.value, false)
647
+ : undefined;
648
+ const variable = {
649
+ name,
650
+ value,
651
+ writable: mutable,
652
+ scope,
653
+ };
654
+ if (!initialized) {
655
+ variable.initialized = false;
656
+ }
657
+ variables.push(variable);
658
+ }
659
+ }
660
+ },
661
+ setVariableValue(name, value) {
662
+ if (s.LexicalEnvironment instanceof
663
+ DeclarativeEnvironmentRecord) {
664
+ const nameValue = interpreter.copyToValue(name);
665
+ const proxiedValue = interpreter.proxyObject(value);
666
+ if (nameValue.Type !== 'normal') {
667
+ throw interpreter.copyFromValue(nameValue.Value);
668
+ }
669
+ if (proxiedValue.Type !== 'normal') {
670
+ throw interpreter.copyFromValue(proxiedValue.Value);
671
+ }
672
+ const result = s.LexicalEnvironment.SetMutableBinding(nameValue.Value, proxiedValue.Value, Value.true);
673
+ if (result.Type !== 'normal') {
674
+ throw interpreter.copyFromValue(result.Value);
675
+ }
676
+ return interpreter.copyFromValue(result.Value);
677
+ }
678
+ },
679
+ };
680
+ return ret;
681
+ });
682
+ }
619
683
  _processCore(actions) {
620
684
  const _this = this;
685
+ const results = [];
686
+ function processAction(action, addToResults) {
687
+ let promise = _this._processAction(action);
688
+ if (addToResults) {
689
+ if (isRuntimePromise(promise)) {
690
+ return markAsRuntimePromise(promise.then((result) => {
691
+ results.push(result);
692
+ }));
693
+ }
694
+ else {
695
+ results.push(promise);
696
+ }
697
+ return;
698
+ }
699
+ return promise;
700
+ }
621
701
  function handleRejection(action, rejection) {
622
702
  let promise = processListOfMaybePromises(null, rejection.newActions, (action) => {
623
- return _this._processAction(action);
703
+ return processAction(action, false);
624
704
  });
625
705
  if (rejection.rejected) {
626
706
  return;
627
707
  }
628
708
  if (promise) {
629
- return markAsRuntimePromise(promise.then((p) => _this._processAction(action)));
709
+ return markAsRuntimePromise(promise.then((p) => processAction(action, true)));
630
710
  }
631
711
  else {
632
- return _this._processAction(action);
712
+ return processAction(action, true);
633
713
  }
634
714
  }
635
- return processListOfMaybePromises(null, actions, (action) => {
715
+ let promise = processListOfMaybePromises(null, actions, (action) => {
636
716
  let rejection = this._rejectAction(action);
717
+ let result;
637
718
  if (isRuntimePromise(rejection)) {
638
- return markAsRuntimePromise(rejection.then((result) => handleRejection(action, result)));
719
+ result = markAsRuntimePromise(rejection.then((result) => handleRejection(action, result)));
639
720
  }
640
721
  else {
641
- return handleRejection(action, rejection);
722
+ result = handleRejection(action, rejection);
642
723
  }
724
+ return result;
643
725
  });
726
+ if (isRuntimePromise(promise)) {
727
+ return markAsRuntimePromise(promise.then(() => results));
728
+ }
729
+ else {
730
+ return results;
731
+ }
644
732
  }
645
733
  _processAction(action) {
646
734
  if (action.type === 'action') {
647
735
  const result = this._shout(action.eventName, action.botIds, action.argument, false);
648
736
  if (isRuntimePromise(result)) {
649
- return markAsRuntimePromise(result.then((result) => this._processCore(result.actions)));
737
+ return markAsRuntimePromise(result
738
+ .then((result) => this._processCore(result.actions))
739
+ .then(() => result));
650
740
  }
651
741
  else {
652
- return this._processCore(result.actions);
742
+ let promise = this._processCore(result.actions);
743
+ if (isRuntimePromise(promise)) {
744
+ return markAsRuntimePromise(promise.then(() => result));
745
+ }
746
+ else {
747
+ return result;
748
+ }
653
749
  }
654
750
  }
655
751
  else if (action.type === 'run_script') {
@@ -662,6 +758,7 @@ export class AuxRuntime {
662
758
  if (hasValue(action.taskId)) {
663
759
  this._globalContext.resolveTask(action.taskId, result.result, false);
664
760
  }
761
+ return null;
665
762
  });
666
763
  }
667
764
  else {
@@ -671,6 +768,7 @@ export class AuxRuntime {
671
768
  }
672
769
  }
673
770
  }
771
+ return null;
674
772
  }));
675
773
  }
676
774
  else {
@@ -682,6 +780,7 @@ export class AuxRuntime {
682
780
  this._scheduleJobQueueCheck();
683
781
  }
684
782
  }
783
+ return null;
685
784
  }));
686
785
  }
687
786
  if (hasValue(action.taskId)) {
@@ -693,7 +792,13 @@ export class AuxRuntime {
693
792
  }
694
793
  else if (action.type === 'apply_state') {
695
794
  const events = breakIntoIndividualEvents(this.currentState, action);
696
- return this._processCore(events);
795
+ const promise = this._processCore(events);
796
+ if (isRuntimePromise(promise)) {
797
+ return markAsRuntimePromise(promise.then(() => null));
798
+ }
799
+ else {
800
+ return null;
801
+ }
697
802
  }
698
803
  else if (action.type === 'async_result') {
699
804
  const value = action.mapBotsInResult === true
@@ -752,12 +857,21 @@ export class AuxRuntime {
752
857
  this._actionBatch.push(action);
753
858
  }
754
859
  if (hasValue(action.taskId)) {
755
- return this._processCore([asyncResult(action.taskId, null)]);
860
+ const promise = this._processCore([
861
+ asyncResult(action.taskId, null),
862
+ ]);
863
+ if (isRuntimePromise(promise)) {
864
+ return markAsRuntimePromise(promise.then(() => null));
865
+ }
866
+ else {
867
+ return null;
868
+ }
756
869
  }
757
870
  }
758
871
  else {
759
872
  this._actionBatch.push(action);
760
873
  }
874
+ return null;
761
875
  }
762
876
  _registerPortalBot(portalId, botId) {
763
877
  const hadPortalBot = this._portalBots.has(portalId);
@@ -1211,7 +1325,7 @@ export class AuxRuntime {
1211
1325
  }
1212
1326
  let newBot = this._createCompiledBot(bot, false);
1213
1327
  if (!!existing) {
1214
- newBot.script.vars = existing.script.vars;
1328
+ existing.script[REPLACE_BOT_SYMBOL](newBot.script);
1215
1329
  }
1216
1330
  let precalculated = {
1217
1331
  id: bot.id,
@@ -1435,6 +1549,18 @@ export class AuxRuntime {
1435
1549
  });
1436
1550
  }
1437
1551
  }
1552
+ notifyActionEnqueued(action) {
1553
+ if (this._scriptActionEnqueuedListeners.length > 0) {
1554
+ for (let listener of this._scriptActionEnqueuedListeners) {
1555
+ try {
1556
+ listener(action);
1557
+ }
1558
+ catch (err) {
1559
+ console.error(err);
1560
+ }
1561
+ }
1562
+ }
1563
+ }
1438
1564
  createRuntimeBot(bot) {
1439
1565
  const space = getBotSpace(bot);
1440
1566
  const mode = this._editModeProvider.getEditMode(space);
@@ -1673,6 +1799,7 @@ export class AuxRuntime {
1673
1799
  if (isRuntimeBot(newValue)) {
1674
1800
  throw new Error(`It is not possible to save bots as tag values. (Setting '${tag}' on ${bot.id})`);
1675
1801
  }
1802
+ const oldValue = bot.values[tag];
1676
1803
  const space = getBotSpace(bot);
1677
1804
  const mode = this._editModeProvider.getEditMode(space);
1678
1805
  if (mode === RealtimeEditMode.Immediate) {
@@ -1689,6 +1816,21 @@ export class AuxRuntime {
1689
1816
  else if (newValue instanceof Rotation) {
1690
1817
  newValue = formatBotRotation(newValue);
1691
1818
  }
1819
+ if (this._scriptUpdatedTagListeners.length > 0) {
1820
+ for (let listener of this._scriptUpdatedTagListeners) {
1821
+ try {
1822
+ listener({
1823
+ botId: bot.id,
1824
+ tag,
1825
+ oldValue,
1826
+ newValue,
1827
+ });
1828
+ }
1829
+ catch (err) {
1830
+ console.error(err);
1831
+ }
1832
+ }
1833
+ }
1692
1834
  return {
1693
1835
  mode,
1694
1836
  changedValue: newValue,
@@ -1704,6 +1846,7 @@ export class AuxRuntime {
1704
1846
  if (isRuntimeBot(value)) {
1705
1847
  throw new Error(`It is not possible to save bots as tag values. (Setting '${tag}' on ${bot.id})`);
1706
1848
  }
1849
+ let oldValuesAndSpaces = [];
1707
1850
  let updated = false;
1708
1851
  for (let space of spaces) {
1709
1852
  const mode = this._editModeProvider.getEditMode(space);
@@ -1714,6 +1857,7 @@ export class AuxRuntime {
1714
1857
  if (!bot.masks[space]) {
1715
1858
  bot.masks[space] = {};
1716
1859
  }
1860
+ let oldValue = bot.masks[space][tag];
1717
1861
  if (isTagEdit(value)) {
1718
1862
  if (!bot.originalTagMaskEditValues[space]) {
1719
1863
  bot.originalTagMaskEditValues[space] = {};
@@ -1728,6 +1872,10 @@ export class AuxRuntime {
1728
1872
  bot.masks[space][tag] = value;
1729
1873
  }
1730
1874
  updated = true;
1875
+ oldValuesAndSpaces.push({
1876
+ space,
1877
+ oldValue,
1878
+ });
1731
1879
  }
1732
1880
  }
1733
1881
  if (updated) {
@@ -1744,6 +1892,24 @@ export class AuxRuntime {
1744
1892
  else if (value instanceof Rotation) {
1745
1893
  value = formatBotRotation(value);
1746
1894
  }
1895
+ if (updated && this._scriptUpdatedTagMaskListeners.length > 0) {
1896
+ for (let listener of this._scriptUpdatedTagMaskListeners) {
1897
+ for (let { oldValue, space } of oldValuesAndSpaces) {
1898
+ try {
1899
+ listener({
1900
+ botId: bot.id,
1901
+ tag,
1902
+ oldValue,
1903
+ newValue: value,
1904
+ space,
1905
+ });
1906
+ }
1907
+ catch (err) {
1908
+ console.error(err);
1909
+ }
1910
+ }
1911
+ }
1912
+ }
1747
1913
  return {
1748
1914
  mode: RealtimeEditMode.Immediate,
1749
1915
  changedValue: value,
@@ -1979,6 +2145,20 @@ export class AuxRuntime {
1979
2145
  ctx.creator = ctx.bot
1980
2146
  ? this._getRuntimeBot(ctx.bot.script.tags.creator)
1981
2147
  : null;
2148
+ // TODO: Determine whether to support this
2149
+ // if (this._beforeScriptEnterListeners.length > 0) {
2150
+ // for (let listener of this._beforeScriptEnterListeners) {
2151
+ // try {
2152
+ // listener({
2153
+ // botId: ctx.bot.id,
2154
+ // tag: ctx.tag,
2155
+ // enterType: 'call',
2156
+ // });
2157
+ // } catch (err) {
2158
+ // console.error(err);
2159
+ // }
2160
+ // }
2161
+ // }
1982
2162
  },
1983
2163
  onError: (err, ctx, meta) => {
1984
2164
  const data = this._handleError(err, ctx.bot, ctx.tag);
@@ -2087,6 +2267,11 @@ export class AuxRuntime {
2087
2267
  if (map.has(value)) {
2088
2268
  return map.get(value);
2089
2269
  }
2270
+ if (typeof value === 'object' &&
2271
+ value !== null &&
2272
+ value[UNMAPPABLE] === true) {
2273
+ return value;
2274
+ }
2090
2275
  if (hasValue(value) &&
2091
2276
  !Array.isArray(value) &&
2092
2277
  !(value instanceof ArrayBuffer) &&
@@ -2220,6 +2405,46 @@ export class AuxRuntime {
2220
2405
  // });
2221
2406
  // }
2222
2407
  _processJobQueueNow() {
2408
+ // TODO: Determine whether to support this
2409
+ // let scriptJobs: { botId: string; tag: string }[] = [];
2410
+ // for (let job of this._interpreter.agent.jobQueue) {
2411
+ // if (
2412
+ // job.callerScriptOrModule &&
2413
+ // FUNCTION_METADATA in job.callerScriptOrModule
2414
+ // ) {
2415
+ // const meta: AuxScriptMetadata = (
2416
+ // job.callerScriptOrModule as any
2417
+ // )[FUNCTION_METADATA] as AuxScriptMetadata;
2418
+ // const context = meta.context as {
2419
+ // bot: CompiledBot;
2420
+ // tag: string;
2421
+ // };
2422
+ // const botId = context.bot.id;
2423
+ // const tag = context.tag;
2424
+ // scriptJobs.push({
2425
+ // botId,
2426
+ // tag,
2427
+ // });
2428
+ // }
2429
+ // }
2430
+ // if (
2431
+ // scriptJobs.length > 0 &&
2432
+ // this._beforeScriptEnterListeners.length > 0
2433
+ // ) {
2434
+ // for (let job of scriptJobs) {
2435
+ // for (let listener of this._beforeScriptEnterListeners) {
2436
+ // try {
2437
+ // listener({
2438
+ // enterType: 'task',
2439
+ // botId: job.botId,
2440
+ // tag: job.tag,
2441
+ // });
2442
+ // } catch (err) {
2443
+ // console.error(err);
2444
+ // }
2445
+ // }
2446
+ // }
2447
+ // }
2223
2448
  const queueGen = this._interpreter.runJobQueue();
2224
2449
  while (true) {
2225
2450
  const next = queueGen.next();