@player-ui/player 0.3.1-next.0 → 0.4.0-next.0

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.
package/dist/index.cjs.js CHANGED
@@ -847,6 +847,15 @@ function throwError(message, index) {
847
847
  err.description = message;
848
848
  throw err;
849
849
  }
850
+ function createSpanningLocation(start, end) {
851
+ if (!start || !end) {
852
+ return;
853
+ }
854
+ return {
855
+ start: start.start,
856
+ end: end.end
857
+ };
858
+ }
850
859
  function getMaxKeyLen(obj) {
851
860
  let maxLen = 0;
852
861
  Object.keys(obj).forEach((key) => {
@@ -868,7 +877,7 @@ const thisStr = "this";
868
877
  function binaryPrecedence(opVal) {
869
878
  return binaryOps[opVal] || 0;
870
879
  }
871
- function createBinaryExpression(operator, left, right) {
880
+ function createBinaryExpression(operator, left, right, location) {
872
881
  let type;
873
882
  if (operator === "||" || operator === "&&") {
874
883
  type = "LogicalExpression";
@@ -884,7 +893,8 @@ function createBinaryExpression(operator, left, right) {
884
893
  type,
885
894
  operator,
886
895
  left,
887
- right
896
+ right,
897
+ location
888
898
  };
889
899
  }
890
900
  function isDecimalDigit(ch) {
@@ -904,6 +914,16 @@ function parseExpression(expr) {
904
914
  const charCodeAtFunc = expr.charCodeAt;
905
915
  const { length } = expr;
906
916
  let index = 0;
917
+ const getLocation = (startChar) => {
918
+ return {
919
+ start: {
920
+ character: startChar
921
+ },
922
+ end: {
923
+ character: index
924
+ }
925
+ };
926
+ };
907
927
  function exprI(i) {
908
928
  return charAtFunc.call(expr, i);
909
929
  }
@@ -917,6 +937,7 @@ function parseExpression(expr) {
917
937
  let key;
918
938
  let value;
919
939
  let chCode;
940
+ const startCharIndex = index;
920
941
  ++index;
921
942
  while (index < length) {
922
943
  gobbleSpaces();
@@ -962,7 +983,8 @@ function parseExpression(expr) {
962
983
  return {
963
984
  __id: ExpNodeOpaqueIdentifier,
964
985
  type: "Object",
965
- attributes
986
+ attributes,
987
+ location: getLocation(startCharIndex)
966
988
  };
967
989
  }
968
990
  function gobbleSpaces() {
@@ -974,6 +996,7 @@ function parseExpression(expr) {
974
996
  function gobbleExpression() {
975
997
  const test = gobbleBinaryExpression();
976
998
  gobbleSpaces();
999
+ const startCharIndex = index;
977
1000
  if (index < length && exprICode(index) === QUMARK_CODE) {
978
1001
  index++;
979
1002
  const consequent = gobbleExpression();
@@ -992,7 +1015,8 @@ function parseExpression(expr) {
992
1015
  type: "ConditionalExpression",
993
1016
  test,
994
1017
  consequent,
995
- alternate
1018
+ alternate,
1019
+ location: getLocation(startCharIndex)
996
1020
  };
997
1021
  }
998
1022
  throwError("Expected :", index);
@@ -1038,7 +1062,7 @@ function parseExpression(expr) {
1038
1062
  right = stack.pop();
1039
1063
  biop = stack.pop().value;
1040
1064
  left = stack.pop();
1041
- node = createBinaryExpression(biop, left, right);
1065
+ node = createBinaryExpression(biop, left, right, createSpanningLocation(left.location, right.location));
1042
1066
  stack.push(node);
1043
1067
  }
1044
1068
  node = gobbleToken();
@@ -1051,7 +1075,7 @@ function parseExpression(expr) {
1051
1075
  i = stack.length - 1;
1052
1076
  node = stack[i];
1053
1077
  while (i > 1) {
1054
- node = createBinaryExpression(stack[i - 1].value, stack[i - 2], node);
1078
+ node = createBinaryExpression(stack[i - 1].value, stack[i - 2], node, createSpanningLocation(stack[i - 2].location, node.location));
1055
1079
  i -= 2;
1056
1080
  }
1057
1081
  return node;
@@ -1059,6 +1083,7 @@ function parseExpression(expr) {
1059
1083
  function gobbleToken() {
1060
1084
  gobbleSpaces();
1061
1085
  const ch = exprICode(index);
1086
+ const startCharIndex = index;
1062
1087
  if (isDecimalDigit(ch) || ch === PERIOD_CODE) {
1063
1088
  return gobbleNumericLiteral();
1064
1089
  }
@@ -1087,7 +1112,8 @@ function parseExpression(expr) {
1087
1112
  type: "UnaryExpression",
1088
1113
  operator: toCheck,
1089
1114
  argument: gobbleToken(),
1090
- prefix: true
1115
+ prefix: true,
1116
+ location: getLocation(startCharIndex)
1091
1117
  };
1092
1118
  }
1093
1119
  toCheck = toCheck.substr(0, --tcLen);
@@ -1096,6 +1122,7 @@ function parseExpression(expr) {
1096
1122
  }
1097
1123
  function gobbleNumericLiteral() {
1098
1124
  let num = "";
1125
+ const startCharIndex = index;
1099
1126
  while (isDecimalDigit(exprICode(index))) {
1100
1127
  num += exprI(index++);
1101
1128
  }
@@ -1129,13 +1156,15 @@ function parseExpression(expr) {
1129
1156
  __id: ExpNodeOpaqueIdentifier,
1130
1157
  type: "Literal",
1131
1158
  value: parseFloat(num),
1132
- raw: num
1159
+ raw: num,
1160
+ location: getLocation(startCharIndex)
1133
1161
  };
1134
1162
  }
1135
1163
  function gobbleStringLiteral() {
1136
1164
  const quote = exprI(index++);
1137
1165
  let str = "";
1138
1166
  let closed = false;
1167
+ const startCharIndex = index;
1139
1168
  while (index < length) {
1140
1169
  let ch = exprI(index++);
1141
1170
  if (ch === quote) {
@@ -1175,13 +1204,15 @@ function parseExpression(expr) {
1175
1204
  __id: ExpNodeOpaqueIdentifier,
1176
1205
  type: "Literal",
1177
1206
  value: str,
1178
- raw: `${quote}${str}${quote}`
1207
+ raw: `${quote}${str}${quote}`,
1208
+ location: getLocation(startCharIndex)
1179
1209
  };
1180
1210
  }
1181
1211
  function gobbleModelRef() {
1182
1212
  let str = "";
1183
1213
  let closed = false;
1184
1214
  let openBraceCount = 1;
1215
+ const startCharIndex = index;
1185
1216
  index += 2;
1186
1217
  while (index < length) {
1187
1218
  const ch = exprI(index++);
@@ -1207,7 +1238,8 @@ function parseExpression(expr) {
1207
1238
  return {
1208
1239
  __id: ExpNodeOpaqueIdentifier,
1209
1240
  type: "ModelRef",
1210
- ref: str
1241
+ ref: str,
1242
+ location: getLocation(startCharIndex)
1211
1243
  };
1212
1244
  }
1213
1245
  function gobbleIdentifier() {
@@ -1232,19 +1264,22 @@ function parseExpression(expr) {
1232
1264
  __id: ExpNodeOpaqueIdentifier,
1233
1265
  type: "Literal",
1234
1266
  value: literals[identifier],
1235
- raw: identifier
1267
+ raw: identifier,
1268
+ location: getLocation(start)
1236
1269
  };
1237
1270
  }
1238
1271
  if (identifier === thisStr) {
1239
1272
  return {
1240
1273
  __id: ExpNodeOpaqueIdentifier,
1241
- type: "ThisExpression"
1274
+ type: "ThisExpression",
1275
+ location: getLocation(start)
1242
1276
  };
1243
1277
  }
1244
1278
  return {
1245
1279
  __id: ExpNodeOpaqueIdentifier,
1246
1280
  type: "Identifier",
1247
- name: identifier
1281
+ name: identifier,
1282
+ location: getLocation(start)
1248
1283
  };
1249
1284
  }
1250
1285
  function gobbleArguments(termination) {
@@ -1273,6 +1308,7 @@ function parseExpression(expr) {
1273
1308
  function gobbleVariable() {
1274
1309
  let charIndex = exprICode(index);
1275
1310
  let node = charIndex === OPAREN_CODE ? gobbleGroup() : gobbleIdentifier();
1311
+ const startCharIndex = index;
1276
1312
  gobbleSpaces();
1277
1313
  charIndex = exprICode(index);
1278
1314
  while (charIndex === PERIOD_CODE || charIndex === OBRACK_CODE || charIndex === OPAREN_CODE) {
@@ -1284,7 +1320,8 @@ function parseExpression(expr) {
1284
1320
  type: "MemberExpression",
1285
1321
  computed: false,
1286
1322
  object: node,
1287
- property: gobbleIdentifier()
1323
+ property: gobbleIdentifier(),
1324
+ location: getLocation(startCharIndex)
1288
1325
  };
1289
1326
  } else if (charIndex === OBRACK_CODE) {
1290
1327
  node = {
@@ -1292,7 +1329,8 @@ function parseExpression(expr) {
1292
1329
  type: "MemberExpression",
1293
1330
  computed: true,
1294
1331
  object: node,
1295
- property: gobbleExpression()
1332
+ property: gobbleExpression(),
1333
+ location: getLocation(startCharIndex)
1296
1334
  };
1297
1335
  gobbleSpaces();
1298
1336
  charIndex = exprICode(index);
@@ -1305,7 +1343,8 @@ function parseExpression(expr) {
1305
1343
  __id: ExpNodeOpaqueIdentifier,
1306
1344
  type: "CallExpression",
1307
1345
  args: gobbleArguments(CPAREN_CODE),
1308
- callTarget: node
1346
+ callTarget: node,
1347
+ location: getLocation(startCharIndex)
1309
1348
  };
1310
1349
  }
1311
1350
  gobbleSpaces();
@@ -1324,11 +1363,13 @@ function parseExpression(expr) {
1324
1363
  throwError("Unclosed (", index);
1325
1364
  }
1326
1365
  function gobbleArray() {
1366
+ const startCharIndex = index;
1327
1367
  index++;
1328
1368
  return {
1329
1369
  __id: ExpNodeOpaqueIdentifier,
1330
1370
  type: "ArrayExpression",
1331
- elements: gobbleArguments(CBRACK_CODE)
1371
+ elements: gobbleArguments(CBRACK_CODE),
1372
+ location: getLocation(startCharIndex)
1332
1373
  };
1333
1374
  }
1334
1375
  const nodes = [];
@@ -1351,7 +1392,8 @@ function parseExpression(expr) {
1351
1392
  return {
1352
1393
  __id: ExpNodeOpaqueIdentifier,
1353
1394
  type: "Compound",
1354
- body: nodes
1395
+ body: nodes,
1396
+ location: getLocation(0)
1355
1397
  };
1356
1398
  }
1357
1399
 
@@ -1629,6 +1671,76 @@ class ExpressionEvaluator {
1629
1671
  function withoutContext(fn) {
1630
1672
  return (_context, ...args) => fn(...args);
1631
1673
  }
1674
+ function isInRange(position, location) {
1675
+ return position.character >= location.start.character && position.character <= location.end.character;
1676
+ }
1677
+ function findClosestNodeAtPosition(node, position) {
1678
+ var _a, _b, _c, _d, _e;
1679
+ switch (node.type) {
1680
+ case "Modification":
1681
+ case "Assignment":
1682
+ case "LogicalExpression":
1683
+ case "BinaryExpression": {
1684
+ const check = (_a = findClosestNodeAtPosition(node.left, position)) != null ? _a : findClosestNodeAtPosition(node.right, position);
1685
+ if (check) {
1686
+ return check;
1687
+ }
1688
+ break;
1689
+ }
1690
+ case "UnaryExpression": {
1691
+ const checkArg = findClosestNodeAtPosition(node.argument, position);
1692
+ if (checkArg) {
1693
+ return checkArg;
1694
+ }
1695
+ break;
1696
+ }
1697
+ case "MemberExpression": {
1698
+ const checkObject = (_b = findClosestNodeAtPosition(node.object, position)) != null ? _b : findClosestNodeAtPosition(node.property, position);
1699
+ if (checkObject) {
1700
+ return checkObject;
1701
+ }
1702
+ break;
1703
+ }
1704
+ case "ConditionalExpression": {
1705
+ const checkObject = (_d = (_c = findClosestNodeAtPosition(node.test, position)) != null ? _c : findClosestNodeAtPosition(node.consequent, position)) != null ? _d : findClosestNodeAtPosition(node.alternate, position);
1706
+ if (checkObject) {
1707
+ return checkObject;
1708
+ }
1709
+ break;
1710
+ }
1711
+ case "ArrayExpression":
1712
+ case "Compound": {
1713
+ const elements = node.type === "ArrayExpression" ? node.elements : node.body;
1714
+ const anyElements = elements.find((e) => findClosestNodeAtPosition(e, position));
1715
+ if (anyElements) {
1716
+ return anyElements;
1717
+ }
1718
+ break;
1719
+ }
1720
+ case "Object": {
1721
+ const checkObject = node.attributes.reduce((found, next) => {
1722
+ var _a2;
1723
+ return (_a2 = found != null ? found : findClosestNodeAtPosition(next.key, position)) != null ? _a2 : findClosestNodeAtPosition(next.value, position);
1724
+ }, void 0);
1725
+ if (checkObject) {
1726
+ return checkObject;
1727
+ }
1728
+ break;
1729
+ }
1730
+ case "CallExpression": {
1731
+ const anyArgs = (_e = node.args.find((arg) => {
1732
+ return findClosestNodeAtPosition(arg, position);
1733
+ })) != null ? _e : findClosestNodeAtPosition(node.callTarget, position);
1734
+ if (anyArgs) {
1735
+ return anyArgs;
1736
+ }
1737
+ break;
1738
+ }
1739
+ }
1740
+ if (node.location && isInRange(position, node.location)) {
1741
+ return node;
1742
+ }
1743
+ }
1632
1744
 
1633
1745
  const severities = ["trace", "debug", "info", "warn", "error"];
1634
1746
 
@@ -1965,6 +2077,8 @@ function traverseObject(val, options) {
1965
2077
  return resolveDataRefsInString(val, options);
1966
2078
  }
1967
2079
  case "object": {
2080
+ if (!val)
2081
+ return val;
1968
2082
  const keys = Object.keys(val);
1969
2083
  let newVal = val;
1970
2084
  if (keys.length > 0) {
@@ -2020,14 +2134,22 @@ class ValidationMiddleware {
2020
2134
  if (validations === void 0) {
2021
2135
  nextTransaction.push([binding, value]);
2022
2136
  } else if (validations instanceof Set) {
2023
- invalidBindings.push(...validations);
2137
+ validations.forEach((validation) => {
2138
+ invalidBindings.push(validation.binding);
2139
+ if (!validation.isStrong) {
2140
+ nextTransaction.push([validation.binding, value]);
2141
+ }
2142
+ });
2024
2143
  } else {
2025
2144
  (_a = this.logger) == null ? void 0 : _a.debug(`Invalid value for path: ${binding.asString()} - ${validations.severity} - ${validations.message}`);
2026
2145
  }
2027
2146
  });
2028
2147
  if (next && nextTransaction.length > 0) {
2029
2148
  nextTransaction.forEach(([binding]) => this.shadowModelPaths.delete(binding));
2030
- return next.set(nextTransaction, options);
2149
+ const result = next.set(nextTransaction, options);
2150
+ if (invalidBindings.length === 0) {
2151
+ return result;
2152
+ }
2031
2153
  }
2032
2154
  return invalidBindings.map((binding) => {
2033
2155
  return {
@@ -2693,14 +2815,27 @@ const findBasePath = (node) => {
2693
2815
  return findBasePath(parentNode);
2694
2816
  };
2695
2817
  class StringResolverPlugin {
2818
+ constructor() {
2819
+ this.propertiesToSkipCache = new Map();
2820
+ }
2696
2821
  applyResolver(resolver) {
2697
2822
  resolver.hooks.resolve.tap("string-resolver", (value, node, options) => {
2698
- var _a, _b, _c, _d;
2823
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
2699
2824
  if (node.type === exports.NodeType.Empty || node.type === exports.NodeType.Unknown) {
2700
2825
  return null;
2701
2826
  }
2702
2827
  if (node.type === exports.NodeType.Value || node.type === exports.NodeType.Asset || node.type === exports.NodeType.View) {
2703
- const propsToSkip = new Set(((_b = (_a = node.plugins) == null ? void 0 : _a.stringResolver) == null ? void 0 : _b.propertiesToSkip) ? (_d = (_c = node.plugins) == null ? void 0 : _c.stringResolver) == null ? void 0 : _d.propertiesToSkip : []);
2828
+ let propsToSkip;
2829
+ if (node.type === exports.NodeType.Asset || node.type === exports.NodeType.View) {
2830
+ propsToSkip = new Set((_c = (_b = (_a = node.plugins) == null ? void 0 : _a.stringResolver) == null ? void 0 : _b.propertiesToSkip) != null ? _c : ["exp"]);
2831
+ if ((_d = node.value) == null ? void 0 : _d.id) {
2832
+ this.propertiesToSkipCache.set(node.value.id, propsToSkip);
2833
+ }
2834
+ } else if (((_e = node.parent) == null ? void 0 : _e.type) === exports.NodeType.MultiNode && (((_g = (_f = node.parent) == null ? void 0 : _f.parent) == null ? void 0 : _g.type) === exports.NodeType.Asset || ((_i = (_h = node.parent) == null ? void 0 : _h.parent) == null ? void 0 : _i.type) === exports.NodeType.View) && ((_j = node.parent.parent.value) == null ? void 0 : _j.id) && this.propertiesToSkipCache.has(node.parent.parent.value.id)) {
2835
+ propsToSkip = this.propertiesToSkipCache.get(node.parent.parent.value.id);
2836
+ } else {
2837
+ propsToSkip = new Set(["exp"]);
2838
+ }
2704
2839
  const nodePath = findBasePath(node);
2705
2840
  if (nodePath.length > 0 && nodePath.some((segment) => propsToSkip.has(segment.toString()))) {
2706
2841
  return node.value;
@@ -3526,19 +3661,30 @@ class ValidationController {
3526
3661
  getDataMiddleware() {
3527
3662
  return [
3528
3663
  new ValidationMiddleware((binding) => {
3664
+ var _a;
3529
3665
  if (!this.options) {
3530
3666
  return;
3531
3667
  }
3532
3668
  this.updateValidationsForBinding(binding, "change", this.options);
3533
3669
  const strongValidation = this.getValidationForBinding(binding);
3534
- if (strongValidation == null ? void 0 : strongValidation.get())
3670
+ if (((_a = strongValidation == null ? void 0 : strongValidation.get()) == null ? void 0 : _a.severity) === "error") {
3535
3671
  return strongValidation.get();
3672
+ }
3536
3673
  const newInvalidBindings = new Set();
3537
- for (const [, weakValidation] of Array.from(this.validations)) {
3538
- if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && (weakValidation == null ? void 0 : weakValidation.get())) {
3539
- weakValidation == null ? void 0 : weakValidation.weakBindings.forEach(newInvalidBindings.add, newInvalidBindings);
3674
+ this.validations.forEach((weakValidation, strongBinding) => {
3675
+ var _a2;
3676
+ if (caresAboutDataChanges(new Set([binding]), weakValidation.weakBindings) && ((_a2 = weakValidation == null ? void 0 : weakValidation.get()) == null ? void 0 : _a2.severity) === "error") {
3677
+ weakValidation == null ? void 0 : weakValidation.weakBindings.forEach((weakBinding) => {
3678
+ weakBinding === strongBinding ? newInvalidBindings.add({
3679
+ binding: weakBinding,
3680
+ isStrong: true
3681
+ }) : newInvalidBindings.add({
3682
+ binding: weakBinding,
3683
+ isStrong: false
3684
+ });
3685
+ });
3540
3686
  }
3541
- }
3687
+ });
3542
3688
  if (newInvalidBindings.size > 0) {
3543
3689
  return newInvalidBindings;
3544
3690
  }
@@ -3564,7 +3710,9 @@ class ValidationController {
3564
3710
  ignoreDefaultValue: true
3565
3711
  });
3566
3712
  if (originalValue !== withoutDefault) {
3567
- this.options.model.set([[binding, originalValue]]);
3713
+ this.options.model.set([[binding, originalValue]], {
3714
+ silent: true
3715
+ });
3568
3716
  }
3569
3717
  this.updateValidationsForBinding(binding, "load", this.options, () => {
3570
3718
  view.update(new Set([binding]));
@@ -3604,7 +3752,7 @@ class ValidationController {
3604
3752
  this.validations.forEach((validation, vBinding) => {
3605
3753
  if (vBinding !== binding && caresAboutDataChanges(new Set([binding]), validation.weakBindings)) {
3606
3754
  validation.update(trigger, true, (validationObj) => {
3607
- const response = this.validationRunner(validationObj, context, binding);
3755
+ const response = this.validationRunner(validationObj, context, vBinding);
3608
3756
  return response ? { message: response.message } : void 0;
3609
3757
  });
3610
3758
  }
@@ -3691,16 +3839,16 @@ class ValidationController {
3691
3839
  return (_b = (_a = this.tracker) == null ? void 0 : _a.getBindings()) != null ? _b : new Set();
3692
3840
  }
3693
3841
  validateView(trigger = "navigation") {
3694
- var _a, _b;
3695
3842
  this.updateValidationsForView(trigger);
3696
3843
  const validations = new Map();
3697
- for (const b of this.getBindings()) {
3844
+ this.getBindings().forEach((b) => {
3845
+ var _a, _b;
3698
3846
  const invalid = (_a = this.getValidationForBinding(b)) == null ? void 0 : _a.get();
3699
3847
  if (invalid) {
3700
3848
  (_b = this.options) == null ? void 0 : _b.logger.debug(`Validation on binding: ${b.asString()} is preventing navigation. ${JSON.stringify(invalid)}`);
3701
3849
  validations.set(b, invalid);
3702
3850
  }
3703
- }
3851
+ });
3704
3852
  return {
3705
3853
  canTransition: validations.size === 0,
3706
3854
  validations: validations.size ? validations : void 0
@@ -4070,8 +4218,9 @@ class DataController {
4070
4218
  }
4071
4219
  });
4072
4220
  this.hooks.onSet.call(normalizedTransaction);
4221
+ this.hooks.onSet.call(normalizedTransaction);
4073
4222
  if (setUpdates.length > 0) {
4074
- this.hooks.onUpdate.call(setUpdates);
4223
+ this.hooks.onUpdate.call(setUpdates, options);
4075
4224
  }
4076
4225
  return result;
4077
4226
  }
@@ -4272,8 +4421,8 @@ var __async = (__this, __arguments, generator) => {
4272
4421
  step((generator = generator.apply(__this, __arguments)).next());
4273
4422
  });
4274
4423
  };
4275
- const PLAYER_VERSION = "0.3.1-next.0";
4276
- const COMMIT = "b51603be07572111ca68e73d1b710ed2d0aa9412";
4424
+ const PLAYER_VERSION = "0.4.0-next.0";
4425
+ const COMMIT = "6f7a8b3424cb819dfcbe830586a92711adf130ba";
4277
4426
  const _Player = class {
4278
4427
  constructor(config) {
4279
4428
  this.logger = new TapableLogger();
@@ -4400,17 +4549,18 @@ const _Player = class {
4400
4549
  }
4401
4550
  flowController.hooks.flow.tap("player", (flow) => {
4402
4551
  flow.hooks.beforeTransition.tap("player", (state, transitionVal) => {
4403
- if (state.onEnd && (state.transitions[transitionVal] || state.transitions["*"])) {
4552
+ const computedTransitionVal = state.transitions[transitionVal] ? transitionVal : "*";
4553
+ if (state.onEnd && state.transitions[computedTransitionVal]) {
4404
4554
  if (typeof state.onEnd === "object" && "exp" in state.onEnd) {
4405
4555
  expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(state.onEnd.exp);
4406
4556
  } else {
4407
4557
  expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(state.onEnd);
4408
4558
  }
4409
4559
  }
4410
- if (!("transitions" in state) || !state.transitions[transitionVal]) {
4560
+ if (!("transitions" in state) || !state.transitions[computedTransitionVal]) {
4411
4561
  return state;
4412
4562
  }
4413
- return timm.setIn(state, ["transitions", transitionVal], resolveStrings(state.transitions[transitionVal]));
4563
+ return timm.setIn(state, ["transitions", computedTransitionVal], resolveStrings(state.transitions[computedTransitionVal]));
4414
4564
  });
4415
4565
  flow.hooks.skipTransition.tap("validation", (currentState) => {
4416
4566
  var _a;
@@ -4438,7 +4588,14 @@ const _Player = class {
4438
4588
  if (newState.value.state_type === "ACTION") {
4439
4589
  const { exp } = newState.value;
4440
4590
  queueMicrotask__default["default"](() => {
4441
- flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4591
+ try {
4592
+ flowController == null ? void 0 : flowController.transition(String(expressionEvaluator == null ? void 0 : expressionEvaluator.evaluate(exp)));
4593
+ } catch (error) {
4594
+ const state = this.getState();
4595
+ if (error instanceof Error && state.status === "in-progress") {
4596
+ state.fail(error);
4597
+ }
4598
+ }
4442
4599
  });
4443
4600
  }
4444
4601
  expressionEvaluator.reset();
@@ -4604,6 +4761,7 @@ exports.ViewController = ViewController;
4604
4761
  exports.ViewInstance = ViewInstance;
4605
4762
  exports.caresAboutDataChanges = caresAboutDataChanges;
4606
4763
  exports.constructModelForPipeline = constructModelForPipeline;
4764
+ exports.findClosestNodeAtPosition = findClosestNodeAtPosition;
4607
4765
  exports.findInArray = findInArray;
4608
4766
  exports.findNextExp = findNextExp;
4609
4767
  exports.getBindingSegments = getBindingSegments;
package/dist/index.d.ts CHANGED
@@ -165,6 +165,10 @@ interface DataModelOptions {
165
165
  * A flag to set to ignore any default value in the schema, and just use the raw value
166
166
  */
167
167
  ignoreDefaultValue?: boolean;
168
+ /**
169
+ * A flag to indicate that this update should happen silently
170
+ */
171
+ silent?: boolean;
168
172
  /** Other context associated with this request */
169
173
  context?: {
170
174
  /** The data model to use when getting other data from the context of this request */
@@ -370,11 +374,23 @@ declare type ExpressionHandler<T extends readonly unknown[] = unknown[], R = voi
370
374
  declare const ExpNodeOpaqueIdentifier: unique symbol;
371
375
  /** Checks if the input is an already processed Expression node */
372
376
  declare function isExpressionNode(x: any): x is ExpressionNode;
377
+ interface NodePosition {
378
+ /** The character location */
379
+ character: number;
380
+ }
381
+ interface NodeLocation {
382
+ /** The start of the node */
383
+ start: NodePosition;
384
+ /** The end of the node */
385
+ end: NodePosition;
386
+ }
373
387
  interface BaseNode<T> {
374
388
  /** The thing to discriminate the AST type on */
375
389
  type: T;
376
390
  /** How to tell this apart from other objects */
377
391
  __id: typeof ExpNodeOpaqueIdentifier;
392
+ /** The location of the node in the source expression string */
393
+ location?: NodeLocation;
378
394
  }
379
395
  /** A helper interface for nodes that container left and right children */
380
396
  interface DirectionalNode {
@@ -393,11 +409,7 @@ interface BinaryNode extends BaseNode<'BinaryExpression'>, DirectionalNode {
393
409
  /** The operation to perform on the nodes */
394
410
  operator: string;
395
411
  }
396
- interface LogicalNode extends BaseNode<'LogicalExpression'> {
397
- /** The left hand side of the equation */
398
- left: any;
399
- /** The right hand side of the equation */
400
- right: any;
412
+ interface LogicalNode extends BaseNode<'LogicalExpression'>, DirectionalNode {
401
413
  /** The logical operation to perform on the nodes */
402
414
  operator: string;
403
415
  }
@@ -405,7 +417,7 @@ interface UnaryNode extends BaseNode<'UnaryExpression'> {
405
417
  /** The operation to perform on the node */
406
418
  operator: string;
407
419
  /** The single argument that the operation should be performed on */
408
- argument: any;
420
+ argument: ExpressionNode;
409
421
  }
410
422
  declare type ThisNode = BaseNode<'ThisExpression'>;
411
423
  interface ModelRefNode extends BaseNode<'ModelRef'> {
@@ -416,9 +428,9 @@ interface ObjectNode extends BaseNode<'Object'> {
416
428
  /** */
417
429
  attributes: Array<{
418
430
  /** The property name of the object */
419
- key: any;
431
+ key: ExpressionNode;
420
432
  /** the associated value */
421
- value: any;
433
+ value: ExpressionNode;
422
434
  }>;
423
435
  }
424
436
  interface MemberExpressionNode extends BaseNode<'MemberExpression'> {
@@ -443,13 +455,13 @@ interface CompoundNode extends BaseNode<'Compound'> {
443
455
  }
444
456
  interface CallExpressionNode extends BaseNode<'CallExpression'> {
445
457
  /** The arguments to the function */
446
- args: any[];
458
+ args: ExpressionNode[];
447
459
  /** The function name */
448
460
  callTarget: IdentifierNode;
449
461
  }
450
462
  interface ArrayExpressionNode extends BaseNode<'ArrayExpression'> {
451
463
  /** The items in an array */
452
- elements: any[];
464
+ elements: ExpressionNode[];
453
465
  }
454
466
  interface IdentifierNode extends BaseNode<'Identifier'> {
455
467
  /** The variable name */
@@ -505,6 +517,8 @@ declare class ExpressionEvaluator {
505
517
 
506
518
  /** Generates a function by removing the first context argument */
507
519
  declare function withoutContext<T extends unknown[], Return>(fn: (...args: T) => Return): ExpressionHandler<T, Return>;
520
+ /** Get the node in the expression that's closest to the desired position */
521
+ declare function findClosestNodeAtPosition(node: ExpressionNode, position: NodePosition): ExpressionNode | undefined;
508
522
 
509
523
  declare type FormatOptions = Omit<Formatting.Reference, 'type'>;
510
524
  /**
@@ -961,6 +975,8 @@ declare class TemplatePlugin implements ViewPlugin {
961
975
 
962
976
  /** A plugin that resolves all string references for each node */
963
977
  declare class StringResolverPlugin implements ViewPlugin {
978
+ private propertiesToSkipCache;
979
+ constructor();
964
980
  applyResolver(resolver: Resolver): void;
965
981
  apply(view: View): void;
966
982
  }
@@ -1275,7 +1291,7 @@ declare class DataController implements DataModelWithParser<DataModelOptions> {
1275
1291
  onDelete: SyncHook<[any], Record<string, any>>;
1276
1292
  onSet: SyncHook<[BatchSetTransaction], Record<string, any>>;
1277
1293
  onGet: SyncHook<[any, any], Record<string, any>>;
1278
- onUpdate: SyncHook<[Updates], Record<string, any>>;
1294
+ onUpdate: SyncHook<[Updates, DataModelOptions | undefined], Record<string, any>>;
1279
1295
  format: SyncWaterfallHook<[any, BindingInstance], Record<string, any>>;
1280
1296
  deformat: SyncWaterfallHook<[any, BindingInstance], Record<string, any>>;
1281
1297
  serialize: SyncWaterfallHook<[any], Record<string, any>>;
@@ -1434,10 +1450,19 @@ interface ValidatorContext {
1434
1450
  }
1435
1451
  declare type ValidatorFunction<Options = unknown> = (context: ValidatorContext, value: any, options?: Options) => Omit<BaseValidationResponse, 'severity'> | undefined;
1436
1452
 
1453
+ /**
1454
+ * A BindingInstance with an indicator of whether or not it's a strong binding
1455
+ */
1456
+ declare type StrongOrWeakBinding = {
1457
+ /** BindingInstance in question */
1458
+ binding: BindingInstance;
1459
+ /** Boolean indicating whether the relevant BindingInstance is a strong binding */
1460
+ isStrong: boolean;
1461
+ };
1437
1462
  /**
1438
1463
  * Returns a validation object if the data is invalid or an set of BindingsInstances if the binding itself is a weak ref of another invalid validation
1439
1464
  */
1440
- declare type MiddlewareChecker = (binding: BindingInstance, model: DataModelImpl) => ValidationResponse | Set<BindingInstance> | undefined;
1465
+ declare type MiddlewareChecker = (binding: BindingInstance, model: DataModelImpl) => ValidationResponse | Set<StrongOrWeakBinding> | undefined;
1441
1466
  /**
1442
1467
  * Middleware for the data-model that caches the results of invalid data
1443
1468
  */
@@ -1611,4 +1636,4 @@ declare class FlowExpPlugin implements PlayerPlugin {
1611
1636
  apply(player: Player): void;
1612
1637
  }
1613
1638
 
1614
- export { AnyAssetType, ApplicabilityPlugin, ArrayExpressionNode, AssetTransformCorePlugin, AssignmentNode, BaseFlowState, BaseNode, BatchSetTransaction, BeforeTransformFunction, BinaryNode, BinaryOperator, BinaryOperatorAdvanced, BinaryOperatorBasic, BindingFactory, BindingInstance, BindingLike, BindingParser, BindingParserOptions, BindingTracker, Builder, CallExpressionNode, CompletedState, CompoundNode, ConditionalExpressionNode, ConsoleLogger, ConstantsController, ConstantsProvider, ControllerState, DataController, DataModelImpl, DataModelMiddleware, DataModelOptions, DataModelWithParser, DataPipeline, DependencyMiddleware, DependencyModel, DependencySets, DependencyTracker, DirectionalNode, EMPTY_NODE, ErrorState, ErrorValidationResponse, ExpNodeOpaqueIdentifier, ExpressionContext, ExpressionEvaluator, ExpressionEvaluatorFunction, ExpressionEvaluatorOptions, ExpressionHandler, ExpressionLiteralType, ExpressionNode, ExpressionNodeType, ExpressionType, FlowController, FlowExpPlugin, FlowInstance, FormatDefinition, FormatFunction, FormatHandler, FormatOptions, FormatType, Getter, HookOptions, IdentifierNode, InProgressState, LiteralNode, LocalModel, LocalStateStore, LogFn, Logger, LoggerProvider, LogicalNode, MemberExpressionNode, MiddlewareChecker, ModelRefNode, ModificationNode, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NamedState, Node, NodeType, NoopLogger, NotStartedState, ObjectNode, OperatorProcessingOptions, Options, ParseObjectOptions, Parser, PipelinedDataModel, Player, PlayerConfigOptions, PlayerFlowExecutionData, PlayerFlowState, PlayerFlowStatus, PlayerInfo, PlayerPlugin, ProxyLogger, ROOT_BINDING, RawBinding, RawBindingSegment, RawSetTransaction, RawSetType, Resolve, Resolver, SIMPLE_BINDING_REGEX, SchemaController, Severity, StatefulValidationObject, Store, StringResolverPlugin, SwitchPlugin, TapableLogger, TemplatePlugin, ThisNode, TransformFunction, TransformFunctions, TransformRegistry, TransitionFunction, TransitionOptions, UnaryNode, UnaryOperator, Updates, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidationObject, ValidationProvider, ValidationResponse, ValidatorContext, ValidatorFunction, ValidatorRegistry, ViewController, ViewControllerOptions, ViewInstance, ViewPlugin, WarningValidationResponse, caresAboutDataChanges, constructModelForPipeline, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, maybeConvertToNum, parse, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };
1639
+ export { AnyAssetType, ApplicabilityPlugin, ArrayExpressionNode, AssetTransformCorePlugin, AssignmentNode, BaseFlowState, BaseNode, BatchSetTransaction, BeforeTransformFunction, BinaryNode, BinaryOperator, BinaryOperatorAdvanced, BinaryOperatorBasic, BindingFactory, BindingInstance, BindingLike, BindingParser, BindingParserOptions, BindingTracker, Builder, CallExpressionNode, CompletedState, CompoundNode, ConditionalExpressionNode, ConsoleLogger, ConstantsController, ConstantsProvider, ControllerState, DataController, DataModelImpl, DataModelMiddleware, DataModelOptions, DataModelWithParser, DataPipeline, DependencyMiddleware, DependencyModel, DependencySets, DependencyTracker, DirectionalNode, EMPTY_NODE, ErrorState, ErrorValidationResponse, ExpNodeOpaqueIdentifier, ExpressionContext, ExpressionEvaluator, ExpressionEvaluatorFunction, ExpressionEvaluatorOptions, ExpressionHandler, ExpressionLiteralType, ExpressionNode, ExpressionNodeType, ExpressionType, FlowController, FlowExpPlugin, FlowInstance, FormatDefinition, FormatFunction, FormatHandler, FormatOptions, FormatType, Getter, HookOptions, IdentifierNode, InProgressState, LiteralNode, LocalModel, LocalStateStore, LogFn, Logger, LoggerProvider, LogicalNode, MemberExpressionNode, MiddlewareChecker, ModelRefNode, ModificationNode, NOOPDataModel, NOOP_MODEL, NOT_STARTED_STATE, NamedState, Node, NodeLocation, NodePosition, NodeType, NoopLogger, NotStartedState, ObjectNode, OperatorProcessingOptions, Options, ParseObjectOptions, Parser, PipelinedDataModel, Player, PlayerConfigOptions, PlayerFlowExecutionData, PlayerFlowState, PlayerFlowStatus, PlayerInfo, PlayerPlugin, ProxyLogger, ROOT_BINDING, RawBinding, RawBindingSegment, RawSetTransaction, RawSetType, Resolve, Resolver, SIMPLE_BINDING_REGEX, SchemaController, Severity, StatefulValidationObject, Store, StringResolverPlugin, StrongOrWeakBinding, SwitchPlugin, TapableLogger, TemplatePlugin, ThisNode, TransformFunction, TransformFunctions, TransformRegistry, TransitionFunction, TransitionOptions, UnaryNode, UnaryOperator, Updates, ValidationBindingTrackerViewPlugin, ValidationController, ValidationMiddleware, ValidationObject, ValidationProvider, ValidationResponse, ValidatorContext, ValidatorFunction, ValidatorRegistry, ViewController, ViewControllerOptions, ViewInstance, ViewPlugin, WarningValidationResponse, caresAboutDataChanges, constructModelForPipeline, findClosestNodeAtPosition, findInArray, findNextExp, getBindingSegments, isBinding, isExpressionNode, maybeConvertToNum, parse, resolveDataRefs, resolveDataRefsInString, resolveExpressionsInString, severities, toModel, toNodeResolveOptions, withParser, withoutContext };