This commit is contained in:
blueloveTH 2026-01-30 14:40:05 +08:00
parent a59f916f5b
commit cf965a1957
5 changed files with 28 additions and 6 deletions

View File

@ -135,7 +135,7 @@ void FuncDecl__dtor(FuncDecl* self);
typedef struct Function {
FuncDecl_ decl;
py_GlobalRef module; // maybe NULL, weak ref
py_Ref globals; // maybe NULL, strong ref
py_TValue globals; // maybe nil, strong ref
NameDict* closure; // maybe NULL, strong ref
PyObject* clazz; // weak ref; for super()
py_CFunction cfunc; // wrapped C function; for decl-based binding
@ -143,3 +143,8 @@ typedef struct Function {
void Function__ctor(Function* self, FuncDecl_ decl, py_GlobalRef module, py_Ref globals);
void Function__dtor(Function* self);
// https://github.com/pocketpy/pocketpy/issues/456
// Function may be created from `execdyn` and return
// Weakrefs like `.globals` and `.clazz` may invalidate

View File

@ -512,7 +512,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// submit the call
if(!fn->cfunc) {
// python function
VM__push_frame(self, Frame__new(co, p0, fn->module, fn->globals, argv, false));
VM__push_frame(self, Frame__new(co, p0, fn->module, &fn->globals, argv, false));
return opcall ? RES_CALL : VM__run_top_frame(self);
} else {
// decl-based binding
@ -541,7 +541,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// submit the call
if(!fn->cfunc) {
// python function
VM__push_frame(self, Frame__new(co, p0, fn->module, fn->globals, argv, false));
VM__push_frame(self, Frame__new(co, p0, fn->module, &fn->globals, argv, false));
return opcall ? RES_CALL : VM__run_top_frame(self);
} else {
// decl-based binding
@ -557,7 +557,7 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// copy buffer back to stack
self->stack.sp = argv + co->nlocals;
memcpy(argv, self->vectorcall_buffer, co->nlocals * sizeof(py_TValue));
py_Frame* frame = Frame__new(co, p0, fn->module, fn->globals, argv, false);
py_Frame* frame = Frame__new(co, p0, fn->module, &fn->globals, argv, false);
pk_newgenerator(py_retval(), frame, p0, self->stack.sp);
self->stack.sp = p0; // reset the stack
return RES_RETURN;

View File

@ -538,7 +538,7 @@ py_GlobalRef pk_builtins__register() {
void function__gc_mark(void* ud, c11_vector* p_stack) {
Function* func = ud;
if(func->globals) pk__mark_value(func->globals);
pk__mark_value(&func->globals);
if(func->closure) {
NameDict* dict = func->closure;
for(int i = 0; i < dict->capacity; i++) {

View File

@ -143,7 +143,7 @@ void Function__ctor(Function* self, FuncDecl_ decl, py_GlobalRef module, py_Ref
PK_INCREF(decl);
self->decl = decl;
self->module = module;
self->globals = globals;
self->globals = globals != NULL ? *globals : *py_NIL();
self->closure = NULL;
self->clazz = NULL;
self->cfunc = NULL;

17
tests/661_exec_bug.py Normal file
View File

@ -0,0 +1,17 @@
# https://github.com/pocketpy/pocketpy/issues/456
module_code = '''
CONSTANT = 42
def hello(name):
return "Hello, " + name
'''
namespace = {}
exec(module_code, namespace)
assert namespace['CONSTANT'] == 42
assert namespace['hello']('world') == "Hello, world"
# print("Constant:", namespace['CONSTANT'])
# print("Function result:", namespace['hello']('world'))