diff --git a/src/wren_vm.c b/src/wren_vm.c index 4bd4cc97..056b253b 100644 --- a/src/wren_vm.c +++ b/src/wren_vm.c @@ -218,7 +218,7 @@ static Upvalue* captureUpvalue(WrenVM* vm, ObjFiber* fiber, int slot) Upvalue* prevUpvalue = NULL; Upvalue* upvalue = fiber->openUpvalues; - // Walk towards the bottom of the stack until we find a previously existsing + // Walk towards the bottom of the stack until we find a previously existing // upvalue or pass where it should be. while (upvalue != NULL && upvalue->value > local) { @@ -227,7 +227,7 @@ static Upvalue* captureUpvalue(WrenVM* vm, ObjFiber* fiber, int slot) } // Found an existing upvalue for this local. - if (upvalue->value == local) return upvalue; + if (upvalue != NULL && upvalue->value == local) return upvalue; // We've walked past this local on the stack, so there must not be an // upvalue for it already. Make a new one and link it in in the right diff --git a/test/closure/close_over_later_variable.wren b/test/closure/close_over_later_variable.wren new file mode 100644 index 00000000..0d3f977a --- /dev/null +++ b/test/closure/close_over_later_variable.wren @@ -0,0 +1,13 @@ +// This is a regression test. There was a bug where if an upvalue for an +// earlier local (here "a") was captured *after* a later one ("b"), then Wren +// would crash because it walked to the end of the upvalue list (correct), but +// then didn't handle not finding the variable. + +new Fn { + var a = "a" + var b = "b" + new Fn { + IO.print(b) // expect: b + IO.print(a) // expect: a + }.call +}.call