Skip to content

[VM] 'With' and 'jump outside' don't play well together #111

@czukowski

Description

@czukowski

I know 'with' is not supported in the old translator, but it seems to be implemented in the VM (that's also one of the reasons I'm trying it out), and it also seems to work most of the time so far, but I encountered an issue that I can't figure out, unfortunately:

This code runs well:

        var foo = {bar: function() {}};
        with(foo) {
          bar();
        }

But this one does not and it throws JsException: TypeError: undefined or null can't be converted to object:

        var foo = {bar: function() {}};
        with(foo) {
          if (true) {
            bar();
          }
        }

I've only been able to figure out that in the 1st case the eval function of WITH is called once, and in the 2nd one it is called twice with undefined at the top of the stack in the 2nd call.

By uncommenting a line I've found in _execute_fragment_under_context function that prints the opcodes, I can see a difference in execution:

For the code that runs well:

14 LOAD_UNDEFINED()
15 POP()
16 LOAD(u'bar',)
17 CALL_NO_ARGS()
2 LOAD_UNDEFINED()
3 JUMP(2,)
7 JUMP(3,)
4 POP()
5 LOAD_UNDEFINED()
6 RETURN()
18 NOP()
0   <-- this is printed by `print typ` in WITH.eval

And the other one:

14 LOAD_UNDEFINED()
15 LOAD_BOOLEAN(True,)
16 JUMP_IF_FALSE(7,)
17 POP()
18 LOAD(u'bar',)
19 CALL_NO_ARGS()
2 LOAD_UNDEFINED()
3 JUMP(2,)
7 JUMP(3,)
4 POP()
5 LOAD_UNDEFINED()
6 RETURN()
20 JUMP(8,)
2   <-- this is printed by `print typ` in WITH.eval

I think the jump shouldn't be 'outside' in this case, but that's pretty much all sense I could make out of it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions