Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,25 @@ jobs:
- run: npm run build --if-present
- run: npm test

go:

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
go-version: ['1.24', 'stable']

runs-on: ${{ matrix.os }}

defaults:
run:
working-directory: go

steps:
- uses: actions/checkout@v4
- name: Use Go ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- run: go build ./...
- run: go test ./...
1,833 changes: 0 additions & 1,833 deletions dist-test/expr.test.js

This file was deleted.

1 change: 0 additions & 1 deletion dist-test/expr.test.js.map

This file was deleted.

273 changes: 0 additions & 273 deletions dist-test/ternary.test.js

This file was deleted.

1 change: 0 additions & 1 deletion dist-test/ternary.test.js.map

This file was deleted.

16 changes: 14 additions & 2 deletions go/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func makeExpr(op *Op, terms ...interface{}) []interface{} {
}

// Expr is the expression parser plugin for jsonic.
func Expr(j *jsonic.Jsonic, opts map[string]interface{}) {
func Expr(j *jsonic.Jsonic, opts map[string]interface{}) error {
eopts := resolveOptions(opts)
allOps := makeAllOps(j, eopts)

Expand Down Expand Up @@ -797,6 +797,16 @@ func Expr(j *jsonic.Jsonic, opts map[string]interface{}) {
G: "expr,list,imp,space",
})

// Expression ends on non-expression token (catch-all).
// Required so ParseAlts finds a match when the expr rule has consumed
// its tokens but the next token isn't one that extends the expression
// (e.g. ZZ after a suffix like "1!"). Without this, jsonic/go >= v0.1.13
// raises jsonic/unexpected.
exprClose = append(exprClose, &jsonic.AltSpec{
N: map[string]int{"expr": 0},
G: "expr,expr-end",
})

exprSpec.Close = exprClose

// AC: propagate result and evaluate.
Expand Down Expand Up @@ -1149,6 +1159,8 @@ func Expr(j *jsonic.Jsonic, opts map[string]interface{}) {

j.RSM()["ternary"] = ternarySpec
}

return nil
}

// prior converts a prior rule's node into the start of a new expression.
Expand Down Expand Up @@ -1321,7 +1333,7 @@ func MakeJsonic(opts ...map[string]interface{}) *jsonic.Jsonic {
if len(opts) > 0 {
pluginOpts = opts[0]
}
j.Use(Expr, pluginOpts)
_ = j.Use(Expr, pluginOpts)
return j
}

Expand Down
4 changes: 2 additions & 2 deletions go/expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func makeExprJsonic(opOpts ...map[string]interface{}) *jsonic.Jsonic {
if len(opOpts) > 0 {
opts = opOpts[0]
}
j.Use(Expr, opts)
_ = j.Use(Expr, opts)
return j
}

Expand Down Expand Up @@ -383,7 +383,7 @@ func TestEvaluation(t *testing.T) {
}

j := jsonic.Make()
j.Use(Expr, nil)
_ = j.Use(Expr, nil)

tests := []struct {
input string
Expand Down
2 changes: 1 addition & 1 deletion go/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ module github.com/jsonicjs/expr/go

go 1.24.7

require github.com/jsonicjs/jsonic/go v0.1.6
require github.com/jsonicjs/jsonic/go v0.1.18
20 changes: 20 additions & 0 deletions go/go.sum
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
github.com/jsonicjs/jsonic/go v0.1.6 h1:oUw4vxCK6tqa7SGN87vjCtx3sCpeHXdqfl25hx5LKP0=
github.com/jsonicjs/jsonic/go v0.1.6/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.7 h1:OT2X0WO6LpsueskatBqUFStiytMHk7ryyprta/ckzGM=
github.com/jsonicjs/jsonic/go v0.1.7/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.8 h1:OPV/Onzf3zTVgIiIHIKZg5RQhnZP03FsF2/WB2Tpeg0=
github.com/jsonicjs/jsonic/go v0.1.8/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.9 h1:BYnECqYtl4viLSpmiptCehmjfLJLtSJNoncPhjmkKZw=
github.com/jsonicjs/jsonic/go v0.1.9/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.10 h1:gNKxhhkq2r+sLX5MuOcjsiPBp82xDLHNh0CTnE3fIaM=
github.com/jsonicjs/jsonic/go v0.1.10/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.11 h1:XyrZ1umKZJoj31O+u1boifPxNpgV0JOVZGGhgDSU4WA=
github.com/jsonicjs/jsonic/go v0.1.11/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.12 h1:Cr0Lf3jAvgEGXJHxvOmL0xykF7SlTmPG9xrh0bmd5Kg=
github.com/jsonicjs/jsonic/go v0.1.12/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.13 h1:1c6S2I5eTBwcQuiOKX757ncekt5D6foErLftxA1LZ2U=
github.com/jsonicjs/jsonic/go v0.1.13/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.14 h1:RLbujFvSi4n/oOkEMDx/r0mb324oUv8KLdILm+sGKyc=
github.com/jsonicjs/jsonic/go v0.1.14/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.15 h1:gky2G3ZYM12+7R4TgQNKaM42C33DDdtRs4xdde/PKqU=
github.com/jsonicjs/jsonic/go v0.1.15/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.18 h1:OW15hjFisrw2n7HE6zDuQAikW8A5NUW8OyP4SCG2oFg=
github.com/jsonicjs/jsonic/go v0.1.18/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
8 changes: 3 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
},
"scripts": {
"test": "node --enable-source-maps --test dist-test/**/*.test.js",
"pretest": "npm run build",
"test-some": "node --enable-source-maps --test-name-pattern=\"$npm_config_pattern\" --test dist-test/**/*.test.js",
"watch": "tsc --build src test -w",
"build": "tsc --build src test",
"doc": "jsonic-doc",
"clean": "rm -rf node_modules yarn.lock package-lock.json",
"reset": "npm run clean && npm i && npm run build && npm test",
"repo-tag": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION && git push && git tag v$REPO_VERSION && git push --tags;",
"repo-publish": "npm run clean && npm i && npm run repo-publish-quick",
"repo-publish-quick": "npm run build && npm run test && npm run doc && npm run repo-tag && npm publish --access public --registry https://registry.npmjs.org "
"repo-publish-quick": "npm run build && npm run test && npm run repo-tag && npm publish --access public --registry https://registry.npmjs.org "
},
"license": "MIT",
"files": [
Expand All @@ -38,12 +38,10 @@
"LICENSE"
],
"devDependencies": {
"@hapi/code": "^9.0.3",
"@jsonic/doc": "^0.0.9",
"@types/node": "^24.9.1",
"typescript": "^5.7.3"
},
"peerDependencies": {
"jsonic": ">=2.20.1"
"jsonic": "^2.24.0"
}
}
3 changes: 2 additions & 1 deletion test/expr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */

