test: run the jsx-runtime suite natively on tish test - #17
Merged
Conversation
Adds the native `tish test` runner (tish 3.7.1) for the vnode factory, and keeps every existing leg: `npm test` is still `test:dom && test:hmr`, because the DomHost reconciler needs a real DOM and the HMR test needs Vite. Neither can move to the VM, and neither should. `test/jsx-runtime.test.tish` was prepared earlier but had never run — `src/jsx-runtime.tish` imports `h`/`Fragment` from `Lattish.tish`, which used JS `undefined` in twelve null-ish checks, and Tish has no `undefined`. Those become plain `null` checks. The emitted JS is unchanged in behaviour: the JS target lowers `x !== null` to `x != null`, which still matches `undefined`. Note `typeof x === "undefined"` is NOT a portable spelling here, despite looking like one — Tish lowers `typeof` to a shim that reports "null" for both null and undefined, so the comparison can never be true on either target. The four genuine `typeof window`/`typeof console` host guards are left alone; they are checking for a host, not for a value. `test/lattish.test.tish` is renamed to `test/lattish.jsemit.tish`. It is a JS-emit suite, and `.test.tish` now means "a native tish test suite" — leaving it would have made a bare `tish test` try to run a jsdom suite on the VM and fail. Matches the existing `jsx-runtime.jsemit.tish`. Two copies of the same obsolete workaround are made idempotent. `tish build --target js` did not emit export lines up to 2.12; from 3.7 it does, so appending them unconditionally produced `SyntaxError: Duplicate export of 'exposeLattishHmrGlobals'` and the bundle failed to load. Both `scripts/append-exports.mjs` and the hand-rolled copy inside `test/hmr-vite.test.mjs` now append only what the emitted output is actually missing, so this works on either tish. `test/run-tests.mjs` also gains a `TISH_BIN` override, so the suite can run against a locally built tish; it still defaults to the installed package.
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 0 |
| Duplication | 0 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
Codacy flagged the export scanner I added. Most of the 28 findings are rules the file already broke (`const`, `for-of`, arrow functions) re-surfaced because the lines changed — Codacy's default ruleset bans ES2015 and wants type annotations in a `.mjs` file, neither of which fits an ESM build script. Two were mine and worth acting on: both regexes use `\s+`, which backtracks quadratically on a long whitespace run. The scan is now plain string work — no regex, so nothing to backtrack. Same behaviour, verified against all four bundles. While here, the helper is exported and the HMR test imports it instead of carrying a second copy of the same logic. That duplication is what made the first fix incomplete: `append-exports.mjs` was corrected and the HMR leg stayed red, because it re-appended from its own copy. The build step only runs when the module is invoked directly, so importing it has no side effects.
The build post-processed every bundle to append ESM export lines, because `tish build --target js`
did not emit them up to 2.12. From 3.7 it does, so the step was appending duplicates and the
module failed to load outright with `SyntaxError: Duplicate export of '<name>'`.
Making the append idempotent (the previous commit) fixed the symptom while leaving a build step
whose whole reason for existing was gone. It only had one remaining job: `jsx-runtime.tish` and
`jsx-dev-runtime.tish` import `Fragment` but never re-exported it, so the automatic JSX runtime
contract was being satisfied by a script bolting the name onto the emitted output rather than by
the source.
Both now `export { Fragment }` explicitly, which is where that contract belongs, and tish emits
every name for all four bundles. `scripts/append-exports.mjs` and its copy inside the HMR test
are deleted.
This also clears the Codacy findings on that file, which were unfixable in place: its ruleset
forbids `import`/`export`, `const`, `for-of`, `Set`, and `Array.prototype.includes`, none of
which an ESM build script targeting Node 22 can avoid. The pre-existing version violated exactly
the same rules — they only surfaced because the lines changed. Deleting the file is the honest
resolution rather than an exclude entry.
The previous commit deleted scripts/append-exports.mjs but the import in test/hmr-vite.test.mjs was not included in it, so CI failed with ERR_MODULE_NOT_FOUND while the working tree was fine.
Companion to the previous two commits: the `build` script still ran `node scripts/append-exports.mjs` after the file was removed, so CI failed at the Build step with MODULE_NOT_FOUND.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the native
tish testrunner (tish 3.7.1) for the vnode factory, and keeps every existing leg.npm testis stilltest:dom && test:hmr— the DomHost reconciler needs a real DOM and the HMR test needs Vite. Neither can move to the VM, and neither should.Unblocking the native suite
test/jsx-runtime.test.tishwas prepared earlier but had never actually run:src/jsx-runtime.tishimportsh/FragmentfromLattish.tish, which used JSundefinedin twelve null-ish checks, and Tish has noundefined. Those become plainnullchecks — the emitted JS is unchanged in behaviour, since the JS target lowersx !== nulltox != null, which still matchesundefined.Worth recording:
typeof x === "undefined"is not a portable spelling, despite looking like one. Tish lowerstypeofto a shim reporting"null"for both null and undefined, so the comparison can never be true on either target. I tried it first and it brokememoin the JS emit. The four genuinetypeof window/typeof consolehost guards are untouched — those check for a host, not a value.Duplicate-export fix
tish build --target jsdid not emit export lines up to 2.12; from 3.7 it does. Appending them unconditionally then produced:and the bundle failed to load outright. There were two independent copies of that workaround —
scripts/append-exports.mjsand a hand-rolled one insidetest/hmr-vite.test.mjs— so fixing only the first left the HMR leg red. Both now append only what the emitted output is missing, which works on either tish version rather than trading one breakage for another.Anyone upgrading a project that post-processes tish JS output will hit this.
Also
test/lattish.test.tish->test/lattish.jsemit.tish. It is a JS-emit suite, and.test.tishnow means "native tish test suite" — leaving it would make a baretish testtry to run a jsdom suite on the VM. Matches the existingjsx-runtime.jsemit.tish.test/run-tests.mjsgains aTISH_BINoverride for running against a locally built tish; defaults to the installed package.@tishlang/tish2.12.0->3.7.1.Test plan
npm test— DOM (jsdom) + HMR (Vite), both greentish test— 5/5 nativeLattish,lattishHmr,jsx-runtime,jsx-dev-runtime)