Skip to content

Fix native Function.prototype.toString() format to match V8/Node.js - #155

Merged
robobun merged 1 commit into
oven-sh:mainfrom
robobun:claude/fix-native-function-tostring-format
Feb 2, 2026
Merged

Fix native Function.prototype.toString() format to match V8/Node.js#155
robobun merged 1 commit into
oven-sh:mainfrom
robobun:claude/fix-native-function-tostring-format

Conversation

@robobun

@robobun robobun commented Feb 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fix native function toString() representation to use single-line format matching V8/Node.js

Details

Change the native function toString representation from:

function Function() {
    [native code]
}

to:

function Function() { [native code] }

This matches the format used by V8/Node.js and ensures compatibility with packages that depend on the specific output format of toString() for native functions.

Test plan

  • Run function fn() {}; console.log(fn.constructor.toString());
  • Expected: function Function() { [native code] }

Fixes oven-sh/bun#26698

🤖 Generated with Claude Code

Change the native function toString representation from:
  function Function() {
      [native code]
  }
to:
  function Function() { [native code] }

This matches the format used by V8 and ensures compatibility with packages
that depend on the specific output format of toString() for native functions.

Fixes oven-sh/bun#26698

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@robobun
robobun merged commit 8ab210b into oven-sh:main Feb 2, 2026
27 checks passed
@coderabbitai

coderabbitai Bot commented Feb 2, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

Walkthrough

Modified the native code representation in FunctionPrototype::functionProtoFuncToString to format the output as a single-line string instead of a multi-line format. The change affects how toString() is called on native functions and callable objects.

Changes

Cohort / File(s) Summary
Native Function String Formatting
Source/JavaScriptCore/runtime/FunctionPrototype.cpp
Updated the native code representation in functionProtoFuncToString from multi-line format "() {\n [native code]\n}" to compact single-line format "() { [native code] }" for InternalFunction and callable objects.

Comment @coderabbitai help to get the list of available commands and usage tips.

robobun added a commit to oven-sh/bun that referenced this pull request Sep 1, 2026
oven-sh/WebKit#545 completes oven-sh/WebKit#155. NativeExecutable,
builtin functions written in JavaScript, bound functions and remote
functions now print `function name() { [native code] }`, the same
one-line shape as InternalFunction constructors and V8. lodash's
isNative() builds a RegExp from hasOwnProperty's source and tests Map
against it. With one shape the RegExp matches, so cloneDeep, memoize,
uniq and isEqual use a native Map instead of a linear-scan ListCache
under Bun. cloneDeep of 8 000 objects: 1 971 ms before, linear after.

The pin moves from the oven-sh/WebKit#541 preview to the fork's main at
01de4c1d, which also carries oven-sh/WebKit#529, #542 and #543. #543
moved the dynamic-import TLA deadlock check into the engine and removed
JSModuleLoader::asyncEvaluationOrderForKey and the referrerAsyncOrder
parameter of JSC::importModule, so moduleLoaderImportModule no longer
computes or passes it.

Tests: test/js/bun/jsc/function-prototype-tostring.test.ts and the
oven-sh/WebKit#545 stress file as a jsc-stress fixture. Both fail on
Bun 1.4.1.
pull Bot pushed a commit to coleleavitt/WebKit that referenced this pull request Sep 1, 2026
oven-sh#155 changed the InternalFunction and callable-object branches of
Function.prototype.toString to the V8 shape:

    function Map() { [native code] }

Host functions (NativeExecutable::toStringSlow), builtin functions
written in JavaScript (FunctionExecutable::toStringSlow), bound
functions and remote functions (JSFunction::toString) still printed the
old three-line shape:

    function hasOwnProperty() {
        [native code]
    }

lodash's isNative() builds a RegExp from the source of
Object.prototype.hasOwnProperty and tests Map, Set, WeakMap, DataView
and Promise against it. With two shapes in one engine, the RegExp did
not match, lodash decided Map was not native, and MapCache and Stack
fell back to ListCache, a linear scan. cloneDeep, memoize, uniq and
isEqual became quadratic under Bun. json-schema-to-typescript measured
cloneDeep of a 10 000 definition schema at 11 s under Bun and 76 ms
under node (bcherny/json-schema-to-typescript#871).

This changes the remaining four sites to the one-line shape, so all
native functions print the same way, and updates the inspector's
native-getter sniff and the testapi.mm expectation to match.

JSTests/stress/function-toString-native-one-line.js pins the shape for
each kind of function, re-runs lodash's RegExp, and walks the global
object to check that no native function prints on more than one line.
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.constructor.toString() is not compliant with V8 runtime

1 participant