Skip to content

Fix delete with optional chaining not actually deleting properties#4720

Open
Ansh-699 wants to merge 3 commits intoboa-dev:mainfrom
Ansh-699:fix/delete-optional-chaining
Open

Fix delete with optional chaining not actually deleting properties#4720
Ansh-699 wants to merge 3 commits intoboa-dev:mainfrom
Ansh-699:fix/delete-optional-chaining

Conversation

@Ansh-699
Copy link
Contributor

Description

delete with optional chaining (?.) returned true but did not actually delete the property.

Root Cause

Access::from_expression() has no arm for Expression::Optional, so the delete compilation falls to the else branch that just evaluates the expression and pushes true without emitting a delete opcode.

Fix

Added compile_optional_delete and compile_optional_delete_final methods in the bytecompiler (mod.rs). These walk the optional chain, compile intermediate accesses normally, and emit DeletePropertyByName/DeletePropertyByValue for the final chain item. A new Expression::Optional check in unary.rs routes delete compilation through this path.

Example (before fix)

let o = {a: {b: 1}};
delete o?.a.b; // returns true but o.a.b is still 1

Example (after fix)

let o = {a: {b: 1}};
delete o?.a.b; // returns true and o.a.b is undefined

Closes #4719

The `delete` operator with optional chaining (`?.`) was returning `true`
but not actually deleting the property. This happened because
`Access::from_expression()` has no arm for `Expression::Optional`, causing
the compiler to fall through to the else branch that just evaluates the
expression and pushes `true`.

Added a new `compile_optional_delete` method that walks the optional chain,
compiling intermediate accesses normally but emitting `DeletePropertyByName`
or `DeletePropertyByValue` for the final chain item.

Closes boa-dev#4719
@Ansh-699 Ansh-699 requested a review from a team as a code owner February 25, 2026 10:20
@github-actions
Copy link

github-actions bot commented Feb 25, 2026

Test262 conformance changes

Test result main count PR count difference
Total 52,862 52,862 0
Passed 49,505 49,497 -8
Ignored 2,261 2,261 0
Failed 1,096 1,104 +8
Panics 0 0 0
Conformance 93.65% 93.63% -0.02%
Fixed tests (1):
test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js (previously Ignored)
Broken tests (8):
test/built-ins/RegExp/prototype/exec/regexp-builtin-exec-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/replace/regexp-prototype-replace-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/matchAll/regexp-prototype-matchAll-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/search/regexp-prototype-search-v-u-flag.js (previously Passed)
test/built-ins/String/prototype/search/regexp-prototype-search-v-flag.js (previously Passed)
test/built-ins/String/prototype/match/regexp-prototype-match-v-u-flag.js (previously Passed)
test/staging/sm/RegExp/unicode-raw.js (previously Passed)
test/staging/sm/RegExp/unicode-class-raw.js (previously Passed)

Copy link
Member

@nekevss nekevss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking pretty good overall.

Can there be a few unit tests added to test the behavior of this PR.

@nekevss nekevss added bug Something isn't working waiting-on-author Waiting on PR changes from the author labels Feb 26, 2026
@codecov
Copy link

codecov bot commented Feb 26, 2026

Codecov Report

❌ Patch coverage is 87.27273% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.24%. Comparing base (6ddc2b4) to head (5496d5c).
⚠️ Report is 702 commits behind head on main.

Files with missing lines Patch % Lines
core/engine/src/bytecompiler/mod.rs 86.79% 7 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #4720       +/-   ##
===========================================
+ Coverage   47.24%   57.24%   +10.00%     
===========================================
  Files         476      552       +76     
  Lines       46892    60549    +13657     
===========================================
+ Hits        22154    34662    +12508     
- Misses      24738    25887     +1149     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Ansh-699
Copy link
Contributor Author

okie i'll add in a bit

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests look kinda good, but instead of asserting that the value is undefined I'd use Object.getOwnPropertyDescriptor to assert that the descriptor itself gets deleted. This ensures we're properly checking deletion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay

Assert that the property descriptor is fully removed rather than just
checking for undefined, as suggested in review.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working waiting-on-author Waiting on PR changes from the author

Projects

None yet

Development

Successfully merging this pull request may close these issues.

delete with optional chaining (?.) does not actually delete the property

3 participants