-
-
Notifications
You must be signed in to change notification settings - Fork 560
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
The toString() of 'class' and 'function' return SourceText #1726
base: main
Are you sure you want to change the base?
Conversation
@lahma I just tested the branch and while there is still room for improvement as mentioned in by scgm0, this is already a great improvement over the current behaviour. Can we rebase the branch and merge it, or is there something blocking that? |
See the build status. |
sorry, took another look into the failed tests, all but the ones (90) testing for the native function toString() could be fixed by modifying the Regex used but I don't know how to fix these without Esprima returning the correct function name in the first place. |
@lahma Should we skip related tests? Or should we wait for Esprima to update? Does Esprima have any relevant update plans? |
I think skipping the 90 tests would be reasonable as these cover only function toString() which is wastly improved in this PR. |
This is a test code. I can change it anytime. |
How about now? |
Changing just the jint no longer made the results more correct, so I updated Test262Harness.settings.json to skip those 90 toString tests |
I wonder whether we wait for Acornima with this one, as it should provide the information we need from the quick look I took - https://github.com/adams85/acornima |
|
AST to JS was implemented in Acornima today though there are still some rough edges from my testing. |
That fast? |
@@ -359,6 +364,10 @@ public ClassStaticBlockFunction(StaticBlock staticBlock) : base(Nodes.StaticBloc | |||
{ | |||
var methodDef = method.DefineMethod(obj); | |||
methodDef.Closure.SetFunctionName(methodDef.Key); | |||
// TODO currently in the SourceText retrieved from Esprima, the method name is incorrect, so for now, use a string replacement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it make more sense to fix the wrong name on Esprima side?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I don't know how to fix it in Esprima (
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of example test cases. You would just need to check the produced AST and that the identifier is correct. Minimal test case helps.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried it, and after debugging for a while, I gave up. Maybe you can take a look? I'll try it again later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally have a lot more free time for OSS if someone takes care of my child and cleans the house.
Chiming in with some additional thoughts, hope you don't mind. In my opinion this (i.e. utilizing the AST to JS source gen feature of the parser) is not the right way to solve this problem. Neither Esprima, nor Acornima is able to reproduce the exact source text for reasons thoroughly discussed here. Instead of the source gen way, I'd suggest a simpler one that neither needs more support from the parser side, nor ugly hacks on the runtime side: Jint just needs to keep around the original script/module code that was parsed. Then, when you need the source text of a function or class, you can get that as a slice of the script/module code, based on the The tricky part is where to store the original script/module code so it can be accessed wherever needed. At first glance, something like What's even worse, let's consider a script like this: So, I can't really see a better way than using the But @lahma might have an even better idea on storing this piece of information. |
In fact, the method of intercepting the original text cannot pass the |
I'm not sure I follow you... So, are you saying that there are some tests which require the original source text of the function to be regenerated/reformatted? Can you show me such a test? |
|
Oh ok, I see now what you are getting at. Apparently, functions not parsed directly but created dynamically via the (async () => {
async function f() {}
var AsyncFunction = f.constructor;
var p1 = "a", p2 = "/*a */ b, c";
var g = /* before */AsyncFunction(p1, p2, "return Promise.resolve(a+b+c) /* d */ //")/* after */;
console.log(g.toString());
console.log(await g(1, 2, 3));
})() If you want to verify that there is indeed a simple string concatenation under the hood (at least in V8 and Firefox), run this: (async () => {
async function f() {}
var AsyncFunction = f.constructor;
var p1 = "a //", p2 = "/*a */ b, c";
var g = /* before */AsyncFunction(p1, p2, "return Promise.resolve(a+b+c) /* d */ //")/* after */;
console.log(g.toString());
console.log(await g(1, 2, 3));
})() |
As far as I can tell, a template like this is used to generate the function source text: `${isPrototypeAsync ? "async " : ""}function anonymous(${[...arguments].slice(0, arguments.length -1).join(",")}
) {
${arguments[arguments.length -1]}
}` Probably generator functions are also supported, so it may be a bit more complicated than this. EDIT: looks like this is already implemented here. |
I noticed that the previous reason for returning native code was that Esprima didn't support it (in the ToString comment for Function), but I found that Esprima now supports returning SourceText, so wanted to align with the behaviour of the mainstream js engines.
Unfortunately, passing the Test262 test still requires waiting for Esprima to refine the functionality, but that's outside the scope of this pr and beyond my capabilities (
(I accidentally closed the old pr earlier and reset my repository, so I'm re-proposing it now...)