fix: report an error for an unknown target in the JS binding - #6238
Conversation
prql-bot
left a comment
There was a problem hiding this comment.
pre-commit.ci - pr is red, and it's this diff: the repo's typos hook flags postgress in all three changed files (typos prqlc/bindings/js CHANGELOG.md → error: `postgress` should be `postgresql`, `postgres` at test_all.mjs:76, src/lib.rs:121, CHANGELOG.md:59). The hook runs with --write-changes, so pre-commit.ci's autofix rewrites the test's target to the valid sql.postgres — which inverts what the test asserts: compile would succeed and the to.throw() case would fail. A misspelling the typo checker itself recognises is the one thing this test can't use.
Pushing the fix: sql.postgrez in all three places (clean under typos 1.48.0, the version the hook pins), plus a message assertion on the throw — to.throw() with no argument passes on any error, and the surrounding tests in this file already assert on content.
The rest reads correct. Special-casing the empty string is the right call given Target::from_str("") doesn't parse and new CompileOptions() starts empty, so the default path is unchanged; the spanless target error skips .composed() harmlessly since composed is a no-op without a span; and the playground stays on the None branch.
One thing outside this PR's scope, since it would land in all three bindings at once: Target::from_str returns NotFound with no hints, so the thrown message names the bad target but not the valid ones — Target::names() is right there and would make the new error self-explanatory.
`postgress` is in the typos dictionary, so the `typos` pre-commit hook — which runs with `--write-changes` — rewrote the test's target to the valid `sql.postgres`, inverting what the test asserts. Also assert the thrown message names the unknown target.
prqlc-jssilently ignored an invalidtarget:CompileOptions→prqlc::OptionsdidTarget::from_str(&o.target).unwrap_or_default(), soopts.target = "sql.postgress"fell back tosql.anyand the caller got working-but-wrong generic SQL with no signal. This makes the conversion fallible so an unparseable target is thrown to the caller, matching the Python and C bindings, which both already propagate this error.An empty
targetis still the unset default and still meanssql.any— that's the valuenew CompileOptions()starts with, so keeping it accepted avoids a behavior change on the default path. The regression test covers both halves.Why the bindings diverged
Same parse, three different handlings before this change:
prqlc-python/src/lib.rs:150—Target::from_str(&o.target).map_err(ErrorMessages::from)?, and its default is the literal"sql.any"rather than an empty sentinel.prqlc-c/src/lib.rs:326— samemap_err(...)?.js/src/lib.rs—unwrap_or_default().The JS binding needed the empty-string case to keep working, and
unwrap_or_default()handled it as a side effect of swallowing every parse failure. Special-casing empty separates the two.The playground is unaffected:
Workbench.jsx:71callsprql.compile(value)with no options, which takes theOption<CompileOptions>::Nonepath and never touches this conversion.Verification
Built the node target with
wasm-pack build --target nodejs --devand ranmocha tests— 13 passing, including the two new cases.Confirmed the regression test fails without the fix: with
src/lib.rsstashed and the same rebuild,should throw on an unknown target rather than silently using sql.anyfails withAssertionError: expected [Function] to throw an error, while the rest stay green.cargo clippy -p prqlc-js --target wasm32-unknown-unknown --all-targets -- -D warningsis clean, as iscargo fmt -p prqlc-js -- --check.