import { describe, test, beforeEach } from 'node:test'
import { expect } from '@hapi/code'

import { Jsonic, Rule, Context, util } from 'jsonic'
import { Debug } from 'jsonic/debug'
Expand All @@ -18,6 +17,8 @@ import type {
Evaluate,
} from '..'

import { expect } from './spec-util'


const { omap } = util

Expand Down
72 changes: 72 additions & 0 deletions test/spec-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,85 @@

import * as fs from 'fs'
import * as path from 'path'
import * as assert from 'node:assert'


export type SpecEntry = {
input: string
expected: any
}

type ExpectValue = {
equal: (expected: any) => void
}

type ExpectFn = {
throw: (matcher?: RegExp | string) => void
}

// Strip null-prototype containers so deepStrictEqual treats them as
// equivalent to plain objects (matching @hapi/code's behavior).
function normalize(value: any, seen = new WeakMap()): any {
if (value === null || typeof value !== 'object') return value
if (seen.has(value)) return seen.get(value)
if (Array.isArray(value)) {
const out: any[] = []
seen.set(value, out)
for (const v of value) out.push(normalize(v, seen))
return out
}
const proto = Object.getPrototypeOf(value)
if (proto === null || proto === Object.prototype) {
const out: Record<string, any> = {}
seen.set(value, out)
for (const k of Object.keys(value)) out[k] = normalize(value[k], seen)
return out
}
return value
}

export function expect(actual: any): ExpectValue & ExpectFn {
return {
equal(expected: any) {
assert.deepStrictEqual(normalize(actual), normalize(expected))
},
throw(matcher?: RegExp | string) {
let threw: unknown
try {
actual()
} catch (err) {
threw = err
}
if (threw === undefined) {
throw new assert.AssertionError({
message: 'Expected function to throw',
actual: undefined,
expected: matcher,
})
}
if (matcher instanceof RegExp) {
const msg = (threw as Error)?.message ?? String(threw)
if (!matcher.test(msg)) {
throw new assert.AssertionError({
message: `Error message "${msg}" does not match ${matcher}`,
actual: msg,
expected: matcher,
})
}
} else if (typeof matcher === 'string') {
const msg = (threw as Error)?.message ?? String(threw)
if (!msg.includes(matcher)) {
throw new assert.AssertionError({
message: `Error message "${msg}" does not include "${matcher}"`,
actual: msg,
expected: matcher,
})
}
}
},
}
}

export function loadSpec(name: string): SpecEntry[] {
// Resolve spec files relative to the project root test/spec directory,
// since compiled tests run from dist-test/ but specs live in test/spec/.
Expand Down
3 changes: 1 addition & 2 deletions test/spec.test.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */

import { describe, test, beforeEach } from 'node:test'
import { expect } from '@hapi/code'

import { Jsonic, util } from 'jsonic'

import {
Expr,
} from '..'

import { loadSpec } from './spec-util'
import { loadSpec, expect } from './spec-util'


const { omap } = util
Expand Down
3 changes: 2 additions & 1 deletion test/ternary.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */

import { describe, test, beforeEach } from 'node:test'
import { expect } from '@hapi/code'

import { Jsonic, util } from 'jsonic'
import { Debug } from 'jsonic/debug'
Expand All @@ -15,6 +14,8 @@ import type {
Evaluate,
} from '..'

import { expect } from './spec-util'


const { omap } = util

Expand Down
Loading