@casual-simulation/aux-common 3.1.8 → 3.1.9-alpha.3340590989

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 (38) hide show
  1. package/math/Vector2.js +6 -1
  2. package/math/Vector2.js.map +1 -1
  3. package/math/Vector3.js +6 -1
  4. package/math/Vector3.js.map +1 -1
  5. package/package.json +4 -2
  6. package/runtime/AuxCompiler.d.ts +74 -1
  7. package/runtime/AuxCompiler.js +332 -25
  8. package/runtime/AuxCompiler.js.map +1 -1
  9. package/runtime/AuxGlobalContext.d.ts +14 -4
  10. package/runtime/AuxGlobalContext.js +9 -1
  11. package/runtime/AuxGlobalContext.js.map +1 -1
  12. package/runtime/AuxLibrary.d.ts +191 -10
  13. package/runtime/AuxLibrary.js +172 -37
  14. package/runtime/AuxLibrary.js.map +1 -1
  15. package/runtime/AuxLibraryDefinitions.def +469 -82
  16. package/runtime/AuxRuntime.d.ts +66 -7
  17. package/runtime/AuxRuntime.js +976 -118
  18. package/runtime/AuxRuntime.js.map +1 -1
  19. package/runtime/AuxRuntimeDynamicImports.d.ts +14 -0
  20. package/runtime/AuxRuntimeDynamicImports.js +24 -0
  21. package/runtime/AuxRuntimeDynamicImports.js.map +1 -0
  22. package/runtime/CompiledBot.d.ts +59 -1
  23. package/runtime/CompiledBot.js +2 -0
  24. package/runtime/CompiledBot.js.map +1 -1
  25. package/runtime/RuntimeBot.d.ts +17 -0
  26. package/runtime/RuntimeBot.js +85 -5
  27. package/runtime/RuntimeBot.js.map +1 -1
  28. package/runtime/Transpiler.d.ts +21 -0
  29. package/runtime/Transpiler.js +27 -0
  30. package/runtime/Transpiler.js.map +1 -1
  31. package/runtime/Utils.d.ts +11 -0
  32. package/runtime/Utils.js +30 -1
  33. package/runtime/Utils.js.map +1 -1
  34. package/runtime/test/RuntimeTestHelpers.d.ts +5 -0
  35. package/runtime/test/RuntimeTestHelpers.js +11 -0
  36. package/runtime/test/RuntimeTestHelpers.js.map +1 -1
  37. package/test/TestHelpers.js +2 -2
  38. package/test/TestHelpers.js.map +1 -1
@@ -38,12 +38,32 @@ import SeedRandom from 'seedrandom';
38
38
  import { DateTime } from 'luxon';
39
39
  import * as hooks from 'preact/hooks';
40
40
  import { render } from 'preact';
41
+ import { isGenerator, UNCOPIABLE, unwind, } from '@casual-simulation/js-interpreter/InterpreterUtils';
42
+ import { INTERPRETABLE_FUNCTION } from './AuxCompiler';
41
43
  const _html = htm.bind(h);
42
44
  const html = ((...args) => {
43
45
  return _html(...args);
44
46
  });
45
47
  html.h = h;
46
48
  html.f = Fragment;
49
+ /**
50
+ * Creates a new interpretable function based on the given function.
51
+ * @param interpretableFunc
52
+ */
53
+ export function createInterpretableFunction(interpretableFunc) {
54
+ const normalFunc = ((...args) => unwind(interpretableFunc(...args)));
55
+ normalFunc[INTERPRETABLE_FUNCTION] = interpretableFunc;
56
+ return normalFunc;
57
+ }
58
+ /**
59
+ * Sets the INTERPRETABLE_FUNCTION property on the given object (semantically a function) to the given interpretable version and returns the object.
60
+ * @param interpretableFunc The version of the function that should be used as the interpretable version of the function.
61
+ * @param normalFunc The function that should be tagged.
62
+ */
63
+ export function tagAsInterpretableFunction(interpretableFunc, normalFunc) {
64
+ normalFunc[INTERPRETABLE_FUNCTION] = interpretableFunc;
65
+ return normalFunc;
66
+ }
47
67
  /**
48
68
  * The status codes that should be used to retry web requests.
49
69
  */
@@ -139,9 +159,25 @@ export function createDefaultLibrary(context) {
139
159
  };
140
160
  const webhookFunc = makeMockableFunction(webhook, 'webhook');
141
161
  webhookFunc.post = makeMockableFunction(webhook.post, 'webhook.post');
142
- const shoutImpl = shout;
162
+ const shoutImpl = ((name, arg) => unwind(shout(name, arg)));
143
163
  const shoutProxy = new Proxy(shoutImpl, {
144
164
  get(target, name, reciever) {
165
+ if (typeof name === 'symbol' ||
166
+ (typeof target === 'function' && name in Function.prototype)) {
167
+ return Reflect.get(target, name, reciever);
168
+ }
169
+ return (arg) => {
170
+ return unwind(shout(name, arg));
171
+ };
172
+ },
173
+ });
174
+ const interpretableShoutImpl = shout;
175
+ const interpretableShoutProxy = new Proxy(interpretableShoutImpl, {
176
+ get(target, name, reciever) {
177
+ if (typeof name === 'symbol' ||
178
+ (typeof target === 'function' && name in Function.prototype)) {
179
+ return Reflect.get(target, name, reciever);
180
+ }
145
181
  return (arg) => {
146
182
  return shout(name, arg);
147
183
  };
@@ -173,8 +209,8 @@ export function createDefaultLibrary(context) {
173
209
  renameTag,
174
210
  applyMod,
175
211
  subtractMods,
176
- destroy,
177
- changeState,
212
+ destroy: createInterpretableFunction(destroy),
213
+ changeState: createInterpretableFunction(changeState),
178
214
  getLink: createBotLinkApi,
179
215
  getBotLinks,
180
216
  updateBotLinks,
@@ -185,9 +221,9 @@ export function createDefaultLibrary(context) {
185
221
  Quaternion,
186
222
  Rotation,
187
223
  superShout,
188
- priorityShout,
189
- shout: shoutProxy,
190
- whisper,
224
+ priorityShout: createInterpretableFunction(priorityShout),
225
+ shout: tagAsInterpretableFunction(interpretableShoutProxy, shoutProxy),
226
+ whisper: createInterpretableFunction(whisper),
191
227
  byTag,
192
228
  byID,
193
229
  byMod,
@@ -219,6 +255,7 @@ export function createDefaultLibrary(context) {
219
255
  expect,
220
256
  html,
221
257
  os: {
258
+ [UNCOPIABLE]: true,
222
259
  sleep,
223
260
  toast,
224
261
  tip,
@@ -566,7 +603,7 @@ export function createDefaultLibrary(context) {
566
603
  },
567
604
  },
568
605
  tagSpecificApi: {
569
- create: (options) => (...args) => { var _a; return create((_a = options.bot) === null || _a === void 0 ? void 0 : _a.id, ...args); },
606
+ create: tagAsInterpretableFunction((options) => (...args) => { var _a; return create((_a = options.bot) === null || _a === void 0 ? void 0 : _a.id, ...args); }, (options) => (...args) => { var _a; return unwind(create((_a = options.bot) === null || _a === void 0 ? void 0 : _a.id, ...args)); }),
570
607
  setTimeout: botTimer('timeout', setTimeout, true),
571
608
  setInterval: botTimer('interval', setInterval, false),
572
609
  watchPortal: watchPortalBots(),
@@ -578,19 +615,26 @@ export function createDefaultLibrary(context) {
578
615
  if (!options.bot) {
579
616
  throw new Error(`Timers are not supported when there is no current bot.`);
580
617
  }
618
+ if (typeof handler !== 'function') {
619
+ throw new Error('A handler function must be provided.');
620
+ }
581
621
  let timer;
582
622
  if (clearAfterHandlerIsRun) {
583
623
  timer = func(function () {
624
+ let result;
584
625
  try {
585
- handler(...arguments);
626
+ result = handler(...arguments);
586
627
  }
587
628
  finally {
588
629
  context.removeBotTimer(options.bot.id, type, timer);
589
630
  }
631
+ context.processBotTimerResult(result);
590
632
  }, timeout, ...args);
591
633
  }
592
634
  else {
593
- timer = func(handler, timeout, ...args);
635
+ timer = func(function () {
636
+ context.processBotTimerResult(handler(...arguments));
637
+ }, timeout, ...args);
594
638
  }
595
639
  context.recordBotTimer(options.bot.id, {
596
640
  timerId: timer,
@@ -609,12 +653,21 @@ export function createDefaultLibrary(context) {
609
653
  let timerId = 0;
610
654
  return (options) => function (portalId, handler) {
611
655
  let id = timerId++;
656
+ const finalHandler = () => {
657
+ try {
658
+ let result = handler();
659
+ return wrapGenerator(result);
660
+ }
661
+ catch (err) {
662
+ context.enqueueError(err);
663
+ }
664
+ };
612
665
  context.recordBotTimer(options.bot.id, {
613
666
  type: 'watch_portal',
614
667
  timerId: id,
615
668
  portalId,
616
669
  tag: options.tag,
617
- handler,
670
+ handler: finalHandler,
618
671
  });
619
672
  return id;
620
673
  };
@@ -628,7 +681,8 @@ export function createDefaultLibrary(context) {
628
681
  : [getID(bot)];
629
682
  const finalHandler = () => {
630
683
  try {
631
- return handler();
684
+ let result = handler();
685
+ return wrapGenerator(result);
632
686
  }
633
687
  catch (err) {
634
688
  context.enqueueError(err);
@@ -646,6 +700,76 @@ export function createDefaultLibrary(context) {
646
700
  return id;
647
701
  };
648
702
  }
703
+ function wrapGenerator(result) {
704
+ if (isGenerator(result)) {
705
+ const gen = result;
706
+ let valid = true;
707
+ const generatorWrapper = {
708
+ [Symbol.iterator]: () => generatorWrapper,
709
+ next(value) {
710
+ if (!valid) {
711
+ return {
712
+ done: true,
713
+ value: undefined,
714
+ };
715
+ }
716
+ try {
717
+ return gen.next(value);
718
+ }
719
+ catch (err) {
720
+ valid = false;
721
+ context.enqueueError(err);
722
+ return {
723
+ done: true,
724
+ value: undefined,
725
+ };
726
+ }
727
+ },
728
+ return(value) {
729
+ if (!valid) {
730
+ return {
731
+ done: true,
732
+ value: undefined,
733
+ };
734
+ }
735
+ try {
736
+ return gen.return(value);
737
+ }
738
+ catch (err) {
739
+ valid = false;
740
+ context.enqueueError(err);
741
+ return {
742
+ done: true,
743
+ value: undefined,
744
+ };
745
+ }
746
+ },
747
+ throw(e) {
748
+ if (!valid) {
749
+ return {
750
+ done: true,
751
+ value: undefined,
752
+ };
753
+ }
754
+ try {
755
+ return gen.throw(e);
756
+ }
757
+ catch (err) {
758
+ valid = false;
759
+ context.enqueueError(err);
760
+ return {
761
+ done: true,
762
+ value: undefined,
763
+ };
764
+ }
765
+ },
766
+ };
767
+ return generatorWrapper;
768
+ }
769
+ else {
770
+ return result;
771
+ }
772
+ }
649
773
  function clearWatchBot(id) {
650
774
  context.cancelAndRemoveTimers(id, 'watch_bot');
651
775
  }
@@ -5101,15 +5225,15 @@ export function createDefaultLibrary(context) {
5101
5225
  function create(botId, ...mods) {
5102
5226
  return createBase(botId, () => context.uuid(), ...mods);
5103
5227
  }
5104
- function createBase(botId, idFactory, ...datas) {
5228
+ function* createBase(botId, idFactory, ...datas) {
5105
5229
  let parentDiff = botId ? { creator: botId } : {};
5106
- return createFromMods(idFactory, parentDiff, ...datas);
5230
+ return yield* createFromMods(idFactory, parentDiff, ...datas);
5107
5231
  }
5108
5232
  /**
5109
5233
  * Creates a new bot that contains the given tags.
5110
5234
  * @param mods The mods that specify what tags to set on the bot.
5111
5235
  */
5112
- function createFromMods(idFactory, ...mods) {
5236
+ function* createFromMods(idFactory, ...mods) {
5113
5237
  let variants = new Array(1);
5114
5238
  variants[0] = [];
5115
5239
  for (let i = 0; i < mods.length; i++) {
@@ -5180,9 +5304,9 @@ export function createDefaultLibrary(context) {
5180
5304
  for (let i = 0; i < bots.length; i++) {
5181
5305
  ret[i] = context.createBot(bots[i]);
5182
5306
  }
5183
- event(CREATE_ACTION_NAME, ret);
5307
+ yield* event(CREATE_ACTION_NAME, ret);
5184
5308
  for (let bot of ret) {
5185
- event(CREATE_ANY_ACTION_NAME, null, {
5309
+ yield* event(CREATE_ANY_ACTION_NAME, null, {
5186
5310
  bot: bot,
5187
5311
  });
5188
5312
  }
@@ -5197,19 +5321,21 @@ export function createDefaultLibrary(context) {
5197
5321
  * Destroys the given bot, bot ID, or list of bots.
5198
5322
  * @param bot The bot, bot ID, or list of bots to destroy.
5199
5323
  */
5200
- function destroy(bot) {
5324
+ function* destroy(bot) {
5201
5325
  if (typeof bot === 'object' && Array.isArray(bot)) {
5202
- bot.forEach((f) => destroyBot(f));
5326
+ for (let b of bot) {
5327
+ yield* destroyBot(b);
5328
+ }
5203
5329
  }
5204
5330
  else {
5205
- destroyBot(bot);
5331
+ yield* destroyBot(bot);
5206
5332
  }
5207
5333
  }
5208
5334
  /**
5209
5335
  * Removes the given bot or bot ID from the simulation.
5210
5336
  * @param bot The bot or bot ID to remove from the simulation.
5211
5337
  */
5212
- function destroyBot(bot) {
5338
+ function* destroyBot(bot) {
5213
5339
  let realBot;
5214
5340
  let id;
5215
5341
  if (!hasValue(bot)) {
@@ -5247,15 +5373,15 @@ export function createDefaultLibrary(context) {
5247
5373
  return;
5248
5374
  }
5249
5375
  if (id) {
5250
- event(DESTROY_ACTION_NAME, [id]);
5376
+ yield* event(DESTROY_ACTION_NAME, [id]);
5251
5377
  context.destroyBot(realBot);
5252
5378
  }
5253
- destroyChildren(id);
5379
+ yield* destroyChildren(id);
5254
5380
  }
5255
- function destroyChildren(id) {
5381
+ function* destroyChildren(id) {
5256
5382
  const children = getBots(byTag('creator', createBotLink([id])));
5257
5383
  for (let child of children) {
5258
- destroyBot(child);
5384
+ yield* destroyBot(child);
5259
5385
  }
5260
5386
  }
5261
5387
  /**
@@ -5264,7 +5390,7 @@ export function createDefaultLibrary(context) {
5264
5390
  * @param stateName The state that the bot should move to.
5265
5391
  * @param groupName The group of states that the bot's state should change in. (Defaults to "state")
5266
5392
  */
5267
- function changeState(bot, stateName, groupName = 'state') {
5393
+ function* changeState(bot, stateName, groupName = 'state') {
5268
5394
  const previousState = getTag(bot, groupName);
5269
5395
  if (previousState === stateName) {
5270
5396
  return;
@@ -5275,9 +5401,9 @@ export function createDefaultLibrary(context) {
5275
5401
  from: previousState,
5276
5402
  };
5277
5403
  if (hasValue(previousState)) {
5278
- whisper(bot, `${groupName}${previousState}OnExit`, arg);
5404
+ yield* whisper(bot, `${groupName}${previousState}OnExit`, arg);
5279
5405
  }
5280
- whisper(bot, `${groupName}${stateName}OnEnter`, arg);
5406
+ yield* whisper(bot, `${groupName}${stateName}OnEnter`, arg);
5281
5407
  }
5282
5408
  /**
5283
5409
  * Creates a tag value that can be used to link to the given bots.
@@ -5403,9 +5529,9 @@ export function createDefaultLibrary(context) {
5403
5529
  * @param eventNames The names of the events to shout.
5404
5530
  * @param arg The argument to shout.
5405
5531
  */
5406
- function priorityShout(eventNames, arg) {
5532
+ function* priorityShout(eventNames, arg) {
5407
5533
  for (let name of eventNames) {
5408
- let results = event(name, null, arg, undefined, true);
5534
+ let results = yield* event(name, null, arg, undefined, true);
5409
5535
  if (results.hasResult) {
5410
5536
  return results[results.length - 1];
5411
5537
  }
@@ -5432,11 +5558,11 @@ export function createDefaultLibrary(context) {
5432
5558
  * // Tell every bot say "Hi" to you.
5433
5559
  * shout("sayHi()", "My Name");
5434
5560
  */
5435
- function shout(name, arg) {
5561
+ function* shout(name, arg) {
5436
5562
  if (!hasValue(name) || typeof name !== 'string') {
5437
5563
  throw new Error('shout() name must be a string.');
5438
5564
  }
5439
- return event(name, null, arg);
5565
+ return yield* event(name, null, arg);
5440
5566
  }
5441
5567
  /**
5442
5568
  * Asks the given bots to run the given action.
@@ -5459,7 +5585,7 @@ export function createDefaultLibrary(context) {
5459
5585
  * // Tell every friendly bot to say "Hi" to you.
5460
5586
  * whisper(getBots("friendly", true), "sayHi()", "My Name");
5461
5587
  */
5462
- function whisper(bot, eventName, arg) {
5588
+ function* whisper(bot, eventName, arg) {
5463
5589
  if (!hasValue(eventName) || typeof eventName !== 'string') {
5464
5590
  throw new Error('whisper() eventName must be a string.');
5465
5591
  }
@@ -5473,7 +5599,7 @@ export function createDefaultLibrary(context) {
5473
5599
  else {
5474
5600
  return [];
5475
5601
  }
5476
- return event(eventName, bots, arg);
5602
+ return yield* event(eventName, bots, arg);
5477
5603
  }
5478
5604
  /**
5479
5605
  * Gets whether the player is in the sheet dimension.
@@ -5683,7 +5809,7 @@ export function createDefaultLibrary(context) {
5683
5809
  * @param sort Whether to sort the Bots before processing. Defaults to true.
5684
5810
  * @param shortCircuit Whether to stop processing bots when one returns a value.
5685
5811
  */
5686
- function event(name, bots, arg, sendListenEvents = true, shortCircuit = false) {
5812
+ function* event(name, bots, arg, sendListenEvents = true, shortCircuit = false) {
5687
5813
  const startTime = globalThis.performance.now();
5688
5814
  let tag = trimEvent(name);
5689
5815
  let ids = !!bots
@@ -5723,7 +5849,16 @@ export function createDefaultLibrary(context) {
5723
5849
  __energyCheck();
5724
5850
  }
5725
5851
  try {
5726
- const result = listener(arg);
5852
+ let result;
5853
+ if (INTERPRETABLE_FUNCTION in listener) {
5854
+ result = yield* listener[INTERPRETABLE_FUNCTION](arg);
5855
+ }
5856
+ else {
5857
+ result = listener(arg);
5858
+ }
5859
+ if (isGenerator(result)) {
5860
+ result = yield* result;
5861
+ }
5727
5862
  if (result instanceof Promise) {
5728
5863
  result.catch((ex) => {
5729
5864
  context.enqueueError(ex);
@@ -5752,8 +5887,8 @@ export function createDefaultLibrary(context) {
5752
5887
  targets,
5753
5888
  listeners,
5754
5889
  };
5755
- event('onListen', listeners, listenArg, false);
5756
- event('onAnyListen', null, listenArg, false);
5890
+ yield* event('onListen', listeners, listenArg, false);
5891
+ yield* event('onAnyListen', null, listenArg, false);
5757
5892
  }
5758
5893
  if (shortCircuit && stop) {
5759
5894
  results.hasResult = true;