Skip to content

fix(metadata): mark the SHEET/SHEETS argument as optional - #1717

Draft
sequba wants to merge 1 commit into
developfrom
fix/sheet-sheets-optional-arg-metadata
Draft

fix(metadata): mark the SHEET/SHEETS argument as optional#1717
sequba wants to merge 1 commit into
developfrom
fix/sheet-sheets-optional-arg-metadata

Conversation

@sequba

@sequba sequba commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

SHEET and SHEETS declared their single argument as required in implementedFunctions, although both accept a zero-argument call: runFunctionWithReferenceArgument serves args.length === 0 itself, before isNumberOfArgumentValuesValid is consulted.

The change is metadata-only — optionalArg has no other consumer in src/, and evaluation is unaffected (covered by the existing function-sheet/function-sheets specs). It is split out of #1692, whose function-metadata API is the first consumer that can observe it.

Context

How did you test your changes?

Types of changes

  • Breaking change (a fix or a feature because of which an existing functionality doesn't work as expected anymore)
  • New feature or improvement (a non-breaking change that adds functionality)
  • Bug fix (a non-breaking change that fixes an issue)
  • Additional language file, or a change to an existing language file (translations)
  • Change to the documentation

Related issues:

  1. Fixes #...

Checklist:

  • I have reviewed the guidelines about Contributing to HyperFormula and I confirm that my code follows the code style of this project.
  • I have signed the Contributor License Agreement.
  • My change is compliant with the OpenDocument standard.
  • My change is compatible with Microsoft Excel.
  • My change is compatible with Google Sheets.
  • I described my changes in the CHANGELOG.md file.
  • My changes require a documentation update.
  • My changes require a migration guide.

`SHEET` and `SHEETS` declared their single argument as required in
`implementedFunctions`, although both accept a zero-argument call:
`runFunctionWithReferenceArgument` serves `args.length === 0` itself,
before `isNumberOfArgumentValuesValid` is consulted.

The change is metadata-only — `optionalArg` has no other consumer in
`src/`, and evaluation is unaffected (covered by the existing
function-sheet/function-sheets specs). It is split out of #1692, whose
function-metadata API is the first consumer that can observe it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@netlify

netlify Bot commented Jul 30, 2026

Copy link
Copy Markdown

Deploy Preview for hyperformula-dev-docs ready!

Name Link
🔨 Latest commit 8eded2f
🔍 Latest deploy log https://app.netlify.com/projects/hyperformula-dev-docs/deploys/6a6b20571054a000074d25f0
😎 Deploy Preview https://deploy-preview-1717--hyperformula-dev-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown

Performance comparison of head (8eded2f) vs base (ad142ba)

                                     testName |    base |    head | change
--------------------------------------------------------------------------
                                      Sheet A |  482.45 |  485.81 | +0.70%
                                      Sheet B |  153.77 |  153.47 | -0.20%
                                      Sheet T |  136.73 |  139.81 | +2.25%
                                Column ranges |  468.29 |   464.2 | -0.87%
                                Sorted lookup | 13707.8 | 13725.6 | +0.13%
Sheet A:  change value, add/remove row/column |   16.21 |   15.62 | -3.64%
 Sheet B: change value, add/remove row/column |  125.42 |  128.35 | +2.34%
                   Column ranges - add column |  148.75 |  144.08 | -3.14%
                Column ranges - without batch |  452.44 |  435.33 | -3.78%
                        Column ranges - batch |  113.39 |  113.78 | +0.34%

@codecov

codecov Bot commented Jul 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.22%. Comparing base (ad142ba) to head (8eded2f).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop    #1717   +/-   ##
========================================
  Coverage    97.22%   97.22%           
========================================
  Files          178      178           
  Lines        15612    15612           
  Branches      3430     3430           
========================================
  Hits         15178    15178           
  Misses         426      426           
  Partials         8        8           
Files with missing lines Coverage Δ
src/interpreter/plugin/InformationPlugin.ts 93.33% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

sequba added a commit that referenced this pull request Jul 30, 2026
…F-249)

Addresses the review of this branch. Every factual claim below was verified
against a live engine built from src/, not against Excel's documentation.

Correctness
-----------
- GAUSS stated the inverse of what it computes ("falling more than this many
  times standard deviation from mean"). GAUSS(2) is 0.47725, i.e. the
  probability of falling BETWEEN the mean and z; "more than" is 0.0228.
- SHEET/SHEETS declared their single argument as required while accepting a
  zero-argument call, so getFunctionDetails contradicted the entry's own
  "An optional sheet name..." and its first example, =SHEET(). Restores
  optionalArg: true. This is metadata-only: optionalArg has exactly two
  readers, and isNumberOfArgumentValuesValid is unreachable from
  runFunctionWithReferenceArgument, which serves args.length === 0 itself.
  The docs page prints SHEET([value]) again, as it did before this branch.
  Supersedes #1717, which can be closed.
- A function id colliding with an Object.prototype member (`toString`,
  `valueOf`, `__proto__`) reported as a built-in id, because the catalogue
  doubles as the built-in id set and is indexed with a caller-supplied id.
  A custom function registered under such a name leaked into the static list
  and came back with localizedName as a function rather than a string, which
  then vanished through JSON.stringify - breaking this API's own round-trip
  invariant. FUNCTION_DOCS is now prototype-less, which fixes every lookup
  site at once, plus a typeof guard in resolveName for the translation
  package, which is indexed the same way.

Prose describes HyperFormula, not Excel
---------------------------------------
The catalogue was seeded from a page documenting Excel. INT and BASE were
corrected earlier as one-offs; these are the rest of that population:

- CEILING/FLOOR named #NUM! for significance 0; it is #DIV/0!. #NUM! occurs
  only for a positive number with a negative significance, and number 0
  yields 0 whatever the sign.
- CEILING.MATH/FLOOR.MATH said "when non-zero"; only mode 1 switches the
  direction - mode 2 behaves like the default 0.
- nine engineering `places` descriptions were BASE's semantics: a minimum
  width. They are an exact width, #NUM! when the result needs more digits,
  and ignored for negative numbers.
- DECIMAL said "positive integer"; DECIMAL("0", 2) is 0.
- MOD said "one integer"; MOD(10.5, 3) is 1.5.
- MROUND omitted that base 0 returns 0.
- GCD, LCM, MULTINOMIAL, COMBIN, COMBINA and ROMAN truncate to an integer,
  documented for FACT/FACTDOUBLE but not for these.
- ISEVEN/ISODD short descriptions implied a binary split; both return FALSE
  for a fractional value.
- the seven *A variants claimed text counts as 0. AVERAGEA(1, "3") is 2:
  numeric text coerces, non-numeric text passed directly gives #VALUE!, and
  only text inside a range counts as 0.

Six of these are genuine deviations from Excel and Google Sheets and are now
rows in the list of differences, with a note on the shared root causes.

Naming and categories, before they become API surface
-----------------------------------------------------
getFunctionDetails makes ~900 parameter names public, so these are cheap now
and breaking later. Parameter counts are unchanged throughout.

- one `cumulative` flag across all 14 distributions, replacing a 6/8 split
  between `boolean` (which named the type, not the role) and `mode` (which
  was also carrying four unrelated meanings). TDIST's third argument is a
  tail count, so it becomes `tails`.
- positional number1..number5 replaced by the statistical roles they play in
  11 functions (BETA.DIST, BINOM.DIST, HYPGEOM.DIST, WEIBULL.DIST, ...).
- Excel's criteria_range1/criteria1 everywhere; COUNTIFS used `range1`,
  which meant "criteria range" there and "the x values" in SUMX2MY2.
- FIND takes SEARCH's parameter names; they are the same operation.
- DAYS(end_date, start_date) and DAYS360(start_date, end_date, format) no
  longer share date1/date2 for opposite roles.
- SUMX2MY2/SUMX2PY2/SUMXMY2 get array_x/array_y and three descriptions that
  can actually be told apart.
- BESSELI/J/K/Y move to Engineering, N to Information, COUNTUNIQUE to
  Statistical, matching where Excel and Google Sheets classify them.
- FUNCTION_CATEGORIES is alphabetical, so the generated page's sections are.
- no two of the 423 ids now share a shortDescription (was 14 groups over 32
  functions, including the standard-normal pair reusing the general normal
  pair's wording verbatim).

Structure
---------
- FunctionRegistry.isListableFunctionId is now the single listability gate,
  applied by both getListableFunctionIds and getFunctionDetails. The design
  rests on the two tiers agreeing; that was upheld by two copies of the rule
  in two files.
- getAvailableFunctions' JSDoc called custom functions "instance-scoped".
  registerFunctionPlugin registers globally; the static methods omit them by
  policy. Reworded to say that.
- DEV_DOCS promised drift detection on "optionality that does not match
  optionalArg/defaultValue". No such check exists - ParameterDoc has no
  optionality field - and its absence is why the SHEET/SHEETS contradiction
  shipped. Documents the real gap and the rule for zero-argument calls.
- script/*.ts is now linted (it was covered by the blanket `script` ignore,
  so the branch's three new files were neither linted nor type-checked by
  any npm script). They pass clean. The legacy CommonJS helpers stay ignored.

Verified: 502/502 suites, 6172 passed, 0 failed (was 2 failed of 6164);
tsc --noEmit clean; lint 0 errors; docs page still 423 rows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant