You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Over at https://github.com/Swatinem/js-source-scopes I have been experimenting with extracting scopes, and their names from minified source; and re-mapping the individual name components using a sourcemaps names, with surprisingly great success.
We should make up our minds how we expect this inference to work.
This inference works differently in the rendered stack traces of various browsers, which is the primary use-case we are after.
The value of the "name" property is a String that is descriptive of the function. The name has no semantic significance but is typically a variable or property name that is used to refer to the function at its point of definition in ECMAScript code.
For named functions, this is trivial, but for anonymous functions, the spec defines a whole section on how the name should be inferred:
In particular the runtime semantics for NamedEvaluation is being "called" with the name as defined using various ambient syntax.
For example const a = () => {}; is clearly defined by the spec as the following:
LexicalBinding : BindingIdentifier Initializer
1. Let bindingId be StringValue of BindingIdentifier.
2. ...
3. If IsAnonymousFunctionDefinition(Initializer) is true, then
a. Let value be ? NamedEvaluation of Initializer with argument bindingId.
The final .name property of functions is evaluated at runtime and does support dynamic constructs like so:
$ a = "abc", b = {[a]: () => {}}, b.abc.name
> "abc"
Names for property Assignments
The spec only infers name from relatively simple constructs. Neither Firefox nor Chrome infer a name for this snippet:
$ a = {}, a.abc = () => {}, a.abc.name
> ""
Interesting though that at least the firefox devtools internally do infer the name, and the stacktrace even has the complete object path to the function:
My prototype infers the name from the complete expression the function was assigned to.
Class/Prototype/Constructors
Another interesting case is classes, constructors, and methods either on the class directly or on the prototype.
classX{staticy(){}z(){}}X.prototype.w=()=>{};
As before, the .name property for all of these is their name, except w for which it is empty.
However, when throwing an Error, the stack trace will say X.w in chrome/node, and X.prototype.w in Firefox for the method defined on the prototype, but just z in Firefox for the class method.
In stack traces, Chrome/Node will prefix this with the class name of that specific instance, not the name of the class defining the method if you use inheritance!
My personal intuition says that I would like to have the names X.y for the static function, and X.prototype.z for the instance function; as that is how you would refer to them via code.
Anonymous Callbacks
The most complicated case would be "completely" anonymous functions used as callbacks.
constmyCallback=useCallback(()=>{},[]);
Per spec, this function has no name itself. In stack traces, Chrome/Node do not infer a name at all. Firefox however lists all of the named scopes in which the callback is defined.
Options that we have in this case are:
Anonymous callback to useCallback.
Anonymous callback which results in myCallback.
The second option is very much specific to the use-case in React, as the framework returns a wrapper that is then being called. We can’t infer from pure syntax if that is the case, or if the callback is immediately invoked, such as with Array.prototype.map, in which case the first option would make more sense.
The text was updated successfully, but these errors were encountered:
Over at https://github.com/Swatinem/js-source-scopes I have been experimenting with extracting scopes, and their names from minified source; and re-mapping the individual name components using a sourcemaps
names
, with surprisingly great success.We should make up our minds how we expect this inference to work.
This inference works differently in the rendered stack traces of various browsers, which is the primary use-case we are after.
Discussion
Function instance name
The
Function instance name
is defined like this:For named functions, this is trivial, but for anonymous functions, the spec defines a whole section on how the name should be inferred:
In particular the runtime semantics for
NamedEvaluation
is being "called" with the name as defined using various ambient syntax.For example
const a = () => {};
is clearly defined by the spec as the following:The final
.name
property of functions is evaluated at runtime and does support dynamic constructs like so:Names for property Assignments
The spec only infers
name
from relatively simple constructs. Neither Firefox nor Chrome infer a name for this snippet:Interesting though that at least the firefox devtools internally do infer the name, and the stacktrace even has the complete object path to the function:
My prototype infers the name from the complete expression the function was assigned to.
Class/Prototype/Constructors
Another interesting case is classes, constructors, and methods either on the class directly or on the prototype.
As before, the
.name
property for all of these is their name, exceptw
for which it is empty.However, when throwing an Error, the stack trace will say
X.w
in chrome/node, andX.prototype.w
in Firefox for the method defined on the prototype, but justz
in Firefox for the class method.In stack traces, Chrome/Node will prefix this with the class name of that specific instance, not the name of the class defining the method if you use inheritance!
My personal intuition says that I would like to have the names
X.y
for the static function, andX.prototype.z
for the instance function; as that is how you would refer to them via code.Anonymous Callbacks
The most complicated case would be "completely" anonymous functions used as callbacks.
Per spec, this function has no name itself. In stack traces, Chrome/Node do not infer a name at all. Firefox however lists all of the named scopes in which the callback is defined.
Options that we have in this case are:
useCallback
.myCallback
.The second option is very much specific to the use-case in React, as the framework returns a wrapper that is then being called. We can’t infer from pure syntax if that is the case, or if the callback is immediately invoked, such as with
Array.prototype.map
, in which case the first option would make more sense.The text was updated successfully, but these errors were encountered: