Changes
Follow-ups to #35, consolidated in #53. Every expectation is checked against jsonata-js 2.2.2.
Breaking changes
- Regex maps from custom functions: a regex is a function inside an expression. A custom function receives a regex argument as a
{"pattern", "flags"}map, and only that same map turns back into a regex when returned; a map of that shape the function builds, copies or reads from input is a plain object. To migrate, return the regex value you received (README, Regex Arguments). - Lambda context: a lambda's body evaluates against the context it was defined in, as in jsonata-js.
($f := function($x){ name & $x }; items.$f("!"))reads the root'sname, not each item's; pass the item as an argument instead (README, Lambda Context). functions.EvalFnlost itsfocusparameter, and the standard library applies function values with a null context (README,functions.EvalFn).- Argument validation: every builtin except
$containsvalidates argument counts and types against its jsonata-js signature ($sort([1], 1),$map([1], 2)→ T0410;$sum(["a"])→ T0412). - Custom function
focusisnilwhen the function is passed as an argument or applied by a barex ~> $f. WithSequencecounts input data, as jsonata-js'ssequenceoption does (D2015), with jsonata-js's last-step exemption.- Nesting limits: S0218 past 10,000 parse levels; U1001 past 1,500 nested calls through partial applications, compositions, function arguments, transforms and builtin callbacks.
Fixes — jsonata-js conformance
- Functions: context arguments, signature validation, tail calls, null-context function arguments, HOF callback arities, partial applications (no context, declared parameters, unwrapped array arguments),
$clone,$distinctof variables and parameters,$powerwith an undefined exponent (D3061). - Numbers:
$stringand&lay out numbers as jsonata-js does, including numbers read from raw JSON (1.50→"1.5"). - Regex: a regex is a function value; a called regex searches from its offset (exact also with left context) and converts its argument as JavaScript's
String()does; lexing of/and regex literals follows jsonata-js. - Dates:
$toMillisfollows jsonata-js's picture regex with a linear step budget;$fromMillisoffset pictures read the parsed presentation. - Paths: constructed arrays,
[], builtin result sequences,%resolved at parse time, groups on whole paths, stages after#/@bindings,**and*. - Fast paths:
EvalBytes,EvalMapandStreamEvaluatoragree withEval(numeric field names, groups, bindings, number comparisons beyond 2^53);StreamEvaluator.EvalMapof an empty map is{}.
Known differences
- Large integers: an integer literal from raw JSON with magnitude above 2^53 keeps its digits in
$stringand&(12345678901234567890stays as is; jsonata-js prints12345678901234567000). Arithmetic rounds and comparisons use float64. See README row 36. - The README table (rows 1–36) documents every deliberate difference.
Robustness and performance
- No walk over data recurses (tested at 200,000 levels); function-value nesting is bounded; long chains compile and evaluate in linear time.
- Parsed
$toMillispictures are cached (about 40% faster than v0.5.3 on a picture). Overall evaluation is about 12% slower than v0.5.3 (geometric mean of the benchmarks), the cost of the parity work; allocations are about 5% lower. Details in #53.
Tests
-
Coverage 93.8%; parity cases run through
Eval,EvalBytes,EvalMapandStreamEvaluator. -
npm:
gnata-js@0.6.0