@sheetxl/primitives 0.8.0-beta.11 → 0.8.0-beta.13

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.
@@ -6,6 +6,7 @@ import { IFunction } from './IFunction';
6
6
  import { IFunctionArguments } from './IFunctionArguments';
7
7
  import { IFormulaContext } from './IFormulaContext';
8
8
  import { IRuntime } from './IRuntime';
9
+ import { IRichData } from './IRichData';
9
10
  import { LocaleProfile } from './LocaleProfile';
10
11
  /**
11
12
  * Default implementation of the IFormulaContext interface.
@@ -63,6 +64,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
63
64
  getSheetCount(): number | null;
64
65
  /** @inheritdoc IFormulaContext.markVolatile */
65
66
  markVolatile(): void;
67
+ /** @inheritdoc IFormulaContext.defer */
68
+ defer(_executor: IFormulaContext.DeferExecutor, _payload?: unknown): unknown;
66
69
  /** @inheritdoc IFormulaContext.formatResults */
67
70
  formatResults(numFmt: string): void;
68
71
  /** @inheritdoc IFormulaContext.filterHidden */
@@ -94,7 +97,7 @@ export declare class StubbedFormulaContext implements IFormulaContext {
94
97
  * Unimplemented. See {@link IFormulaContext.createGrouping}.
95
98
  *
96
99
  * @remarks
97
- * Grouping needs Excel's key equality, which this stub does not have.
100
+ * Grouping needs the engine's key equality, which this stub does not have.
98
101
  */
99
102
  createGrouping(keys: IRange, options?: IFormulaContext.GroupingOptions): IFormulaContext.Grouping;
100
103
  /**
@@ -112,15 +115,15 @@ export declare class StubbedFormulaContext implements IFormulaContext {
112
115
  * Renders a scalar as text. See {@link IFormulaContext.toText}.
113
116
  *
114
117
  * @remarks
115
- * A BASIC rendering, deliberately NOT Excel's. Excel's rule -- coercion General (15
118
+ * A BASIC rendering, deliberately NOT the engine's. The engine's rule -- coercion General (15
116
119
  * significant digits, plain decimal while the rendering fits 20 characters, else
117
120
  * scientific) written with the workbook LOCALE's decimal separator -- is
118
121
  * `formatNumberGeneral` in `@sheetxl/sdk`, and every evaluation path reaches it through
119
122
  * the calculation context rather than through this stub. Numbers here get the plain JS
120
- * rendering, which diverges from Excel on both precision and separator.
123
+ * rendering, which diverges from the engine on both precision and separator.
121
124
  *
122
125
  * This exists so authoring, type defs and other non-runtime access get usable text
123
- * instead of throwing. Anything that needs Excel parity is running in the engine, and
126
+ * instead of throwing. Anything that needs the full rule is running in the engine, and
124
127
  * the engine never lands here.
125
128
  */
126
129
  toText(value: Scalar | undefined): string;
@@ -128,14 +131,14 @@ export declare class StubbedFormulaContext implements IFormulaContext {
128
131
  * Orders two scalars. See {@link IFormulaContext.compare}.
129
132
  *
130
133
  * @remarks
131
- * A BASIC total order, deliberately NOT Excel's. Excel's rule -- locale collation, the word
134
+ * A BASIC total order, deliberately NOT the engine's. The engine's rule -- locale collation, the word
132
135
  * sort, a blank taking the other operand's type, 11-decimal numeric normalization -- is
133
136
  * `ScalarCollation` in `@sheetxl/sdk`, and every evaluation path reaches it through the
134
137
  * calculation context rather than through this stub. `options` is ignored: strength is a
135
138
  * collation concept and nothing here collates.
136
139
  *
137
140
  * This exists so authoring, type defs and other non-runtime access get a usable ordering
138
- * instead of throwing. Anything that needs Excel parity is running in the engine, and the
141
+ * instead of throwing. Anything that needs the full rule is running in the engine, and the
139
142
  * engine never lands here.
140
143
  */
141
144
  compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
@@ -143,6 +146,8 @@ export declare class StubbedFormulaContext implements IFormulaContext {
143
146
  getRuntime(): IRuntime;
144
147
  /** @inheritdoc IFormulaContext.getArgs */
145
148
  getArgs(): IFunctionArguments;
149
+ /** @inheritdoc IFormulaContext.createRichData */
150
+ createRichData(_type: string, _data?: any): IRichData;
146
151
  }
147
152
  /**
148
153
  * The single, shared {@link IFormulaContext} that formula implementations use (via
@@ -231,6 +236,8 @@ export declare class ScopedFormulaContext implements IFormulaContext {
231
236
  getSheetCount(): number | null;
232
237
  /** @inheritdoc IFormulaContext.markVolatile */
233
238
  markVolatile(): void;
239
+ /** @inheritdoc IFormulaContext.defer */
240
+ defer(executor: IFormulaContext.DeferExecutor, payload?: unknown): unknown;
234
241
  /** @inheritdoc IFormulaContext.formatResults */
235
242
  formatResults(numFmt: string): void;
236
243
  /** @inheritdoc IFormulaContext.filterHidden */
@@ -245,6 +252,8 @@ export declare class ScopedFormulaContext implements IFormulaContext {
245
252
  compare(a: Scalar, b: Scalar, options?: Intl.CollatorOptions): number;
246
253
  /** @inheritdoc IFormulaContext.getRuntime */
247
254
  getRuntime(): IRuntime;
255
+ /** @inheritdoc IFormulaContext.createRichData */
256
+ createRichData(type: string, data?: any): IRichData;
248
257
  /** @inheritdoc IFormulaContext.getArgs */
249
258
  getArgs(): IFunctionArguments;
250
259
  get [Symbol.toStringTag](): string;
@@ -20,7 +20,7 @@ import { IReferenceRange } from './IReferenceRange';
20
20
  *
21
21
  * SpillErrorScalarSubType | "Unknown" | "Collision" | "IndeterminateSize" | "WorksheetEdge" | "OutOfMemoryWhileCalc" | "Table" | "MergedCell"
22
22
  * # Office 2023
23
- * 10. #CONNECT! This occurs when a data type is used that is not currently supported in this version of Excel.
23
+ * 10. #CONNECT! This occurs when a data type is used that is not currently supported.
24
24
  * 11. #BLOCKED! Indicates that an action or feature is blocked, possibly due to security settings, protected view, or other restrictions. Often related to online features, external links, or macros.
25
25
  * 12. #UNKNOWN! May be returned in the case of a protected workbook.
26
26
  * 13. #FIELD! Invalid field name for a data type.
@@ -5,6 +5,7 @@ import { IReferenceRange } from './IReferenceRange';
5
5
  import { IFunction } from './IFunction';
6
6
  import { IFunctionArguments } from './IFunctionArguments';
7
7
  import { IRuntime } from './IRuntime';
8
+ import { IRichData } from './IRichData';
8
9
  /**
9
10
  * Everything a formula function is allowed to know about the world outside its arguments.
10
11
  *
@@ -29,6 +30,7 @@ import { IRuntime } from './IRuntime';
29
30
  * | Category | Key methods |
30
31
  * |---|---|
31
32
  * | Evaluation lifecycle | `markVolatile`, `getRow`, `getColumn`, `getEntireCoords`, `getRandom` |
33
+ * | Answering later | `defer` |
32
34
  * | Argument reflection | `getArgs` |
33
35
  * | Output hints | `formatResults` |
34
36
  * | Range construction | `createRange`, `flattenAreas`, `filterHidden` |
@@ -65,8 +67,8 @@ export interface IFormulaContext {
65
67
  * A union `(A1:A5,B1:B2)` reaches a {@link IFunction.ParameterTypeJSON.reportType} slot as one
66
68
  * `IRange` per area. Functions that answer over it do so because they walk MEMBERS and a union
67
69
  * simply has more of them — `LARGE((DA1:DA5,DK1:DK2),2)` is the second largest of all seven
68
- * cells. This is that walk, and it is a helper rather than a marshalling step on purpose: Excel
69
- * flattens in exactly the same place, a shared reducer its bodies opt into, which is why the
70
+ * cells. This is that walk, and it is a helper rather than a marshalling step on purpose:
71
+ * flattening is a shared reducer the bodies opt into, which is why the
70
72
  * same union is flattened by `LARGE`, refused by `SUMPRODUCT` and answered `#REF!` by `ROWS`.
71
73
  *
72
74
  * The result is a single column in area order, row-major within each area. SHAPE IS NOT
@@ -115,7 +117,7 @@ export interface IFormulaContext {
115
117
  */
116
118
  getColumn(): number;
117
119
  /**
118
- * Whether the call being evaluated is in Excel's VALUE mode, where a multi-cell reference at a
120
+ * Whether the call being evaluated is in VALUE mode, where a multi-cell reference at a
119
121
  * slot that reads ONE value is implicitly intersected with the formula's cell (the `@` rule);
120
122
  * `false` is ARRAY mode, where such a slot reads the reference's first cell.
121
123
  *
@@ -154,7 +156,7 @@ export interface IFormulaContext {
154
156
  * A few arguments honor only their top-left corner and are re-sized to the shape of the range
155
157
  * that drives them — `SUMIF`'s `sum_range`, `LOOKUP`'s `result_vector`. The window can therefore
156
158
  * run off the bottom or right of the grid: `SUMIF(A1:A5,">0",A1048574)` asks for five rows
157
- * starting three from the end. Excel reads the part that fits and treats the rest as blank, which
159
+ * starting three from the end. The part that fits is read and the rest is blank, which
158
160
  * is what this returns; positions past the clamp read as `undefined` from `getValueAt`.
159
161
  *
160
162
  * @param anchor The coords of the argument as written; only its top-left corner is honored.
@@ -558,12 +560,11 @@ export interface IFormulaContext {
558
560
  * want the raw carry above — `DATEDIF("2020-01-31","2020-03-01","md")` is `-1`
559
561
  * because Jan 31 rolls into March. `EDATE`/`EOMONTH` want the opposite and CLAMP to
560
562
  * the target month's length, so they pre-clamp before calling here. One conversion,
561
- * two opposite rules, both matching Excel. Baking either one in breaks the other.
563
+ * two opposite rules. Baking either one in breaks the other.
562
564
  * * **Results may legitimately leave the calendar.** `YEARFRAC` basis 1 anchors a year
563
565
  * length on January 1 of `laterYear + 1`, which at the top of the calendar is
564
- * `10000-01-01`; Excel answers `1.9972602739726026` for
565
- * `YEARFRAC(DATE(9998,1,1),DATE(9999,12,31),1)` rather than `#NUM!`. A range check
566
- * here would break it.
566
+ * `10000-01-01`; `YEARFRAC(DATE(9998,1,1),DATE(9999,12,31),1)` is
567
+ * `1.9972602739726026`, not `#NUM!`. A range check here would break it.
567
568
  * * **The 16-bit argument limits are per-function.** `DATE`'s month errors outside
568
569
  * `[-32767, 32766]` while its day saturates to `32767`, and `TIME` errors outside
569
570
  * `[0, 32767]` on every argument — same magic number, three different rules.
@@ -571,8 +572,8 @@ export interface IFormulaContext {
571
572
  * Note the asymmetry with {@link getDateParts}, which DOES throw `#NUM!` outside the
572
573
  * calendar because it answers a user-facing question. An internal intermediate that
573
574
  * steps one day past the end must therefore not be round-tripped through it; compute
574
- * on the fields instead. That mistake made `YEARFRAC(DATE(9999,1,1),DATE(9999,12,31),0)`
575
- * `#NUM!` where Excel says `1`.
575
+ * on the fields instead, or `YEARFRAC(DATE(9999,1,1),DATE(9999,12,31),0)` becomes `#NUM!`
576
+ * rather than `1`.
576
577
  */
577
578
  getSerialDate(year: number, month: number, day: number, hour?: number, minute?: number, second?: number, millis?: number): number;
578
579
  /**
@@ -588,8 +589,8 @@ export interface IFormulaContext {
588
589
  *
589
590
  * @remarks
590
591
  * Argument REFLECTION, for the one thing a declaration cannot say: what happened at *this* call.
591
- * It exists to serve Excel's declared `any`, which means "no contract, the body decides" — every
592
- * other Excel type maps onto a type we already have and the marshaller handles it.
592
+ * It exists to serve a declared `any`, which means "no contract, the body decides" — every
593
+ * other declared type maps onto a type we already have and the marshaller handles it.
593
594
  *
594
595
  * The returned view is valid ONLY while the body that asked for it is running. Views are pooled
595
596
  * by dispatch depth, so retaining one across an `await`, a callback, or a nested evaluation hands
@@ -598,6 +599,65 @@ export interface IFormulaContext {
598
599
  * @throws If called outside a function dispatch — there are no arguments to reflect on.
599
600
  */
600
601
  getArgs(): IFunctionArguments;
602
+ /**
603
+ * Answers this call later: hands `executor` a call to settle, and leaves the cell showing what
604
+ * the function returns now.
605
+ *
606
+ * @param executor Runs once at the end of the recalculation with every call made against it.
607
+ * Pass a module-level function by name: calls join one batch when they name the same function.
608
+ * @param payload Everything the executor needs to answer this call, and how a later evaluation
609
+ * recognizes it: while the call is still waiting, a recalculation with
610
+ * an equal payload leaves it be rather than asking again. Once it has stopped, a recalculation
611
+ * calls the function again; what it fetched is answered from the workbook's cache
612
+ * (`IDeferContext.fetch`).
613
+ * @returns The last answer this call gave for the same question, when the function is being
614
+ * called again (a recalculation); `undefined` on a first call or a changed question. Return it
615
+ * to keep showing it until the new answer arrives, or return something else to show that the
616
+ * cell is waiting.
617
+ *
618
+ * @remarks
619
+ * The function still returns a value: what this call answers until its result arrives (nothing
620
+ * returned reads as blank), and it is what every formula over the cell calculates
621
+ * from meanwhile: return `#BUSY!` when they should wait as an error, or text such as
622
+ * `'Fetching…'` when that is what they should show.
623
+ *
624
+ * The executor runs after the recalculation, outside any cell, so the ambient `FormulaContext`
625
+ * is not its own: it reads the workbook through `ctx.getFormulaContext()`. Whatever the body
626
+ * knows about its cell goes in the payload.
627
+ *
628
+ * @example
629
+ * ```typescript
630
+ * function fetchAll(
631
+ * calls: readonly IFormulaContext.DeferredCall<string>[],
632
+ * ctx: IFormulaContext.IDeferContext
633
+ * ): void {
634
+ * for (const call of calls) {
635
+ * ctx.fetch(call.payload as string)
636
+ * .then((response) => response.text())
637
+ * .then((text) => call.resolve(text), (error) => call.reject(error));
638
+ * }
639
+ * }
640
+ *
641
+ * export function FETCHTEXT(url: string): string {
642
+ * FormulaContext.defer(fetchAll, url);
643
+ * return 'Fetching…';
644
+ * }
645
+ * ```
646
+ */
647
+ defer(executor: IFormulaContext.DeferExecutor, payload?: unknown): unknown;
648
+ /**
649
+ * A rich value of a registered type, made from its data as the type's JSON holds it, for the
650
+ * workbook being calculated.
651
+ *
652
+ * @param type The name of the value's kind (`'hyperlink'`): what its `getKind().getName()`
653
+ * will answer.
654
+ * @param data The value's data, as its JSON's `data`.
655
+ *
656
+ * @remarks
657
+ * A type nobody has registered still makes a value: one that carries the data and reads as
658
+ * nothing.
659
+ */
660
+ createRichData(type: string, data?: any): IRichData;
601
661
  }
602
662
  /**
603
663
  * {@inheritDoc IFormulaContext}
@@ -623,7 +683,7 @@ export declare namespace IFormulaContext {
623
683
  * then `range` is returned as it is, hidden rows included.
624
684
  *
625
685
  * @remarks
626
- * This is `SUBTOTAL` 1-11 (Excel: they "include manually hidden rows", which is what an
686
+ * This is `SUBTOTAL` 1-11 (they include manually hidden rows, which is what an
627
687
  * unfiltered sheet reads as). `SUBTOTAL` 101-111 and `AGGREGATE` leave it off and skip
628
688
  * always.
629
689
  * @defaultValue false
@@ -748,5 +808,150 @@ export declare namespace IFormulaContext {
748
808
  */
749
809
  readonly dow: number;
750
810
  }
811
+ /**
812
+ * Answers the calls made by {@link IFormulaContext.defer} against it. Invoked once at the end of
813
+ * a recalculation with every such call; how many requests that becomes is the executor's choice.
814
+ */
815
+ type DeferExecutor<T = any> = (calls: readonly DeferredCall<T>[], ctx: IDeferContext) => void | Promise<void>;
816
+ /**
817
+ * One call made by {@link IFormulaContext.defer}, as its executor receives it.
818
+ *
819
+ * @remarks
820
+ * Settle each call itself, never by its position in a response. An executor that returns a
821
+ * promise which rejects fails every call it has not settled.
822
+ */
823
+ interface DeferredCall<T = any> {
824
+ /** What the function passed to `defer`. */
825
+ readonly payload: unknown;
826
+ /** Settles the call with its result. */
827
+ resolve(value: T, options?: DeferredCall.ResolveOptions): void;
828
+ /** Settles the call with an error: a `FormulaError` as itself, anything else as `#VALUE!`. */
829
+ reject(error: unknown): void;
830
+ /** Runs `fn` when the result is no longer wanted. */
831
+ onCancel(fn: () => void): void;
832
+ /**
833
+ * Whether the result is no longer wanted. Only an executor that holds calls to settle later
834
+ * needs it; a result for a cancelled call is dropped.
835
+ */
836
+ readonly cancelled: boolean;
837
+ }
838
+ namespace DeferredCall {
839
+ /**
840
+ * Options for {@link DeferredCall.resolve}.
841
+ */
842
+ interface ResolveOptions {
843
+ /**
844
+ * Whether the blanks of an array result stay blank when it spills. Omitted, they read as
845
+ * `0`, as any spilled array's blanks do.
846
+ *
847
+ * @remarks
848
+ * For data whose empty fields mean "nothing here", such as an imported file. The result
849
+ * keeps them while a formula passes it on as it is (`IF(c, result, …)`). A function that
850
+ * answers element by element builds a new array, whose blanks read as `0`
851
+ * (`IFERROR(result, …)`, `result & ""`).
852
+ * @defaultValue false
853
+ */
854
+ keepBlanks?: boolean;
855
+ }
856
+ }
857
+ /**
858
+ * What an executor is given beside its calls.
859
+ */
860
+ interface IDeferContext {
861
+ /** A random number in `[0, 1)` from the calculation's source, which a test can seed. */
862
+ getRandom(): number;
863
+ /**
864
+ * State kept for this executor across recalculations, made by `init` on first ask. Keep data
865
+ * here (maps, numbers, strings, buffers), not connections or sockets.
866
+ */
867
+ getState<S>(init: () => S): S;
868
+ /**
869
+ * Groups `calls` by payload and runs `answer` once per distinct payload with every call that
870
+ * asked it: one request per question, however many cells asked.
871
+ *
872
+ * @param calls The calls to group, usually every call the executor was handed.
873
+ * @param answer Settles one group. When it throws, or the promise it returns rejects, the
874
+ * group's calls it has not settled fail with that error; the other groups are not affected.
875
+ * @returns Resolves once every group has been answered. It never rejects.
876
+ *
877
+ * @remarks
878
+ * Payloads are equal as `defer` compares them: the same primitive, or plain objects or arrays
879
+ * whose own values are the same one level deep. Groups are answered concurrently, in the
880
+ * order their first call appears.
881
+ *
882
+ * @example
883
+ * ```typescript
884
+ * async function fetchQuotes(
885
+ * calls: readonly IFormulaContext.DeferredCall<number>[],
886
+ * ctx: IFormulaContext.IDeferContext
887
+ * ): Promise<void> {
888
+ * await ctx.byPayload(calls, async (ticker: string, group) => {
889
+ * const response = await ctx.fetch(`https://api.example.com/quote/${ticker}`);
890
+ * const price: number = (await response.json()).price;
891
+ * for (const call of group) call.resolve(price);
892
+ * });
893
+ * }
894
+ * ```
895
+ */
896
+ byPayload<T = any, P = unknown>(calls: readonly DeferredCall<T>[], answer: (payload: P, group: readonly DeferredCall<T>[]) => void | Promise<void>): Promise<void>;
897
+ /**
898
+ * A rich value of a registered type, for the workbook being calculated: what
899
+ * {@link IFormulaContext.createRichData} makes inside a cell, made here for a call's result.
900
+ */
901
+ createRichData(type: string, data?: any): IRichData;
902
+ /**
903
+ * Adds bytes to the workbook being calculated as a resource (an `IResource`), for a rich value
904
+ * to hold: pass it in {@link createRichData}'s data. The workbook saves it while a value holds
905
+ * it. With `fetchedFrom` it is the workbook's copy of that URL: {@link fetch} answers the URL
906
+ * from it, and adding the same URL again answers the resource already added.
907
+ */
908
+ addResource(buffer: ArrayBuffer, options?: {
909
+ fetchedFrom?: string;
910
+ }): object;
911
+ /**
912
+ * Fetches through the workbook being calculated: the standard `fetch`, answered by the
913
+ * fetchers the host registered for the URL's scheme, with the host's authentication. An
914
+ * answer the workbook already has for the URL (a picture it keeps, or anything fetched while
915
+ * it is open) answers from the workbook, and two calls for one URL share one request. In an
916
+ * external calculation (*Refresh All*) it goes to the source.
917
+ *
918
+ * Rejects when the URL cannot be reached, with a `FormulaError.Blocked` when the site responded
919
+ * but the browser would not let the page read it.
920
+ */
921
+ fetch(input: string, init?: RequestInit): Promise<Response>;
922
+ /**
923
+ * The formula context of the workbook being calculated, with no cell: its parsing, text,
924
+ * comparison and dates, read with the workbook's locale and date system.
925
+ *
926
+ * @remarks
927
+ * Valid for as long as the executor runs, across every `await`. The ambient `FormulaContext`
928
+ * is not: it belongs to the cell being evaluated, and an executor runs after that evaluation
929
+ * ends. What needs a cell (`getRow`, `getReference`, `getValueAt`, `defer`, `markVolatile`,
930
+ * `formatResults`, `getRandom`) throws here; {@link getRandom} is the executor's own.
931
+ */
932
+ getFormulaContext(): IFormulaContext;
933
+ /**
934
+ * Reads delimited text (CSV, TSV) into rows of values, each field read the way the workbook
935
+ * reads typed entry: numbers, dates, booleans and error labels become values, anything else
936
+ * stays text, and an empty field is blank.
937
+ *
938
+ * @param text The delimited text.
939
+ * @param options How the text is split.
940
+ * @returns The rows, padded with blanks to the widest row.
941
+ */
942
+ parseText(text: string, options?: IDeferContext.ParseTextOptions): Promise<Scalar[][]>;
943
+ }
944
+ namespace IDeferContext {
945
+ /**
946
+ * Options for {@link IDeferContext.parseText}.
947
+ */
948
+ interface ParseTextOptions {
949
+ /**
950
+ * The character between fields.
951
+ * @defaultValue `','`
952
+ */
953
+ delimiter?: string;
954
+ }
955
+ }
751
956
  }
752
957
  //# sourceMappingURL=IFormulaContext.d.ts.map
@@ -284,11 +284,9 @@ export declare namespace IFunction {
284
284
  getMembers(): readonly IFunction.IEnumMember[];
285
285
  }
286
286
  /**
287
- * Describes the runtime return behavior of a function, including modifiers like
288
- * async resolution, streaming data, or volatility.
287
+ * Describes the runtime return behavior of a function, including modifiers like volatility.
289
288
  *
290
289
  * @remarks
291
- * All return type modifiers are mutually exclusive.
292
290
  * If none are specified, The value will be returned with no special behavior.
293
291
  */
294
292
  interface IReturnType extends IValueType {
@@ -300,26 +298,13 @@ export declare namespace IFunction {
300
298
  * @see {@link ReturnTypeJSON.kind}
301
299
  */
302
300
  getKind(): ValueKind | null;
303
- /**
304
- * Indicates the return value is a Promise or Promise-like (i.e., async).
305
- * The system will mark the result as pending and re-trigger evaluation once resolved.
306
- *
307
- * Can be combined with any scalar, array, or range return type.
308
- */
309
- isAsync(): boolean;
310
- /**
311
- * Indicates whether the function produces a continuous stream of output (e.g., real-time data).
312
- *
313
- * @defaultValue `false`
314
- */
315
- isStreaming(): boolean;
316
301
  /**
317
302
  * True when the result can change with nothing dirty, so a cell naming this function
318
303
  * recalculates on every pass — the `Volatile<T>` marker.
319
304
  *
320
305
  * @remarks
321
306
  * STATIC, and read from the formula text at compile time: it is true of the call whether or
322
- * not the call runs, which is what a lazy argument (and Excel) requires.
307
+ * not the call runs, which is what a lazy argument requires.
323
308
  *
324
309
  * @see {@link ReturnTypeJSON.volatile}
325
310
  */
@@ -358,7 +343,7 @@ export declare namespace IFunction {
358
343
  * @remarks
359
344
  * Only meaningful for a VARIADIC function; a fixed parameter list is already its own maximum.
360
345
  * The number is the whole CALL's argument count, prefix and optional suffix included, and it
361
- * is refused where Excel refuses it — at entry, before evaluation.
346
+ * is refused at entry, before evaluation.
362
347
  *
363
348
  * @see {@link Repeating}
364
349
  */
@@ -660,8 +645,8 @@ export declare namespace IFunction {
660
645
  * Generated from the `NoLift<T>` marker.
661
646
  *
662
647
  * @remarks
663
- * Per parameter, because Excel is: `NETWORKDAYS.INTL` refuses a reference at its date slots
664
- * and lifts one at `weekend`. An ARRAY at the slot still lifts, a one-cell reference is an
648
+ * Per parameter, because Excel's built-ins differ by slot: `NETWORKDAYS.INTL` refuses a
649
+ * reference at its date slots and lifts one at `weekend`. An ARRAY at the slot still lifts, a one-cell reference is an
665
650
  * ordinary argument, and a repeating slot absorbs a container as members, so the marker only
666
651
  * ever applies to a non-repeating scalar parameter.
667
652
  */
@@ -701,7 +686,7 @@ export declare namespace IFunction {
701
686
  * union is the range arm, handed over whole. The slot never lifts.
702
687
  *
703
688
  * @remarks
704
- * Excel reads a one-cell argument at some array slots as THE ARGUMENT rather than as a
689
+ * Some array slots read a one-cell argument as THE ARGUMENT rather than as a
705
690
  * one-cell container: `SORT(<#N/A cell>,1,1,<#DIV/0! cell>)` is `#N/A` where
706
691
  * `TAKE(<#N/A cell>,<#DIV/0! cell>)` is `#DIV/0!`. The engine's default
707
692
  * for a range slot is TAKE's; this flag is SORT's. {@link scalar} and {@link range} each carry
@@ -738,8 +723,7 @@ export declare namespace IFunction {
738
723
  members: [name: string, value: number | string, deprecated?: string | true][];
739
724
  }
740
725
  /**
741
- * Describes the runtime return behavior of a function, including modifiers like
742
- * async resolution, streaming data, or volatility.
726
+ * Describes the runtime return behavior of a function, including modifiers like volatility.
743
727
  *
744
728
  * @remarks
745
729
  * If none are specified, The value will be returned with no special behavior.
@@ -763,29 +747,15 @@ export declare namespace IFunction {
763
747
  * is a scalar is its member value downstream.
764
748
  */
765
749
  kind?: ValueKind;
766
- /**
767
- * Indicates the return value is a Promise or Promise-like (i.e., async).
768
- * The system will mark the result as pending and re-trigger evaluation once resolved.
769
- *
770
- * Can be combined with any scalar, array, or range return type.
771
- */
772
- async?: boolean;
773
- /**
774
- * Indicates whether the function produces a continuous stream of output (e.g., real-time data).
775
- *
776
- * @defaultValue `false`
777
- */
778
- stream?: boolean;
779
750
  /**
780
751
  * The result can change with nothing dirty — a cell naming this function recalculates on
781
752
  * every pass. Generated from the `Volatile<T>` marker.
782
753
  *
783
754
  * @remarks
784
755
  * Collected at COMPILE time from the formula text (`CompiledFormula.hasVolatile`), because
785
- * that is where Excel decides it: `=IF(TRUE,1,RAND())` recalculates on every idle pass though
756
+ * that is where volatility is decided: `=IF(TRUE,1,RAND())` recalculates on every idle pass though
786
757
  * no branch selects the arm, and with lazy arguments the call never happens for the engine to
787
- * observe. Sits beside {@link async} and {@link stream} because all three are about WHEN a
788
- * result arrives rather than what it is.
758
+ * observe.
789
759
  *
790
760
  * @see {@link Volatile}
791
761
  */
@@ -806,11 +776,10 @@ export declare namespace IFunction {
806
776
  * parameter. Omitted at the default of 255.
807
777
  *
808
778
  * @remarks
809
- * Excel keeps one such number per NAME and compares it against the whole call's argument
810
- * count in its front end, so a call past it is refused AT ENTRY rather than answered — which
811
- * is why the cap lives on the declaration and not in a body. It is not derivable from the
812
- * shape: `STDEV` takes 255 arguments and `STDEV.S`, the same function under its dotted name,
813
- * takes 254.
779
+ * The cap is one number per NAME, compared against the whole call's argument count, so a call
780
+ * past it is refused AT ENTRY rather than answered — which is why the cap lives on the
781
+ * declaration and not in a body. It is not derivable from the shape: in Excel `STDEV` takes 255
782
+ * arguments and `STDEV.S`, the same function under its dotted name, takes 254.
814
783
  *
815
784
  * @defaultValue 255
816
785
  */
@@ -15,9 +15,8 @@ import { IFunction } from './IFunction';
15
15
  * - What was the value BEFORE the parameter's type coerced it?
16
16
  * - Was that empty slot an omission, or a blank cell the caller pointed at?
17
17
  *
18
- * Excel has behaviors that turn on exactly those questions, and they cluster at the
19
- * parameters Excel declares `any` — where there is nothing to express as a type, because Excel
20
- * declined to express one. `CUMIPMT` refuses a boolean at every slot while `FV` coerces one at
18
+ * Some functions have behaviors that turn on exactly those questions, and they cluster at
19
+ * parameters declared `any` — where there is nothing to express as a type. `CUMIPMT` refuses a boolean at every slot while `FV` coerces one at
21
20
  * every slot; the difference is not the values, it is that `CUMIPMT`'s slots are `any` and its
22
21
  * body decides.
23
22
  *
@@ -142,7 +141,7 @@ export interface IFunctionArguments {
142
141
  */
143
142
  getKindAt(index: number): ValueKind;
144
143
  /**
145
- * True when the argument at `index` is DIRECT — Excel's "typed into the list of arguments":
144
+ * True when the argument at `index` is DIRECT — typed into the list of arguments:
146
145
  * the evaluated value IS a value, not a container or a callable.
147
146
  *
148
147
  * @param index The PARAMETER index — the position in the body's own signature.
@@ -255,7 +255,7 @@ export interface IRange<T extends Scalar = Scalar> {
255
255
  * @remarks
256
256
  * Errors INSIDE a range are the body's to judge: the engine hands a valid range over whole and
257
257
  * never looks inside, so a function whose answer depends on every member says so with this
258
- * line, placed before its own validation where Excel's error outranks it. A reshaper or a
258
+ * line, placed before its own validation where the member's error outranks it. A reshaper or a
259
259
  * lookup, whose members pass through or are never read, needs no line at all.
260
260
  */
261
261
  firstError(): FormulaError.Known | null;
@@ -268,7 +268,7 @@ export interface IRange<T extends Scalar = Scalar> {
268
268
  * @remarks
269
269
  * `options.axis` is the TRAVERSAL order feeding the ordinal, not the orientation of the result:
270
270
  * the result is always Nx1, and a row is `flatten().transpose()`. The default is row-major,
271
- * which is the order Excel pairs two range operands in.
271
+ * which is the order two range operands pair in.
272
272
  *
273
273
  * `options.type` carries a read type onto the result, so a member the type filters out becomes
274
274
  * a HOLE at its ordinal rather than compacting the column. That is what lets two operands be
@@ -916,7 +916,7 @@ export declare namespace IRange {
916
916
  *
917
917
  * - By default, `broadcast()` follows strict alignment rules like NumPy and will
918
918
  * throw an error if the input ranges cannot be broadcasted together.
919
- * - When `misalignValue` is provided, `broadcast()` will instead mimic Excel behavior:
919
+ * - When `misalignValue` is provided, `broadcast()` will instead follow Excel's behavior:
920
920
  * - It finds the **largest valid intersection** of the ranges.
921
921
  * - It expands the result to the **union of both range sizes**.
922
922
  * - Any cells that do not have valid corresponding values from the inputs
@@ -974,7 +974,7 @@ export declare namespace IRange {
974
974
  *
975
975
  * @remarks
976
976
  * Off, a dimension of 1 is a short dimension like any other and pads `misalignValue` past
977
- * its one position: Excel's `MAP` rule, where a 1-row array is not stretched.
977
+ * its one position: the `MAP` rule, where a 1-row array is not stretched.
978
978
  */
979
979
  tile?: boolean;
980
980
  /**
@@ -71,7 +71,7 @@ export interface IRangeStats {
71
71
  */
72
72
  getAggregates(options?: IRange.IteratorOptions): Readonly<IRangeStats.Aggregates>;
73
73
  /**
74
- * Returns the sum as Excel's `SUM` reports it — {@link getAggregates}'s `sum` with Excel's
74
+ * Returns the sum as `SUM` reports it — {@link getAggregates}'s `sum` with Excel's
75
75
  * cancellation-to-zero rule applied.
76
76
  *
77
77
  * @param total A total the caller accumulated across SEVERAL stats instances. Omit for a
@@ -82,7 +82,7 @@ export interface IRangeStats {
82
82
  * @remarks
83
83
  * Collapses a total to exactly zero when it lands at least 50 binary exponents below the
84
84
  * operands that produced it, so `SUM(0.1,0.2,-0.3)` is `0` rather than `5.55111512312578E-17`.
85
- * Use this wherever you mean "the number Excel's SUM would show" — a status bar, a report
85
+ * Use this wherever you mean "the number SUM shows" — a status bar, a report
86
86
  * total, a formula. Use `getAggregates().sum` where you mean the true total of the data.
87
87
  *
88
88
  * The two genuinely differ, and neither is a rounding of the other:
@@ -92,12 +92,12 @@ export interface IRangeStats {
92
92
  * and `PERCENTOF`, and to NOTHING else — `SUMIF`, `SUMPRODUCT`, `SERIESSUM`, `DSUM`, the
93
93
  * `SUMX2MY2` family and every binary operator all keep the residue over the same values.
94
94
  * That is why this is a method you call and not a change to `getAggregates`.
95
- * - `AVERAGE` divides THIS, not the raw sum: snapping the mean instead is measurably wrong.
95
+ * - `AVERAGE` divides THIS, not the raw sum: snapping the mean instead is wrong.
96
96
  *
97
97
  * It is also cheap when it does not fire: a bound derived from `min`/`max` rejects any
98
98
  * ordinary total without re-reading the range.
99
99
  *
100
- * **Multiple ranges.** Excel evaluates the rule on the *final* accumulation step, so a total
100
+ * **Multiple ranges.** The rule applies on the *final* accumulation step, so a total
101
101
  * spanning several ranges must be judged against the range holding the LAST value — pass the
102
102
  * running total as `total` and call this on that range. (Snapping each range separately gets
103
103
  * `SUM(A1:A3,0)` and `SUM(A1:A1,A2:A2,A3:A3)` wrong in opposite directions.) A composite
@@ -245,7 +245,7 @@ export declare namespace IRangeStats {
245
245
  * Sorting requires materializing the full numeric population (O(n log n), one allocation).
246
246
  * Unlike `Aggregates`, sorted views are **not composable across sub-ranges**.
247
247
  *
248
- * Covers the following Excel functions (all share one sort per coords per calc cycle):
248
+ * Covers the following functions (all share one sort per coords per calc cycle):
249
249
  * - `LARGE`, `SMALL`
250
250
  * - `MEDIAN`, `PERCENTILE`, `PERCENTILE.INC`, `PERCENTILE.EXC`
251
251
  * - `QUARTILE`, `QUARTILE.INC`, `QUARTILE.EXC` (q1 = k=0.25, q3 = k=0.75)
@@ -310,7 +310,7 @@ export declare namespace IRangeStats {
310
310
  * one outside the population is not found.
311
311
  * @param exclusive If true, uses exclusive formula (0 and 1 are excluded).
312
312
  * @param significance Number of DECIMAL PLACES to TRUNCATE the result to — despite what
313
- * Excel's own help calls the argument, it is not significant digits and it does not round.
313
+ * Excel's help calls the argument, it is not significant digits and it does not round.
314
314
  * Truncated toward zero first (1.9 places means 1), and must be at least 1. Omit it for the
315
315
  * exact untruncated rank, which is also the only form that cannot fail.
316
316
  * @returns The percent rank of x; `null` if x is not found or there are no numbers in range.