Skip to content

fix: #776 — implicit-return functions now produce undefined, not 0#786

Merged
TheHypnoo merged 2 commits into
mainfrom
fix/issue-776-implicit-return-undefined
May 15, 2026
Merged

fix: #776 — implicit-return functions now produce undefined, not 0#786
TheHypnoo merged 2 commits into
mainfrom
fix/issue-776-implicit-return-undefined

Conversation

@TheHypnoo
Copy link
Copy Markdown
Contributor

Summary

  • Fixes Function-expression implicit return leaves numeric sentinel in return slot instead of undefined #776. Functions that fall off the end without an explicit return were emitting ret double 0.0 in LLVM IR. In Perry's NaN-boxing scheme, 0.0 is the number 0, not undefined (TAG_UNDEFINED = 0x7FFC_0000_0000_0001). User code that did f() === undefined, typeof f(), or console.log(f()) against an implicit-return function got false / "number" / 0 instead of the JS-correct true / "undefined" / undefined.
  • Fixed in every implicit-return / bare-return; site: regular functions, closures, methods, static methods (sync + async). Async paths also now resolve the promise with undefined, not 0.
  • Tightened the class-decorator return-value check from typeof ret === "function" to ret !== undefined, removed the workaround comment, and updated the error message. The previous narrow check only caught function/class replacements; primitive or object returns were silently discarded.

Test plan

  • function bare() {} ; console.log(bare() === undefined, typeof bare(), bare())true undefined undefined
  • @Injectable (no-return decorator) still works
  • @ReturnsFn / @ReturnsObj decorators now throw TypeError
  • Workspace test suite passes
  • Parity: 333/360 (+2 vs main baseline at 331)

TheHypnoo added 2 commits May 15, 2026 10:02
A function that falls off the end without an explicit `return` was
emitting `ret double 0.0`, which under NaN-boxing is the number 0 —
not `undefined` (TAG_UNDEFINED = 0x7FFC_0000_0000_0001). Code like
`f() === undefined` or `typeof f()` therefore disagreed with JS
semantics.

Replace every implicit-return / bare-`return;` site with the NaN-boxed
TAG_UNDEFINED literal (sync + async, regular functions, closures,
methods, static methods). Async epilogues also resolve the promise
with `undefined` instead of `0`.

With the bug fixed, the class-decorator return-value guard added in
PR #754 can be tightened from `typeof ret === "function"` to
`ret !== undefined`, catching primitive and plain-object replacement
returns as well. Workaround comment dropped, error message generalized,
parity expectation updated to match.
@TheHypnoo TheHypnoo merged commit fff3f8f into main May 15, 2026
9 checks passed
@TheHypnoo TheHypnoo deleted the fix/issue-776-implicit-return-undefined branch May 15, 2026 09:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Function-expression implicit return leaves numeric sentinel in return slot instead of undefined

1 participant