test262 icon indicating copy to clipboard operation
test262 copied to clipboard

add a test for Generator

Open SkyCrystal opened this issue 3 years ago • 3 comments

Hello! This is my first pull request here. I found a bug in quickjs, and it should fail this test. Hopes that everything goes right.

SkyCrystal avatar Nov 24 '22 11:11 SkyCrystal

Yes there is some different between set property and evaluate code. When generateing bytecode, compiler may parse obj.foo = first and push obj into stack. So after we call return the obj may remains in stack. quickjs throws a InternalError while compiling this code.

SkyCrystal avatar Nov 25 '22 08:11 SkyCrystal

Yes there is some different between set property and evaluate code. When generateing bytecode, compiler may parse obj.foo = first and push obj into stack. So after we call return the obj may remains in stack. quickjs throws a InternalError while compiling this code.

Is that speculation, or a statement of fact? And what would be the relevant difference between obj.foo = yield and unreachable += yield?

gibson042 avatar Nov 25 '22 16:11 gibson042

Is that speculation, or a statement of fact? And what would be the relevant difference between obj.foo = yield and unreachable += yield?

It's a statement of fact in quickjs, and is very easy to reproduce. Just try to compile this function.

When generateing bytecode, compiler may parse obj.foo = first and push obj into stack. So after we call return the obj may remains in stack.

Quickjs works as I said, and generates a wrong bytecode, which fails its check in compute_stack_size.

To get this error, you need a obj.foo = to push obj into stack first, a yield to generate two different branch( The return and the next, and only next really evaulates obj.foo = yield to use the foo in stack.) And at last, a try-finally block is needed, to let these different branch meet with each other.

This is a bytecode generated by quickjs:

error_case.js:2: function: *foo
  stack_size: 4
  opcodes:
;; function* foo() {
;;     try {
;;         test.f= yield 123;
;;     }
;;     finally {
;;             return 1;
;;     }
;; }

        initial_yield
        catch 38
        get_var test                 //push test in stack first
        push_i8 123
        yield
        if_false8 23
        nip                          //even if the set property won't be evaluated.
        gosub 44
        return_async
   23:  put_field f                  //sp[-2].f=sp[-1],sp-=2
        drop
        undefined
        gosub 44
        drop
        goto8 46
   38:  gosub 44
        throw
   44:  push_1 1                     //two branches meet at here.
        return_async
   46:  undefined
        return_async
InternalError: unconsistent stack size: 2 3 (pc=44)

SkyCrystal avatar Nov 28 '22 03:11 SkyCrystal