@odoo/o-spreadsheet 15.2.13 → 15.2.15

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.
@@ -108,14 +108,72 @@ const FORMULA_REF_IDENTIFIER = "|";
108
108
  // -----------------------------------------------------------------------------
109
109
  // Date Type
110
110
  // -----------------------------------------------------------------------------
111
+ /**
112
+ * A DateTime object that can be used to manipulate spreadsheet dates.
113
+ * Conceptually, a spreadsheet date is simply a number with a date format,
114
+ * and it is timezone-agnostic.
115
+ * This DateTime object consistently uses UTC time to represent a naive date and time.
116
+ */
117
+ class DateTime {
118
+ constructor(year, month, day, hours = 0, minutes = 0, seconds = 0) {
119
+ this.jsDate = new Date(Date.UTC(year, month, day, hours, minutes, seconds, 0));
120
+ }
121
+ static fromTimestamp(timestamp) {
122
+ const date = new Date(timestamp);
123
+ return new DateTime(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
124
+ }
125
+ static now() {
126
+ const now = new Date();
127
+ return new DateTime(now.getFullYear(), now.getMonth(), now.getDate(), now.getHours(), now.getMinutes(), now.getSeconds());
128
+ }
129
+ toString() {
130
+ return this.jsDate.toString();
131
+ }
132
+ getTime() {
133
+ return this.jsDate.getTime();
134
+ }
135
+ getFullYear() {
136
+ return this.jsDate.getUTCFullYear();
137
+ }
138
+ getMonth() {
139
+ return this.jsDate.getUTCMonth();
140
+ }
141
+ getDate() {
142
+ return this.jsDate.getUTCDate();
143
+ }
144
+ getDay() {
145
+ return this.jsDate.getUTCDay();
146
+ }
147
+ getHours() {
148
+ return this.jsDate.getUTCHours();
149
+ }
150
+ getMinutes() {
151
+ return this.jsDate.getUTCMinutes();
152
+ }
153
+ getSeconds() {
154
+ return this.jsDate.getUTCSeconds();
155
+ }
156
+ setDate(date) {
157
+ this.jsDate.setUTCDate(date);
158
+ }
159
+ setHours(hours) {
160
+ this.jsDate.setUTCHours(hours);
161
+ }
162
+ setMinutes(minutes) {
163
+ this.jsDate.setUTCMinutes(minutes);
164
+ }
165
+ setSeconds(seconds) {
166
+ this.jsDate.setUTCSeconds(seconds);
167
+ }
168
+ }
111
169
  // -----------------------------------------------------------------------------
112
170
  // Parsing
113
171
  // -----------------------------------------------------------------------------
114
172
  const CURRENT_MILLENIAL = 2000; // note: don't forget to update this in 2999
115
- const CURRENT_YEAR = new Date().getFullYear();
116
- const INITIAL_1900_DAY$1 = new Date(1899, 11, 30);
117
- const INITIAL_JS_DAY = new Date(0);
118
- const DATE_JS_1900_OFFSET = INITIAL_JS_DAY - INITIAL_1900_DAY$1;
173
+ const CURRENT_YEAR = DateTime.now().getFullYear();
174
+ const INITIAL_1900_DAY$1 = new DateTime(1899, 11, 30);
175
+ const INITIAL_JS_DAY = DateTime.fromTimestamp(0);
176
+ const DATE_JS_1900_OFFSET = INITIAL_JS_DAY.getTime() - INITIAL_1900_DAY$1.getTime();
119
177
  const mdyDateRegexp = /^\d{1,2}(\/|-|\s)\d{1,2}((\/|-|\s)\d{1,4})?$/;
120
178
  const ymdDateRegexp = /^\d{3,4}(\/|-|\s)\d{1,2}(\/|-|\s)\d{1,2}$/;
121
179
  const timeRegexp = /((\d+(:\d+)?(:\d+)?\s*(AM|PM))|(\d+:\d+(:\d+)?))$/;
@@ -155,7 +213,7 @@ function parseDateTime(str) {
155
213
  return {
156
214
  value: date.value + time.value,
157
215
  format: date.format + " " + (time.format === "hhhh:mm:ss" ? "hh:mm:ss" : time.format),
158
- jsDate: new Date(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
216
+ jsDate: new DateTime(date.jsDate.getFullYear() + time.jsDate.getFullYear() - 1899, date.jsDate.getMonth() + time.jsDate.getMonth() - 11, date.jsDate.getDate() + time.jsDate.getDate() - 30, date.jsDate.getHours() + time.jsDate.getHours(), date.jsDate.getMinutes() + time.jsDate.getMinutes(), date.jsDate.getSeconds() + time.jsDate.getSeconds()),
159
217
  };
160
218
  }
161
219
  return date || time;
@@ -172,13 +230,13 @@ function parseDate(str, dateFormat) {
172
230
  const day = Number(parts[dayIndex]);
173
231
  const leadingZero = (parts[monthIndex].length === 2 && month < 10) || (parts[dayIndex].length === 2 && day < 10);
174
232
  const year = parts[yearIndex] ? inferYear(parts[yearIndex]) : CURRENT_YEAR;
175
- const jsDate = new Date(year, month - 1, day);
233
+ const jsDate = new DateTime(year, month - 1, day);
176
234
  const sep = str.match(/\/|-|\s/)[0];
177
235
  if (jsDate.getMonth() !== month - 1 || jsDate.getDate() !== day) {
178
236
  // invalid date
179
237
  return null;
180
238
  }
181
- const delta = jsDate - INITIAL_1900_DAY$1;
239
+ const delta = jsDate.getTime() - INITIAL_1900_DAY$1.getTime();
182
240
  let format = leadingZero ? `mm${sep}dd` : `m${sep}d`;
183
241
  if (parts[yearIndex]) {
184
242
  format = isMDY ? format + sep + "yyyy" : "yyyy" + sep + format;
@@ -238,7 +296,7 @@ function parseTime(str) {
238
296
  if (hours >= 24) {
239
297
  format = "hhhh:mm:ss";
240
298
  }
241
- const jsDate = new Date(1899, 11, 30, hours, minutes, seconds);
299
+ const jsDate = new DateTime(1899, 11, 30, hours, minutes, seconds);
242
300
  return {
243
301
  value: hours / 24 + minutes / 1440 + seconds / 86400,
244
302
  format: format,
@@ -252,7 +310,7 @@ function parseTime(str) {
252
310
  // -----------------------------------------------------------------------------
253
311
  function numberToJsDate(value) {
254
312
  const truncValue = Math.trunc(value);
255
- let date = new Date(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
313
+ let date = DateTime.fromTimestamp(truncValue * 86400 * 1000 - DATE_JS_1900_OFFSET);
256
314
  let time = value - truncValue;
257
315
  time = time < 0 ? 1 + time : time;
258
316
  const hours = Math.round(time * 24);
@@ -325,7 +383,7 @@ function formatJSTime(jsDate, format) {
325
383
  .map((p) => {
326
384
  switch (p) {
327
385
  case "hhhh":
328
- const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1) / (60 * 60 * 1000));
386
+ const helapsedHours = Math.floor((jsDate.getTime() - INITIAL_1900_DAY$1.getTime()) / (60 * 60 * 1000));
329
387
  return helapsedHours.toString();
330
388
  case "hh":
331
389
  return hours.toString().padStart(2, "0");
@@ -2844,7 +2902,7 @@ function isBoolean(str) {
2844
2902
  function isDateTime(str) {
2845
2903
  return parseDateTime(str) !== null;
2846
2904
  }
2847
- const MARKDOWN_LINK_REGEX = /^\[([^\[]+)\]\((.+)\)$/;
2905
+ const MARKDOWN_LINK_REGEX = /^\[(.+)\]\((.+)\)$/;
2848
2906
  //link must start with http or https
2849
2907
  //https://stackoverflow.com/a/3809435/4760614
2850
2908
  const WEB_LINK_REGEX = /^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,4}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)$/;
@@ -4720,7 +4778,7 @@ var database = /*#__PURE__*/Object.freeze({
4720
4778
  DVARP: DVARP
4721
4779
  });
4722
4780
 
4723
- const INITIAL_1900_DAY = new Date(1899, 11, 30);
4781
+ const INITIAL_1900_DAY = new DateTime(1899, 11, 30);
4724
4782
  const DEFAULT_TYPE = 1;
4725
4783
  const DEFAULT_WEEKEND = 1;
4726
4784
  function isLeapYear(year) {
@@ -4749,7 +4807,7 @@ const DATE = {
4749
4807
  if (_year < 1900) {
4750
4808
  _year += 1900;
4751
4809
  }
4752
- const jsDate = new Date(_year, _month - 1, _day);
4810
+ const jsDate = new DateTime(_year, _month - 1, _day);
4753
4811
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4754
4812
  assert(() => delta >= 0, _lt(`The function [[FUNCTION_NAME]] result must be greater than or equal 01/01/1900.`));
4755
4813
  return Math.round(delta / 86400000);
@@ -4822,7 +4880,7 @@ const EDATE = {
4822
4880
  const yStart = _startDate.getFullYear();
4823
4881
  const mStart = _startDate.getMonth();
4824
4882
  const dStart = _startDate.getDate();
4825
- const jsDate = new Date(yStart, mStart + _months, dStart);
4883
+ const jsDate = new DateTime(yStart, mStart + _months, dStart);
4826
4884
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4827
4885
  return Math.round(delta / 86400000);
4828
4886
  },
@@ -4844,7 +4902,7 @@ const EOMONTH = {
4844
4902
  const _months = Math.trunc(toNumber(months));
4845
4903
  const yStart = _startDate.getFullYear();
4846
4904
  const mStart = _startDate.getMonth();
4847
- const jsDate = new Date(yStart, mStart + _months + 1, 0);
4905
+ const jsDate = new DateTime(yStart, mStart + _months + 1, 0);
4848
4906
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
4849
4907
  return Math.round(delta / 86400000);
4850
4908
  },
@@ -4884,17 +4942,17 @@ const ISOWEEKNUM = {
4884
4942
  // The first week of the year is the week that contains the first
4885
4943
  // Thursday of the year.
4886
4944
  let firstThursday = 1;
4887
- while (new Date(y, 0, firstThursday).getDay() !== 4) {
4945
+ while (new DateTime(y, 0, firstThursday).getDay() !== 4) {
4888
4946
  firstThursday += 1;
4889
4947
  }
4890
- const firstDayOfFirstWeek = new Date(y, 0, firstThursday - 3);
4948
+ const firstDayOfFirstWeek = new DateTime(y, 0, firstThursday - 3);
4891
4949
  // The last week of the year is the week that contains the last Thursday of
4892
4950
  // the year.
4893
4951
  let lastThursday = 31;
4894
- while (new Date(y, 11, lastThursday).getDay() !== 4) {
4952
+ while (new DateTime(y, 11, lastThursday).getDay() !== 4) {
4895
4953
  lastThursday -= 1;
4896
4954
  }
4897
- const lastDayOfLastWeek = new Date(y, 11, lastThursday + 3);
4955
+ const lastDayOfLastWeek = new DateTime(y, 11, lastThursday + 3);
4898
4956
  // B - If our date > lastDayOfLastWeek then it's in the weeks of the year after
4899
4957
  // If our date < firstDayOfFirstWeek then it's in the weeks of the year before
4900
4958
  let offsetYear;
@@ -4920,17 +4978,17 @@ const ISOWEEKNUM = {
4920
4978
  case 1:
4921
4979
  // firstDay is the 1st day of the 1st week of the year after
4922
4980
  // firstDay = lastDayOfLastWeek + 1 Day
4923
- firstDay = new Date(y, 11, lastThursday + 3 + 1);
4981
+ firstDay = new DateTime(y, 11, lastThursday + 3 + 1);
4924
4982
  break;
4925
4983
  case -1:
4926
4984
  // firstDay is the 1st day of the 1st week of the previous year.
4927
4985
  // The first week of the previous year is the week that contains the
4928
4986
  // first Thursday of the previous year.
4929
4987
  let firstThursdayPreviousYear = 1;
4930
- while (new Date(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
4988
+ while (new DateTime(y - 1, 0, firstThursdayPreviousYear).getDay() !== 4) {
4931
4989
  firstThursdayPreviousYear += 1;
4932
4990
  }
4933
- firstDay = new Date(y - 1, 0, firstThursdayPreviousYear - 3);
4991
+ firstDay = new DateTime(y - 1, 0, firstThursdayPreviousYear - 3);
4934
4992
  break;
4935
4993
  }
4936
4994
  const dif = (_date.getTime() - firstDay.getTime()) / 86400000;
@@ -5069,8 +5127,8 @@ const NETWORKDAYS_INTL = {
5069
5127
  });
5070
5128
  }
5071
5129
  const invertDate = _startDate.getTime() > _endDate.getTime();
5072
- const stopDate = new Date((invertDate ? _startDate : _endDate).getTime());
5073
- let stepDate = new Date((invertDate ? _endDate : _startDate).getTime());
5130
+ const stopDate = DateTime.fromTimestamp((invertDate ? _startDate : _endDate).getTime());
5131
+ let stepDate = DateTime.fromTimestamp((invertDate ? _endDate : _startDate).getTime());
5074
5132
  const timeStopDate = stopDate.getTime();
5075
5133
  let timeStepDate = stepDate.getTime();
5076
5134
  let netWorkingDay = 0;
@@ -5094,8 +5152,7 @@ const NOW = {
5094
5152
  returns: ["DATE"],
5095
5153
  returnFormat: { specificFormat: "m/d/yyyy hh:mm:ss" },
5096
5154
  compute: function () {
5097
- let today = new Date();
5098
- today.setMilliseconds(0);
5155
+ let today = DateTime.now();
5099
5156
  const delta = today.getTime() - INITIAL_1900_DAY.getTime();
5100
5157
  const time = today.getHours() / 24 + today.getMinutes() / 1440 + today.getSeconds() / 86400;
5101
5158
  return Math.floor(delta / 86400000) + time;
@@ -5169,8 +5226,8 @@ const TODAY = {
5169
5226
  returns: ["DATE"],
5170
5227
  returnFormat: { specificFormat: "m/d/yyyy" },
5171
5228
  compute: function () {
5172
- const today = new Date();
5173
- const jsDate = new Date(today.getFullYear(), today.getMonth(), today.getDate());
5229
+ const today = DateTime.now();
5230
+ const jsDate = new DateTime(today.getFullYear(), today.getMonth(), today.getDate());
5174
5231
  const delta = jsDate.getTime() - INITIAL_1900_DAY.getTime();
5175
5232
  return Math.round(delta / 86400000);
5176
5233
  },
@@ -5226,10 +5283,10 @@ const WEEKNUM = {
5226
5283
  }
5227
5284
  const y = _date.getFullYear();
5228
5285
  let dayStart = 1;
5229
- let startDayOfFirstWeek = new Date(y, 0, dayStart);
5286
+ let startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5230
5287
  while (startDayOfFirstWeek.getDay() !== startDayOfWeek) {
5231
5288
  dayStart += 1;
5232
- startDayOfFirstWeek = new Date(y, 0, dayStart);
5289
+ startDayOfFirstWeek = new DateTime(y, 0, dayStart);
5233
5290
  }
5234
5291
  const dif = (_date.getTime() - startDayOfFirstWeek.getTime()) / 86400000;
5235
5292
  if (dif < 0) {
@@ -5283,7 +5340,7 @@ const WORKDAY_INTL = {
5283
5340
  timesHoliday.add(holiday.getTime());
5284
5341
  });
5285
5342
  }
5286
- let stepDate = new Date(_startDate.getTime());
5343
+ let stepDate = DateTime.fromTimestamp(_startDate.getTime());
5287
5344
  let timeStepDate = stepDate.getTime();
5288
5345
  const unitDay = Math.sign(_numDays);
5289
5346
  let stepDay = Math.abs(_numDays);
@@ -18706,13 +18763,18 @@ class EvaluationPlugin extends UIPlugin {
18706
18763
  // Getters
18707
18764
  // ---------------------------------------------------------------------------
18708
18765
  evaluateFormula(formulaString, sheetId = this.getters.getActiveSheetId()) {
18709
- const compiledFormula = compile(formulaString);
18710
- const params = this.getFormulaParameters(() => { });
18711
- const ranges = [];
18712
- for (let xc of compiledFormula.dependencies) {
18713
- ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
18766
+ try {
18767
+ const compiledFormula = compile(formulaString);
18768
+ const params = this.getFormulaParameters(() => { });
18769
+ const ranges = [];
18770
+ for (let xc of compiledFormula.dependencies) {
18771
+ ranges.push(this.getters.getRangeFromSheetXC(sheetId, xc));
18772
+ }
18773
+ return compiledFormula.execute(ranges, sheetId, ...params);
18774
+ }
18775
+ catch {
18776
+ return "#ERROR";
18714
18777
  }
18715
- return compiledFormula.execute(ranges, sheetId, ...params);
18716
18778
  }
18717
18779
  /**
18718
18780
  * Return the value of each cell in the range as they are displayed in the grid.
@@ -19205,25 +19267,26 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19205
19267
  */
19206
19268
  this.rulePredicate = {
19207
19269
  CellIsRule: (cell, rule) => {
19270
+ var _a, _b, _c, _d, _e, _f;
19208
19271
  if (cell && cell.evaluated.type === CellValueType.error) {
19209
19272
  return false;
19210
19273
  }
19211
19274
  const values = rule.values.map(parsePrimitiveContent);
19212
19275
  switch (rule.operator) {
19213
19276
  case "IsEmpty":
19214
- return !isDefined(cell) || cell.evaluated.value.toString().trim() === "";
19277
+ return !isDefined(cell) || ((_a = cell.evaluated.value) === null || _a === void 0 ? void 0 : _a.toString().trim()) === "";
19215
19278
  case "IsNotEmpty":
19216
- return isDefined(cell) && cell.evaluated.value.toString().trim() !== "";
19279
+ return isDefined(cell) && ((_b = cell.evaluated.value) === null || _b === void 0 ? void 0 : _b.toString().trim()) !== "";
19217
19280
  case "BeginsWith":
19218
19281
  if (!cell && values[0] === "") {
19219
19282
  return false;
19220
19283
  }
19221
- return (isDefined(cell) && (cell === null || cell === void 0 ? void 0 : cell.evaluated.value.toString().startsWith(values[0].toString())));
19284
+ return (isDefined(cell) && ((_c = cell.evaluated.value) === null || _c === void 0 ? void 0 : _c.toString().startsWith(values[0].toString())));
19222
19285
  case "EndsWith":
19223
19286
  if (!cell && values[0] === "") {
19224
19287
  return false;
19225
19288
  }
19226
- return isDefined(cell) && cell.evaluated.value.toString().endsWith(values[0].toString());
19289
+ return isDefined(cell) && ((_d = cell.evaluated.value) === null || _d === void 0 ? void 0 : _d.toString().endsWith(values[0].toString()));
19227
19290
  case "Between":
19228
19291
  return (isDefined(cell) &&
19229
19292
  cell.evaluated.value >= values[0] &&
@@ -19233,11 +19296,11 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19233
19296
  cell.evaluated.value >= values[0] &&
19234
19297
  cell.evaluated.value <= values[1]);
19235
19298
  case "ContainsText":
19236
- return (isDefined(cell) && cell.evaluated.value.toString().indexOf(values[0].toString()) > -1);
19299
+ return (isDefined(cell) && ((_e = cell.evaluated.value) === null || _e === void 0 ? void 0 : _e.toString().indexOf(values[0].toString())) > -1);
19237
19300
  case "NotContains":
19238
19301
  return (!isDefined(cell) ||
19239
19302
  !cell.evaluated.value ||
19240
- cell.evaluated.value.toString().indexOf(values[0].toString()) == -1);
19303
+ ((_f = cell.evaluated.value) === null || _f === void 0 ? void 0 : _f.toString().indexOf(values[0].toString())) == -1);
19241
19304
  case "GreaterThan":
19242
19305
  return isDefined(cell) && cell.evaluated.value > values[0];
19243
19306
  case "GreaterThanOrEqual":
@@ -19346,39 +19409,34 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19346
19409
  this.computedIcons[activeSheetId] = {};
19347
19410
  const computedStyle = this.computedStyles[activeSheetId];
19348
19411
  for (let cf of this.getters.getConditionalFormats(activeSheetId)) {
19349
- try {
19350
- switch (cf.rule.type) {
19351
- case "ColorScaleRule":
19352
- for (let range of cf.ranges) {
19353
- this.applyColorScale(range, cf.rule);
19354
- }
19355
- break;
19356
- case "IconSetRule":
19357
- for (let range of cf.ranges) {
19358
- this.applyIcon(range, cf.rule);
19359
- }
19360
- break;
19361
- default:
19362
- for (let ref of cf.ranges) {
19363
- const zone = toZone(ref);
19364
- for (let row = zone.top; row <= zone.bottom; row++) {
19365
- for (let col = zone.left; col <= zone.right; col++) {
19366
- const pr = this.rulePredicate[cf.rule.type];
19367
- let cell = this.getters.getCell(activeSheetId, col, row);
19368
- if (pr && pr(cell, cf.rule)) {
19369
- if (!computedStyle[col])
19370
- computedStyle[col] = [];
19371
- // we must combine all the properties of all the CF rules applied to the given cell
19372
- computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
19373
- }
19412
+ switch (cf.rule.type) {
19413
+ case "ColorScaleRule":
19414
+ for (let range of cf.ranges) {
19415
+ this.applyColorScale(range, cf.rule);
19416
+ }
19417
+ break;
19418
+ case "IconSetRule":
19419
+ for (let range of cf.ranges) {
19420
+ this.applyIcon(range, cf.rule);
19421
+ }
19422
+ break;
19423
+ default:
19424
+ for (let ref of cf.ranges) {
19425
+ const zone = toZone(ref);
19426
+ for (let row = zone.top; row <= zone.bottom; row++) {
19427
+ for (let col = zone.left; col <= zone.right; col++) {
19428
+ const pr = this.rulePredicate[cf.rule.type];
19429
+ let cell = this.getters.getCell(activeSheetId, col, row);
19430
+ if (pr && pr(cell, cf.rule)) {
19431
+ if (!computedStyle[col])
19432
+ computedStyle[col] = [];
19433
+ // we must combine all the properties of all the CF rules applied to the given cell
19434
+ computedStyle[col][row] = Object.assign(((_a = computedStyle[col]) === null || _a === void 0 ? void 0 : _a[row]) || {}, cf.rule.style);
19374
19435
  }
19375
19436
  }
19376
19437
  }
19377
- break;
19378
- }
19379
- }
19380
- catch (_) {
19381
- // we don't care about the errors within the evaluation of a rule
19438
+ }
19439
+ break;
19382
19440
  }
19383
19441
  }
19384
19442
  }
@@ -19397,7 +19455,7 @@ class EvaluationConditionalFormatPlugin extends UIPlugin {
19397
19455
  return this.getters.evaluateFormula(`=PERCENTILE(${range},${Number(threshold.value) / 100})`);
19398
19456
  case "formula":
19399
19457
  const value = threshold.value && this.getters.evaluateFormula(threshold.value);
19400
- return !(value instanceof Promise) ? value : null;
19458
+ return typeof value === "number" ? value : null;
19401
19459
  default:
19402
19460
  return null;
19403
19461
  }
@@ -31337,6 +31395,6 @@ const helpers = {
31337
31395
  export { CommandResult, CorePlugin, DATETIME_FORMAT, DataSource, DispatchResult, Model, Registry, Revision, SPREADSHEET_DIMENSIONS, Spreadsheet, UIPlugin, DEBUG as __DEBUG__, __info__, astToFormula, cellTypes, compile, convertAstNodes, coreTypes, functionCache, helpers, invalidateEvaluationCommands, parse, readonlyAllowedCommands, registries, setTranslationMethod };
31338
31396
 
31339
31397
 
31340
- __info__.version = '15.2.13';
31341
- __info__.date = '2023-11-24T13:06:49.659Z';
31342
- __info__.hash = 'ea82269';
31398
+ __info__.version = '15.2.15';
31399
+ __info__.date = '2024-01-17T10:22:20.395Z';
31400
+ __info__.hash = 'c78b15d';