-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Make eval("arguments") work inside of lambdas. #1463
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
Conversation
|
Hi @jordonwii, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
TTYL, MSBOT; |
| See Github issue #1209 for more. | ||
| */ | ||
| AddVarsToScope(pnodeScope->sxFnc.pnodeVars, byteCodeGenerator); |
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.
These symbols have to be added to the body scope. Does that not mean that the call has to happen where it currently happens, after we've begun processing the body scope?
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.
This works because AddVarsToScope explicitly adds vars to the current function's body scope. It uses ByteCodeGenerator::AddSymbolToFunctionScope, which in turn calls ByteCodeGenerator:AddSymbolToScope with scope = currentScope->GetFunc()->GetBodyScope().
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.
The real problem, I think, is that the processing of the arguments symbol is still being handled by a method that's specific to the body scope. How about if we move that logic to the processing of the param scope?
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.
Good question. I don't have a solid answer to that. If you're referring to the setting of argumentsSymbol inside of AddVarsToScope, my thinking would be that we set it there because that already has to do a pass over all of the variables in the body scope, and doing it elsewhere would mean doing two passes. In the more common case where we don't have a split scope, we don't do any param scope processing logic, so we can't only set it there.
@ianwjhalliday thoughts?
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.
We can restructure things so that two passes are not necessary, i.e., make the arguments symbol available without searching the body scope vars to find it. Going forward, we're going to create real symbols for this, super, and new.target to staunch the trickle of special-casey bugs involving those constructs, so whatever we invent to allow easy processing of "arguments" in the param scope will work for those other symbols as well.
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.
And indeed @aneeshdk and I discussed making the arguments symbol a normal symbol instead of a special case, to remove a lot of this extra work. After some code review and discussion we concluded that there is no reason to have a specially handled arguments symbol and it should just work if we make it a normal symbol (with some special care to ensure it is available regardless whether the user script declared it or not).
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.
Out of scope for this PR of course.
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 am in favor of jiggering this code however needed to make it work for this PR.
Then we should very soon go and make the arguments symbol not a special case.
|
It turns out that in my first push of the test, I mistakenly included an eval call inside of the new test's body (in |
|
I can't seem to reproduce either the test failure or the assertion failure outside of running Edit: The bug happens when the function containing a lambda with It looks like there's another "uses arguments" related flag the JIT'd function body ( |
|
Contacted @jordonwii to follow up on this PR. He is planning to continue work on this PR once he has the time. I'll keep in touch with him. |
Conflicts: lib/Runtime/ByteCode/ByteCodeGenerator.cpp test/es6/default-splitscope.js
…e1209 Conflicts: lib/Runtime/ByteCode/ByteCodeGenerator.cpp test/es6/default-splitscope.js
|
Progress, at last. :) It looks like the errors I mentioned in my last comment were the result of the jit trying to inline the outer function, when it shouldn't have been able to because the inner Lambda used eval. The code added in these last few commits fixes that by marking the outer function arguments object as referenceable. I haven't figured out how to verify that this isn't over compensating somehow, but right now it appears to work. If this looks good, I'll flatten the commits tonight and add a couple comments, especially to the tests. |
| { | ||
| name: "eval('arguments') works correctly within lambdas", | ||
| body: function () { | ||
| var arguments = 'not arguments object'; |
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.
To clarify this, should each instance of arguments in this line bind to the var called arguments or to an actual arguments object?
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.
Both should refer to the variable ('not an arguments object'). The var arguments line shadows the default arguments object, so both the first param to areEqual and the arguments inside the lambda should refer to that.
|
Hey @jordonwii - just checking in if you'd like to continue work on this PR |
|
@pleath: I contacted @jordonwii offline to discuss this PR and he said he was under the impression that this PR would be superceded by other refactoring work or another change. Is that the case? If so (regardless of whether that work is in progress or not), we should close this PR. |
|
Per offline discussion with @pleath I'm closing this PR. |
Fixes #1209
This is fairly close to the solution @aneeshdk @ianwjhalliday and I discussed. There's one minor difference: in order for the new location of
AddVarsToScopeto be as clear as possible, we planned to move it above all of the paramScope code. Sadly, the call thepushScope(paramScope)needs to happen prior toAddVarsToScopeto avoid an assertion failure in ByteCodeGenerator.cpp:1659 due tocurrentScopenot being updated.I couldn't come up with a less repetitive way to test this than to just copy/paste the bulk of the "
argumentsin lambdas" test, and replace the use ofargumentswitheval("arguments"). Definitely open to suggestions here.