Repository navigation
fix(hir): built-in function .name own-property (#2144) - #2185
Merged
Merged
Conversation
A built-in function's `name` own-property read back `undefined`, and `Object.getOwnPropertyDescriptor(Promise.race, "name")` returned undefined too. Built-in constructors (`TypeError`, `Promise`, `Array`, …) and the static functions on built-in namespaces / constructors (`Math.min`, `Promise.race`, `Array.isArray`, …) are not represented as named closure values in Perry — bare reads of them produce the `globalThis` lookup's `0` / undefined sentinel, so `.name` on the result follows suit. Follow-up to #2075 (#2059), which only covered user-defined function declarations and expressions. `assert.throws` reports `expectedErrorConstructor.name` to label thrown errors (so every built-in `Error` constructor showed as `undefined` instead of `TypeError`/`RangeError`/etc.) and Test262's `built-ins/Function` sample is dominated by `Cannot read … (reading 'name')` once the sibling "built-in proto methods are undefined" gap lands. - `analysis::is_builtin_static_function_member`: spec-defined static function members of built-in namespaces / constructors. Function-typed members only — numeric constants like `Math.PI` stay unfolded so `(Math.PI).name` keeps producing `undefined` (matching Node). - `lower/expr_member`: `<BuiltinCtor>.name` and `<BuiltinNs>.<staticFn>.name` fold to `Expr::String`. Gated on the *lowered* receiver matching `GlobalGet(0)` / `PropertyGet { GlobalGet(0), … }`, so a locally-shadowed `const Math = …` lowers to a `LocalGet` and bypasses the fold. - `lower/expr_call/native_module` (`Object.getOwnPropertyDescriptor` arm): `…(<BuiltinFn>, "name")` folds to the spec-compliant data descriptor object literal `{ value, writable:false, enumerable:false, configurable:true }`. Same lowered-receiver gate as the `.name` fold. - `lower/expr_call/name_fold` (new): AST recognizer + descriptor builder shared by both fold sites. Parity test test-parity/node-suite/object/builtin-function-name.ts is byte-identical to `node --experimental-strip-types`. The existing #2075 `function-name-descriptor.ts` parity test still passes. perry-hir lib tests: 111/111. Surfaced by the #799 Test262 radar re-harvest (built-ins/Function ~16% — 38× `Cannot read … (reading 'name')`). Part of #793.
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.
Summary
Built-in functions'
.nameown-property read backundefined.Promise.race.name,Math.min.name,Array.isArray.name, and built-in error constructors (TypeError.name, …) all returned0/undefinedwhere the spec definesnameas{ value, writable:false, enumerable:false, configurable:true }. Follow-up to #2075 (which covered user-defined functions only).Built-in constructors and namespace static functions in Perry aren't represented as named closure values — bare reads of them produce the
globalThislookup's sentinel, so.nameon the result follows suit.assert.throwsconsequently reported the expected error constructor asundefinedinstead ofTypeError/RangeError/etc., and Test262'sbuilt-ins/Functionsample is dominated byCannot read … (reading 'name').Fix
HIR-level constant fold in
lower/expr_member.rsandlower/expr_call/native_module.rs:<BuiltinCtor>.name→Expr::String("<Ctor>")<BuiltinNs>.<staticFn>.name→Expr::String("<fn>")(gated on a known spec-defined function table — numeric constants likeMath.PI.namestay unfolded)Object.getOwnPropertyDescriptor(<BuiltinFn>, "name")→ the spec-compliant data descriptor object literalBoth fold sites gate on the lowered receiver matching
GlobalGet(0)/PropertyGet { GlobalGet(0), … }, so a locally-shadowedconst Math = …lowers to aLocalGetand correctly bypasses the fold.Test plan
test-parity/node-suite/object/builtin-function-name.tsbyte-identical tonode --experimental-strip-typestest-parity/node-suite/object/function-name-descriptor.ts(fix(runtime): function.nameown-property + getOwnPropertyDescriptor on functions (#2059) #2075) still byte-identical (no regression)cargo test --release -p perry-hir --lib— 111/111 passcargo fmt --all -- --checkcleanSurfaced by the #799 Test262 radar re-harvest. Part of #793.