Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function.prototype.toString() #76

Open
xorgy opened this issue May 17, 2019 · 12 comments
Open

Function.prototype.toString() #76

xorgy opened this issue May 17, 2019 · 12 comments

Comments

@xorgy
Copy link

xorgy commented May 17, 2019

It seems unnecessary to me that Function.prototype.toString() returns a useless placeholder token (like it does with native functions). For native functions it is fair enough, and the ECMAScript standard reflects this; but the code in this case is JavaScript, even if it's in AST form, so it seems like it would be better to more closely follow the behaviour of real JavaScript. Furthermore, there is at least some code which relies on Function.prototype.toString(), whether you feel that's a prudent idea or not.

How much trouble would it be to have Function.prototype.toString() lazily emit a valid (or standard) JavaScript source representation of the binary AST instead?

@myshov
Copy link

myshov commented May 18, 2019

Yes I agree with @xorgy. There was usage of Function.prototype.toString() at least in the first version of Angular for implementation of dependency injection.

@ExE-Boss
Copy link

ExE-Boss commented May 19, 2019

You could always display the arguments, eg.: example toString() result:

function example(foo, bar) {
	[sourceless code]
}

That would avoid breaking the old Angular dependency injection.

@xorgy
Copy link
Author

xorgy commented May 24, 2019

@ExE-Boss That's an interesting middle ground, though I'm not sure it's quite right either, makes it necessary to use a regex to tell that the code isn't real, though I guess not all that many people are going to be accidentally evaling some garbage they got from Function.prototype.toString().

@ExE-Boss
Copy link

makes it necessary to use a regex to tell that the code isn't real

You already need to do that with native functions, where the result is slightly different between browsers: tc39/Function-prototype-toString-revision#21.

Also, the ESNext native function toString() method will optionally be returning function parameters.

@vdjeric
Copy link
Collaborator

vdjeric commented May 24, 2019

It seems unnecessary to me that Function.prototype.toString() returns a useless placeholder token [...] there is at least some code which relies on Function.prototype.toString()

You are right and we want toString() in BinAST to work the same way as it does for plain JS but it's just a matter of implementation priorities. Right now we're working on a new file format for BinAST and decoder performance so we've shelved toString() for the timebeing.

@xorgy
Copy link
Author

xorgy commented May 29, 2019

@vdjeric Fair enough, though I suspect regardless of what BinAST looks like, it is not likely to be difficult for implementers to write some sort of toString, especially the sort that @ExE-Boss is describing (since there's not much that can be done to collapse arguments, especially with object destructuring, so presumably names will be intact).

As long as a slightly more useful Function.prototype.toString is not off the table, I'm happy. :- )

@fabiosantoscode
Copy link

One of the things that make JavaScript great is the fact you can eval() most functions' string representations (plus a pair of parentheses) and get a function back. This is not recommended, but is still great for a lot of reasons:

  • You can inline a function into a data: URL (which is useful, for say, creating a Worker on-demand)
  • You can read arguments and comments as said above and perform actions based upon the results

And probably more things I can't remember right now.

IMO the VM should generate a string representation from its internal AST, on-demand, when the toString method is called.

@rossberg
Copy link
Member

@fabiosantoscode:

  • You can inline a function into a data: URL

That's a bug, not a feature. Unless you want to help attackers.

@fabiosantoscode
Copy link

@rossberg not like a security issue, more like this:

const worker = new Worker('data:text/javascript,(' + () => {
  /* worker code goes here... */
} + ')()')

In this example, it helps you define a worker next to the place it's going to be used and not in a new file. There's probably more interesting things you can do with data-urls and toString. I can't see how this is a bug.

@fabiosantoscode
Copy link

Also, I can't overstate how many times I use Function.prototype.toString to read the source code of some unknown callback in the browser console or the node console.

@guybedford
Copy link

guybedford commented Jun 24, 2019 via email

@C-Ezra-M
Copy link

C-Ezra-M commented Jan 2, 2023

If there is need to have Function.prototype.toString() compatible with eval(), it would be best for comments to not be saved in the AST, because they are not executed.

Python has AST-relevant public APIs built into the standard library as the ast module, and it's evident that the Python AST parser doesn't save comments (Python uses # to denote them):

import ast

print(ast.unparse(ast.parse("""def a():
    # does stuff
    return 0""")))

which outputs:

def a():
    return 0

The comment isn't there because it's not necessary for the function to work. Docstrings are preserved, though.

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

No branches or pull requests

8 participants