ecma262
ecma262 copied to clipboard
Normative: Allow toString of a built-in function to output a computed property name
e.g., as output by XS:
$ eshost -se 'Proxy.revocable({}, {}).revoke.toString()'
#### ChakraCore, SpiderMonkey
function() {
[native code]
}
#### engine262, GraalJS, Hermes, V8
function () { [native code] }
#### JavaScriptCore
function () {
[native code]
}
#### Moddable XS
function [""] (){[native code]}
Does anyone but xs do this? This doesn't really seem to match the intention of toString reform, altho "it can't parse" certainly means it validates the letter.
It seems like perhaps a simpler approach is to add test262 tests to prohibit what xs is doing, assuming they're willing to change their behavior?
That's possible, but note that every major engine and most minor ones also output similar strings in certain scenarios (albeit not necessarily for built-in functions):
$ eshost -se '(function(){
const sym1 = Symbol("foo"), sym2 = Symbol("bar"), obj = { [sym1](){}, get [sym2](){} };
const m1 = obj[sym1], m2 = Object.getOwnPropertyDescriptor(obj, sym2).get;
return [m1, m2, m1.bind(), m2.bind()].map(
fn => `${fn} # => ${JSON.stringify(fn.name)}`.replace(/\s*([(){}])\s*/g, " $1 ").replace(/\s+/g, " ")
).join("\n");
})()'
#### ChakraCore
TypeError: No implicit conversion of Symbol to String
#### engine262, SpiderMonkey, V8
[sym1] ( ) { } # => "[foo]"
get [sym2] ( ) { } # => "get [bar]"
function ( ) { [native code] } # => "bound [foo]"
function ( ) { [native code] } # => "bound get [bar]"
#### JavaScriptCore
function ( ) { } # => "[foo]"
function ( ) { } # => "get [bar]"
function [foo] ( ) { [native code] } # => "bound [foo]"
function get [bar] ( ) { [native code] } # => "bound get [bar]"
#### Moddable XS
function ["[foo]"] ( ) { [native code] } # => "[foo]"
function ["get [bar]"] ( ) { [native code] } # => "get [bar]"
function ["bound [foo]"] ( ) { [native code] } # => "bound [foo]"
function ["bound get [bar]"] ( ) { [native code] } # => "bound get [bar]"
The title of this PR is misleading. Computed property names are already allowed in Function.prototype.toString output. The grammar changes here are simply a refactoring. Can you update the title to describe the actual normative requirement change?
The title of this PR is misleading. Computed property names are already allowed in Function.prototype.toString output. The grammar changes here are simply a refactoring. Can you update the title to describe the actual normative requirement change?
The current output for built-in functions (with a String-valued [[InitialName]]) is constrained by "the portion of the returned String that would be matched by |NativeFunctionAccessor?| |PropertyName| must be the value of func.[[InitialName]]" (emphasis mine), which does not permit a computed property name because String contents like [""] do not match the value of "" (even though they are grammatically permitted by |NativeFunction|).
So I believe that the title already describes this normative change, although I'm open to alternative suggestions.
I don't like the strategy of parsing and evaluating the property name here, especially if all of PropertyName is allowed, which potentially includes arbitrary expressions. If we're introducing a new AO anyway, just change NativeFunctionName to permit a subset of the PropertyName grammar and introduce an SDO that extracts the name from that. If it's not clear what I mean, we can get on a call or you can join the weekly editor call.
@gibson042 separate from the mechanism of doing the change, can you elaborate on why this is desirable?
separate from the mechanism of doing the change, can you elaborate on why this is desirable?
There are editorial aspects which are important to make the current text actually coherent (which I will split out into a separate PR: #2828), and normative aspects relating to consistency of valid output from Function.prototype.toString(callableWithoutASourceTextSlot)... right now the output for a built-in function is much more constrained than the output for other such callables such as proxies and/or bound versions of accessor and/or symbol-named functions (cf. https://github.com/tc39/ecma262/pull/2695#issuecomment-1069648775 ) in that the [[InitialName]] requirement (seems to) preclude a computed name, but not so constrained that it is actually deterministic (in that the presence and form of whitespace is unspecified).
But if there is implementer appetite for tackling this in the other direction (making Function.prototype.toString output for built-in and/or other non-[[SourceText]] callables more deterministic), I would be happy to abandon this PR in favor of such a replacement.
@gibson042 See related: https://github.com/tc39/Function-prototype-toString-revision/issues/21#issuecomment-269954023
Right. That issue was never resolved, and it's not clear to me how it would be without implementer commitment to align.
Per the July 2022 TC39 meeting, this should be replaced with https://github.com/tc39/proposal-stricter-function-tostring .