Repository navigation
Fix Omit & Overrides intersection excess, dual-package extends, split indexed-access helpers - #315
Merged
Merged
Conversation
…dexed-access helpers
Lazy on-click diagnosis with documented drift, tagSnapshot view fix, Awaited/ReturnType/ReadonlyMap/ReadonlySet support, function ret threading, mismatched-param crash fix, utilityNames completion, plus anchors/hostile/read/builtin fixtures and parity cases.
Single-line \n-joined sources in generateTypeChecks.spec.js become indented template literals bound to const src; AGENTS.md gains the rule plus the Object.assign shapeFor example.
Parity fixtures lose their caseNN placeholders: every case function is now named after what it checks (checkUppercase, addFrozenAnchor, checkAwaitedPromise), and run.mjs matches plain lowercase names anchored at line start instead of case digits. The twoArgs helper in functions.mjs inlines as a named function expression with typed params so no extra definition trips the runner. All written JSON goes through JSON.stringify(value, null, 2) plus trailing newline (31 expectation files reformatted, lock files untouched); AGENTS.md records the rule, the meaningful-names rule, and the token-economy rule (mechanical jobs belong in scripts, never shuttle file contents through the model).
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.
Fixes #314
What changed
src-runtime/inspectType.jsposts reports without a precomputed diagnosis: no per-error differ cost, no larger posts, no frozen rows.src-runtime/TypePanel.jsbuildCompareContentandsrc-runtime/compareText.jsdiff locally on open and on Copy, with comments stating the lazy contract (late twins can resolve more than the checker knew).src-runtime/reportedDiagnosis.spec.js(new, wired intotest_runtime.js) pins the contract with seven honesty tests, each in same-realm and cross-realm (structuredClone) legs: reports carry no diagnosis; the lazy diff finds the true row from transported values; a registry-less panel degrades to one opaque row instead of inventing member rows; the anchors-shaped payload diffs to exactly one row; an option-drifted panel shows the extra strictness row; a validator-drifted panel reproduces the exact production phantom union row; and a typed-array diagnosis carries no$typerow with same-vs-cross renders agreeing exactly.src-runtime/tagSnapshot.jsno longer tags typed arrays andDataViews: an expando tag on a view does not survivestructuredClone(typed-array serialization is buffer-only), so tagging printed a phantom informational$typerow on the checking side and lost the tag at the realm boundary, while no consumer ever read view tags (snapshotTagrejects non-plain protos,snapshotMatchesneeds registered classes). Views now post untouched likeMap/Set/Date.tagSnapshot.spec.jspins the new contract (testTypedArrayUntagged: identity, no tag).test/typechecking/anchors-diagnosis-input.mjs(+-output.mjs,test/typechecking.jsonentry,anchors-diagnosis-errors.json) pins the worker verdict for the production shape: the arrays-plus-instance call passes, the alignment call throws exactly once (test/jsdoc-expect: 41/41 agree with all fixtures below).test/typechecking/playcanvas-tower-hostile-input.mjs(+-output.mjs,test/typechecking.jsonentry,playcanvas-tower-hostile-errors.json) pins the worker verdict across every component family and hostile value: dense arrays intoVec | number[]unions, instances and tagged snapshots nominally,number | nullboth ways, frozen arrays, unknown names through theobjectfalse branch, dataless calls. Eleven throws pinned with values (sparse tail and typed array omitvalue: holes canonicalize ambiguously and views serialize as index objects). Three deliberate tsc divergences carry// Expected:notes (explicit null into optional-without-|null, frozen array intonumber[], sparse tail); every other line is tsc-strict clean with all@ts-expect-errordirectives consumed.src-runtime/validateArray.spec.jsgains frozen/typed-array/extra-prop cases;src-runtime/componentTowerStress.spec.jsgains explicit-null-into-optional, nullable-union members, union-all-fail and subclass-nominal cases: validator-level pins for what the hostile fixture exercises at worker level.retin all three expanders (expandType.js,expandTypeBabelTS.js,expandTypeDepFree.js, with triple parity holding),stringifyTypeprints it,Awaitedunwraps to the fulfillment type instead of wrapper-checking (a Promise was wrongly accepted, results wrongly rejected), andReturnTyperesolves declared returns.test/typechecking/builtin-utilities-input.mjs(+-output.mjs,test/typechecking.jsonentry,builtin-utilities-errors.json) pins 14 throws with tsc-strict green on every@ts-expect-error;test/parity/cases/builtins.mjspins 11 Awaited/ReturnType/intrinsic cases count-equal with tsc;validateReference.spec.jsgains Awaited/ReturnType/intrinsic specs andstringifyType.spec.jsgains the return-printing spec. The pre-existingsubstituteFunctionret handling needed no change.test/parity/cases/tower-hostile.mjspins the tower against tsc per case (8/8 agree): dense arrays, instances, unknown-name fallthrough and typed arrays count-equal; frozen arrays, sparse tails and explicit null carry asserted-directionparity-divergesmarkers (quieter/quieter/stricter).test/parity/cases/builtins.mjspins builtins against tsc per case (11/11 agree): Awaited unwrap, ReturnType resolution, all four intrinsics, union-distributed intrinsics,ReadonlyMap/ReadonlySetshapes, plus the documentedIterableshape-only divergence.test/typechecking/playcanvas-tower-read-input.mjs(+-output.mjs,test/typechecking.json,playcanvas-tower-read-errors.json) pins the read path:findComponent/findComponentsresolve through the return-position conditional, so lookups keep their type when the result flows into the next checked call, with unknown names falling back toComponent. Three throws pinned with posted$typesnapshots; one// Expected:note (live non-null instance vs declared| null— RTI checks values, tsc checks declarations).src-transpiler/Asserter.jsno longer emits references to undeclared variables: a JSDoc@paramnaming nothing declared (including stray@overloadblocks without a matching implementation signature) warnsMissing paramand skips instead of generating aReferenceErrorat runtime.src-transpiler/generateTypeChecks.spec.js(new) pins the skip, the overload-docblock skip, the rest-binding exemption (...restdeclares its binding) and the still-checking control.utilityNamesinsrc-runtime/firstBadEntry.jscompleted to all 29 utilitycasebranches ofvalidateReference(was 20, missingArrayLikefamily,ReadonlyArray/Map/Set,ConcatArray, async iterables). A registered class shadowing a missing name made the windowed map scan trustinstanceofand return clean without running the loop — a false negative where the validator takes the utility branch.firstBadEntry.spec.jspins the collision (testUtilityNameCollisionBailsOut, mutation-verified: old set scans -1, new set bails -2).AGENTS.mdgains the spec-source rule: JavaScript sources in specs are readable code in template literals, never\n-joined fragments or+-concatenated lines, with the snippet bound to its ownconst src, JSDoc stars aligned, and one-liners staying single-quoted (theObject.assignshape example documents the style).src-transpiler/generateTypeChecks.spec.jsis converted to the rule: its five\n-joined sources become indented template literals. No other new spec needed conversion (the runtime specs build values or parse types directly, never JS sources).Proof
Entity#addComponent data, fontAsset -1, tagged Color, dense anchor/margin,[0,0]alignment) carries exactly three worker strings (Element data.alignment has wrong type.,validateMapping failed), which is the current worker output for that payload, verified by replaying the log's ownvalue/expectthrough the served bundle'sexplainMismatch(1 finding) and through the full comparator render path (1 Diagnosis row, green tree, singlerti-fail-hiton alignment).tmp/drift-hunt.mjs, 2691 same-vs-cross pairs over hostile arrays, typed arrays, Maps/Sets, functions, class instances, getters, null-proto objects, six option sets) reproduces the phantom-row class on demand: a hostile panelvalidateArrayturns dense clean arrays into`[0,0,1,1]` at `data.anchor` matches no union member; closest is number[] with 1 problem, character-identical to the production rows. The committed drift specs pin this openly as panel behavior instead of suppressing it: the option-drift spec shows the strictness row, the validator-drift spec shows the phantom union row. After the view-untag fix the matrix shows 0 same-vs-cross divergences (34 before, all typed-array$typetransit losses).structuredClonepasses and the larger posts, and it flips on cheap checks; the lazy path spends zero per error either way.testReportCarriesNoDiagnosis; restoring thetagSnapshot.jsview branch breaks the view-transit test with the phantom$typeextra row; removing the localexplainMismatchrender calls breaks the foreign-registry spec (one opaque row).structuredClonepasses and larger posts (unmeasured in the 0.45ms-vs-10.36ms micro-benchmark, which also flips on cheap checks), and it froze the diagnosis at report time so late-loading twins could never add information. No code from that revision survives except its tests, rewritten as honesty specs.tsc --strict(TS2739, array not assignable toVec2) while the arrays-plus-instance call passes its options check.@ts-expect-error(consumed in full runs) and every divergence from tsc carries a// Expected:note with the analysis; tsc-strict runs are green except for the documented lines: the builtin fixture (14 throws), the hostile tower (11 throws), the read tower (3 throws), and the parity suites (65/65 agree with asserted directions).Latent holes
alignmentfailure itself is a genuine engine typing hole, deliberately left unfixed here:ElementComponent's getter declares@type {Vec2}with noElementComponentOptionsOverridesentry, while the setter acceptsVec2|number[]and the example passes[0,0]. tsc reports the same split (TS2739on the fixture's alignment call). Verdict: deferred to the engine repo (add analignment?: Vec2 | number[]override next to anchor/margin/pivot, or widen the getter); RTI is correctly reporting what the declared options type says.buildTypeTree(the expandable type tree, not the Diagnosis rows) still diffs in the panel realm against the panel registry, so in a registry-less panel it marks value keys as informational extras. Verdict: tolerated deliberately (tree is exploratory navigation, Diagnosis is the verdict record; unifying the tree would mean posting the whole materialized tree per report).MAX_DEPTH/MAX_MAP_ENTRIESbudgets bound the on-click diff, andrepeatdedup prevents re-sends.firstBadEntry.utilityNameswas incomplete (20 of 29 utility branches): a userland class shadowingReadonlyMap,ArrayLikeorAwaitedmade the windowed map scan return clean while validation failed — a silent false negative reachable withwindowedChecks: true(which the engine opts into). No engine class collides today, so nothing ever misfired in production; the set is now complete and the collision spec pins the bail-out. Verdict: fixed here.Dead code
explainMismatchcalls inbuildCompareContentandcompareTextare the only render path, unchanged. Proof of life: the foreign-registry spec test deletes the registry and asserts the fallback path still renders (one opaque row), so removing either call would fail the suite.tmp/fake-dom.mjs,tmp/render-compare.mjs,tmp/roundtrip.mjs,tmp/bundle-diagnosis.mjs,tmp/drift-hunt.mjs) stay out of the commit: the behaviors they probed are now pinned byreportedDiagnosis.spec.js(render path),tagSnapshot.spec.js(view transit), andanchors-diagnosis-errors.json(worker verdict).ArrayBuffer.isViewbranch intagName(src-runtime/tagSnapshot.js:38) can no longer produce a tag: the early return covers every view, so$typeoriginates only from registered-class instances viaregisteredNameOf. Proof of death:testTypedArrayUntaggedasserts identity return with no expando written, and the 2691-pair drift matrix shows zero same-vs-cross finding divergences involving views; re-adding the branch resurrects the phantom$typeextra row the view-transit spec forbids.