ecma262 icon indicating copy to clipboard operation
ecma262 copied to clipboard

Editorial: Specify _prefix_ for non-specific uses of CreateBuiltinFunction

Open gibson042 opened this issue 3 years ago • 13 comments
trafficstars

CreateIntrinsics fails to specify the value of prefix in its calls to CreateBuiltinFunction, and early text in ECMAScript Standard Built-in Objects incorrectly suggests that the name parameter is always the initial value of the "name" property (which is not the case when "name" is something like "[Symbol.iterator]"). This PR corrects those issues and attempts to improve text of the latter section.

gibson042 avatar Jul 20 '22 22:07 gibson042

One problem that this PR doesn't fix is that "the name [that is] given to the function in this specification" is ambiguous. E.g., if the header says String.fromCharCode ( ...codeUnits ) and the preamble says The String.fromCharCode function may be called ..., then I don't think it's ridiculous to at least wonder if String.fromCharCode is "the name given to the function", and thus the value of the name property.

Or consider that sometimes the specification gives more than one name to a function. E.g. Set.prototype.keys and Set.prototype.values are two names given to a single function. One can guess that the name comes from the section that defines the function's algorithm, rather than from the section that merely refers to the function, but the spec doesn't actually say.

jmdyck avatar Jul 21 '22 00:07 jmdyck

For the former, more formalism would be good, but i don’t think anyones actually implemented the wrong thing there.

For the latter, the spec does explicitly say - one defers to the real one from whence the name comes.

ljharb avatar Jul 21 '22 00:07 ljharb

For the latter, the spec does explicitly say - one defers to the real one from whence the name comes.

Explicitly, the Set.prototype.keys section says that the value of the keys property is a function defined elsewhere. But it doesn't explicitly say that that other section is what determines the name of that function. It's a reasonable way to resolve the ambiguity, and maybe nobody has implemented the wrong thing here either. I'm just saying the spec could be clearer.

jmdyck avatar Jul 21 '22 01:07 jmdyck

Also, just stylistically, I think this:

Where not explicitly specified, it is implicitly copied from the name given to the function in this specification or from the property name of the property of a built-in object for which it is defined as the value or a get or set accessor function (whichever is applicable).

is putting too much stuff into a single sentence. I think I'd prefer to see it broken out into multiple sentences, maybe bullet points, maybe with examples. Possibly combined with the case analysis of the subsequent paragraph (though I haven't thought too much about what that would look like).

jmdyck avatar Jul 21 '22 01:07 jmdyck

Explicitly, the Set.prototype.keys section says that the value of the keys property is a function defined elsewhere. But it doesn't explicitly say that that other section is what determines the name of that function. It's a reasonable way to resolve the ambiguity, and maybe nobody has implemented the wrong thing here either. I'm just saying the spec could be clearer.

Yes, it does - the name is determined by where the function is defined; https://tc39.es/ecma262/#sec-set.prototype.keys says it's defined here, and that function's name is "values".

ljharb avatar Jul 21 '22 03:07 ljharb

I have removed "the name [that is] given to the function in this specification" (which is not necessary because every function is either anonymous or associated with a property name, e.g. "eval" for eval and "fromCharCode" for String.fromCharCode), reworded the implicit naming text, and replaced the CreateBuiltinFunction name and prefix prose with a list of rules.

gibson042 avatar Jul 21 '22 14:07 gibson042

the name is determined by where the function is defined;

That's a reasonable assumption, but the spec doesn't actually say that. (It could say that, or something like it.)

https://tc39.es/ecma262/#sec-set.prototype.keys says it's defined here, and that function's name is "values".

That would certainly be true if there were an explicit sentence saying:

The initial value of the name property of this function is "values".

but there isn't.

To ascertain that value, it comes back to this one paragraph in clause 18, which is not set up to decide this case.

One sentence says:

Unless otherwise specified, this value is the name that is given to the function in this specification.

And I'm pointing out that, as far as that wording is concerned, the spec "gives" two different names to this function.

Another sentence says:

For functions that are specified as properties of objects, the name value is the property name string used to access the function.

which indicates that if a program accesses the function in question via Set.prototype.keys, the name value is "keys", whereas if it accesses it via Set.prototype.values, the name value is "values"!

Again, I'm not saying that there isn't a reasonable way to resolve this, I'm saying that the spec doesn't itself give wording that clearly decides the case.

jmdyck avatar Jul 21 '22 19:07 jmdyck

reworded the implicit naming text,

"the property name of the property for which the function is defined as the value"

This phrase fails the above Set.prototype.{values,keys} case: a single function is defined as the value of two properties with different names.

jmdyck avatar Jul 21 '22 19:07 jmdyck

@jmdyck Fixed with a constraint and explanatory note.

gibson042 avatar Jul 21 '22 20:07 gibson042

@jmdyck there is only one function definition - the other points to it. I really don't understand how any other interpretation could be made.

ljharb avatar Jul 21 '22 20:07 ljharb

@jmdyck Fixed with a constraint and explanatory note.

I appreciate the explanatory note. I think the preceding sentence is sufficient now, but it's still conveying a lot of ideas in a complex subordinate clause. One way to divide it into more digestible chunks would be a construction something like this:

If a built-in function is specified as anonymous, the value of the "name" property is the empty String. In all other cases, the value is determined by the section in which the built-in function is defined (i.e., where its [[Call]] semantics are specified). In that section, the function is (either explicitly or implicitly) defined to be the [[Value]], [[Get]], or [[Set]] attribute of a particular property of some object. The name of that property is also the value of the "name" property of the function.

(Or you could leave the other property out of it, and instead define the name in terms of the section header, but I think that might be worse.)

jmdyck avatar Jul 27 '22 01:07 jmdyck

@jmdyck there is only one function definition - the other points to it.

I'm not disputing either of those statements. I said as much 5 posts ago. We don't seem to be getting anywhere, so I'll stop trying.

jmdyck avatar Jul 27 '22 01:07 jmdyck

One way to divide it into more digestible chunks would be a construction something like this:

If a built-in function is specified as anonymous, the value of the "name" property is the empty String. In all other cases, the value is determined by the section in which the built-in function is defined (i.e., where its [[Call]] semantics are specified). In that section, the function is (either explicitly or implicitly) defined to be the [[Value]], [[Get]], or [[Set]] attribute of a particular property of some object. The name of that property is also the value of the "name" property of the function.

Thanks; I like this approach. The latest commit incorporates text derived from it.

gibson042 avatar Jul 27 '22 19:07 gibson042