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

Fix function hoisting behaviour (non-strict mode) #1547

Open
wants to merge 6 commits into
base: static_h
Choose a base branch
from

Conversation

trossimel-sc
Copy link

Summary

Addresses #1455

Hermes currently has divergent function hoisting behavior compared to QuickJS, V8, and JSC in non-strict mode. The following code prints FAIL instead of SUCCESS

{
    function promotedFunction(endRecursion) {
        if(endRecursion) {
            promotedFunction(true);
            return;
        }
        print ('SUCCESS');
    }

    callback = promotedFunction;
}

{
    function promotedFunction(endRecursion) {
        if(endRecursion) {
            promotedFunction(true);
            return;
        }
        print ('FAIL');
    }
}

callback(false);

This happens as scoped function promoted to global scope are treated as global functions, like for var.
To fix this behaviour:

  • Two declarations are created for a promoted identifier instead of one: a global and a scoped declaration, stored in sideIdentifierDeclarationDecl_ and promotedFunctionDecls_
  • If the identifier is promoted, we call emitStore on both pointers associated to the declarations

Test Plan

  • Added a unit test with the failing code

Hermes currently has divergent function hoisting behavior compared to QuickJS, V8, and JSC in non-strict mode. The following code prints Error1; Error1 instead of Error; Error1

```
{
    function test1(a) {
        if(a == "a") {
            test1("b");
            return;
        }
        print ('Error');
    }

    callback1 = test1;
}

{
    function test1(a) {
        if(a == "a") {
            test1("b");
            return;
        }
        print ('Error1');
    }

    callback2 = test1;
}

callback1("a");
callback2("a");
```

This happens as scoped function promoted to global scope are treated as global function, like for `var`.
New approach:
- Creating two declaration associated with each promoted function identifier and storing the function code into two pointers, one global and one scoped. Each declaration has one pointer associated.
- Each identifier which is not a declaration is resolved into either the global or scoped declaration of the promoted function

Test 262 results:
- 100% on test/statements, 98.53% overall. **Nothing changed in the results** before and after the change.

---
@facebook-github-bot
Copy link
Contributor

Hi @trossimel-sc!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at [email protected]. Thanks!

@trossimel-sc
Copy link
Author

Seems like the failing errors are due to auto generated checks

@avp
Copy link
Contributor

avp commented Oct 24, 2024

@trossimel-sc The update-lit build target will update the tests that are autogenerated, then check-hermes to run them. LIT_FILTER will let you narrow down what exactly gets updated or run as well. Thanks for submitting this fix!

@tmikov
Copy link
Contributor

tmikov commented Nov 1, 2024

Hi, we really need the CLA before we can review it internally. Thanks!

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

Successfully merging this pull request may close these issues.

4 participants