Fix #784, #781, #780, #779: destructuring default/rest/cover-grammar gaps#797
Merged
Conversation
…gaps #784 - destructuring defaults applied on `null` instead of `undefined`-only. Replace the `?? default` (`Expr.NullishCoalescing`, triggers on null) at all six desugaring sites with a shared DefaultIfUndefined helper (`v = access; v === undefined ? default : v`), spilling the access so it is read exactly once (getter-safe) and the default stays lazy. Also fix a latent #754 compiled bug it exposed: an assignment-destructuring value-type default over an ABSENT element produced NaN, because the lowered spill temps live inside an expression and so escaped the whole-body numeric-slot taint pass, getting an unboxed double slot that coerced the undefined sentinel. Flag them in VisitDestructuringAssign. #781 - an array-destructuring rest over a typed array / Buffer bound a typed array, not a fresh Array. Materialize typed arrays/buffers element-by-element into a SharpTSArray in Interpreter.NormalizeArrayDestructureSource (they are not GetIterableElements-iterable, so they cannot route through it). Interpreter-only; compiled typed-array construction is blocked by #782. #780 - the object-literal parser rejected the cover-grammar `{ a = 5 }`. Accept it (stored as `{ a: (a = 5) }`) so it round-trips to the #754 assignment- destructuring lowering; an IsShorthandDefault flag on Expr.Property keeps a pure-expression `{ a = 5 }` a type error (TS1312), matching tsc. #779 - a nested pattern WITH a default in an assignment destructuring (`[[a] = []]`, `{p: {x} = {}}`) was rejected. DestructuringAssign now retains the un-lowered (RawTarget, RawDefault); the outer pattern walk re-lowers the inner pattern against the defaulted access. #753 (string rest -> array) was already fixed in main by PR #785; verified and covered by tests here. Adds 14 destructuring test cases (both modes where applicable). Representative compiled program passes --verify. Filed #796 (object destructuring with a default over a source lacking the property reports a spurious "Property does not exist" - pre-existing, shared root cause with #783). #783 left open with findings; its tuple-inference fix did not reach the headline nested case and was reverted.
f996dfa to
b7e8f8b
Compare
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.
Completes a cluster of array/object destructuring conformance gaps. Both interpreter and compiled modes; a representative compiled program passes
--verify. Rebased onto currentmain(the build break that #769×#786 introduced was already repaired onmainby 3564041, so no build-fix is included here).Fixes
#784 — defaults apply on
nullinstead ofundefined-onlyAll six destructuring desugaring sites used
access ?? default(Expr.NullishCoalescing), which also triggers onnull. Replaced with a sharedDefaultIfUndefinedhelper —v = access; v === undefined ? default : v— that spills the access so it is read exactly once (getter-safe) while keeping the default lazy. Reuses existing nodes, so no new emitter/visitor surface.Also fixes a latent #754 compiled bug this exposed: an assignment-destructuring value-type default over an absent element (
[c = 5] = arr,({z: d = 5} = {})) producedNaN. The lowered spill temps live inside anExpr.DestructuringAssignexpression, so they escaped the whole-body numeric-slot taint pass and got an unboxeddoubleslot that coerced the runtimeundefinedsentinel. Flagged inVisitDestructuringAssign.#781 — typed-array rest binds a typed array (interpreter)
const [a, ...rest] = new Uint8Array([1,2,3])bound aUint8Arrayslice (Array.isArray(rest) === false).NormalizeArrayDestructureSourcenow materializes typed arrays/buffers into a freshSharpTSArray(they expose index access but no[Symbol.iterator]in this runtime, so they cannot route throughGetIterableElements). Compiled mode is blocked by #782 (typed-array construction).#780 — object shorthand-with-default
{a = 5}unparsedThe object-literal parser rejected the cover grammar. Now accepted (stored as
{ a: (a = 5) }) so it round-trips to the #754 assignment-destructuring lowering. AnIsShorthandDefaultflag onExpr.Propertykeeps a pure-expression{a = 5}a type error (TS1312), matching tsc, while{a: x = 5}stays valid.#779 — nested pattern with a default in assignment destructuring
[[a] = []] = [[1]]/({p: {x} = {}} = ...)were a parse error.Expr.DestructuringAssignnow retains the un-lowered(RawTarget, RawDefault); the outer pattern walk re-lowers the inner pattern against the defaulted access.#753 — string rest → array
Already fixed in
mainby #785; verified in both modes and covered by tests.Tests
14 new destructuring cases (both modes where applicable): undefined-only defaults (declaration + assignment), value-type default over absent (the compiled
NaNguard), laziness + single-evaluation, typed-array rest, object shorthand-default, the pure-expression cover-grammar error, and nested array/object patterns with defaults.Follow-ups filed
{a = 5}is rejected by the object-literal parser (blocks that form of assignment destructuring) #780/Assignment destructuring: nested pattern WITH a default ([[a] = []]) is unsupported #779). Same "binding-pattern contextual typing" root cause as Nested destructuring over a mixed (non-tuple) array literal fails type-checking (const [[m], n] = [[7], 8]) #783.const [[m], n] = [[7], 8]) #783 — left open with findings: a tuple-inference attempt fixed the leaf case but not the headline nested case (the inferred tuple is lost on the synthetic temp) and changed over-destructure behavior, so it was reverted.